nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* source: fdname.c */ |
2 | /* Copyright Gerhard Rieger */ |
||
3 | /* Published under the GNU General Public License V.2, see file COPYING */ |
||
4 | |||
5 | /* the subroutine sockname prints the basic info about the address of a socket |
||
6 | NOTE: it works on UNIX (kernel) file descriptors, not on libc files! */ |
||
7 | |||
8 | #include "config.h" |
||
9 | #include "xioconfig.h" /* what features are enabled */ |
||
10 | |||
11 | #include "sysincludes.h" |
||
12 | |||
13 | #include "mytypes.h" |
||
14 | #include "compat.h" |
||
15 | #include "error.h" |
||
16 | #include "sycls.h" |
||
17 | #include "sysutils.h" |
||
18 | |||
19 | #include "filan.h" |
||
20 | |||
21 | |||
22 | struct sockopt { |
||
23 | int so; |
||
24 | char *name; |
||
25 | }; |
||
26 | |||
27 | |||
28 | int statname(const char *file, int fd, int filetype, FILE *outfile); |
||
29 | int cdevname(int fd, FILE *outfile); |
||
30 | int sockname(int fd, FILE *outfile); |
||
31 | int unixame(int fd, FILE *outfile); |
||
32 | int tcpname(int fd, FILE *outfile); |
||
33 | |||
34 | |||
35 | int fdname(const char *file, int fd, FILE *outfile, const char *numform) { |
||
36 | struct stat buf = {0}; |
||
37 | int filetype; |
||
38 | Debug1("checking file descriptor %u", fd); |
||
39 | if (fd >= 0) { |
||
40 | if (Fstat(fd, &buf) < 0) { |
||
41 | if (errno == EBADF) { |
||
42 | Debug2("fstat(%d): %s", fd, strerror(errno)); |
||
43 | return -1; |
||
44 | } else { |
||
45 | Error2("fstat(%d): %s", fd, strerror(errno)); |
||
46 | } |
||
47 | } |
||
48 | filetype = (buf.st_mode&S_IFMT)>>12; |
||
49 | if (numform != NULL) { |
||
50 | fprintf(outfile, numform, fd); |
||
51 | } |
||
52 | return statname(file, fd, filetype, outfile); |
||
53 | } else { |
||
54 | if (Stat(file, &buf) < 0) { |
||
55 | Error2("stat(\"%s\"): %s", file, strerror(errno)); |
||
56 | } |
||
57 | filetype = (buf.st_mode&S_IFMT)>>12; |
||
58 | return statname(file, -1, filetype, outfile); |
||
59 | } |
||
60 | } |
||
61 | |||
62 | #if HAVE_PROC_DIR_FD |
||
63 | static int procgetfdname(int fd, char *filepath, size_t pathsize) { |
||
64 | static pid_t pid = -1; |
||
65 | char procpath[PATH_MAX]; |
||
66 | int len; |
||
67 | |||
68 | /* even if configure has shown that we have /proc, we must check if it |
||
69 | exists at runtime, because we might be in a chroot environment */ |
||
70 | #if HAVE_STAT64 |
||
71 | { |
||
72 | struct stat64 buf; |
||
73 | if (Stat64("/proc", &buf) < 0) { |
||
74 | return -1; |
||
75 | } |
||
76 | if (!S_ISDIR(buf.st_mode)) { |
||
77 | return -1; |
||
78 | } |
||
79 | } |
||
80 | #else /* !HAVE_STAT64 */ |
||
81 | { |
||
82 | struct stat buf; |
||
83 | if (Stat("/proc", &buf) < 0) { |
||
84 | return -1; |
||
85 | } |
||
86 | if (!S_ISDIR(buf.st_mode)) { |
||
87 | return -1; |
||
88 | } |
||
89 | } |
||
90 | #endif /* !HAVE_STAT64 */ |
||
91 | |||
92 | if (pid < 0) pid = Getpid(); |
||
93 | snprintf(procpath, sizeof(procpath), "/proc/"F_pid"/fd/%d", pid, fd); |
||
94 | if ((len = Readlink(procpath, filepath, pathsize-1)) < 0) { |
||
95 | Error4("readlink(\"%s\", %p, "F_Zu"): %s", |
||
96 | procpath, filepath, pathsize, strerror(errno)); |
||
97 | return -1; |
||
98 | } |
||
99 | filepath[len] = '\0'; |
||
100 | return 0; |
||
101 | } |
||
102 | #endif /* HAVE_PROC_DIR_FD */ |
||
103 | |||
104 | int statname(const char *file, int fd, int filetype, FILE *outfile) { |
||
105 | char filepath[PATH_MAX]; |
||
106 | |||
107 | filepath[0] = '\0'; |
||
108 | #if HAVE_PROC_DIR_FD |
||
109 | if (fd >= 0) { |
||
110 | procgetfdname(fd, filepath, sizeof(filepath)); |
||
111 | if (filepath[0] == '/') { |
||
112 | file = filepath; |
||
113 | } |
||
114 | } |
||
115 | #endif /* HAVE_PROC_DIR_FD */ |
||
116 | /* now see for type specific infos */ |
||
117 | switch (filetype) { |
||
118 | case (S_IFIFO>>12): /* 1, FIFO */ |
||
119 | fputs("pipe", outfile); |
||
120 | if (file) fprintf(outfile, " %s", file); |
||
121 | break; |
||
122 | case (S_IFCHR>>12): /* 2, character device */ |
||
123 | if (cdevname(fd, outfile) == 0) { |
||
124 | if (file) fprintf(outfile, " %s", file); |
||
125 | } |
||
126 | break; |
||
127 | case (S_IFDIR>>12): /* 4, directory */ |
||
128 | fputs("dir", outfile); |
||
129 | if (file) fprintf(outfile, " %s", file); |
||
130 | break; |
||
131 | case (S_IFBLK>>12): /* 6, block device */ |
||
132 | fputs("blkdev", outfile); |
||
133 | if (file) fprintf(outfile, " %s", file); |
||
134 | break; |
||
135 | case (S_IFREG>>12): /* 8, regular file */ |
||
136 | fputs("file", outfile); |
||
137 | if (file) fprintf(outfile, " %s", file); |
||
138 | break; |
||
139 | case (S_IFLNK>>12): /* 10, symbolic link */ |
||
140 | fputs("link", outfile); |
||
141 | if (file) fprintf(outfile, " %s", file); |
||
142 | break; |
||
143 | case (S_IFSOCK>>12): /* 12, socket */ |
||
144 | #if _WITH_SOCKET |
||
145 | if (fd >= 0) { |
||
146 | sockname(fd, outfile); |
||
147 | } else if (file) { |
||
148 | fprintf(outfile, "socket %s", file); |
||
149 | } else { |
||
150 | fputs("socket", outfile); |
||
151 | } |
||
152 | #else |
||
153 | Error("SOCKET support not compiled in"); |
||
154 | return -1; |
||
155 | #endif /* !_WITH_SOCKET */ |
||
156 | break; |
||
157 | } |
||
158 | /* ioctl() */ |
||
159 | fputc('\n', outfile); |
||
160 | |||
161 | return 0; |
||
162 | } |
||
163 | |||
164 | |||
165 | /* character device analysis */ |
||
166 | /* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */ |
||
167 | int cdevname(int fd, FILE *outfile) { |
||
168 | int ret; |
||
169 | |||
170 | if ((ret = Isatty(fd)) < 0) { |
||
171 | Error2("isatty(%d): %s", fd, strerror(errno)); |
||
172 | return -1; |
||
173 | } |
||
174 | if (ret > 0) { |
||
175 | char *name; |
||
176 | |||
177 | fputs("tty", outfile); |
||
178 | if ((name = Ttyname(fd)) != NULL) { |
||
179 | fputc(' ', outfile); |
||
180 | fputs(name, outfile); |
||
181 | return 1; |
||
182 | } |
||
183 | } else { |
||
184 | fputs("chrdev", outfile); |
||
185 | } |
||
186 | return 0; |
||
187 | } |
||
188 | |||
189 | |||
190 | #if _WITH_SOCKET |
||
191 | int sockname(int fd, FILE *outfile) { |
||
192 | #define FDNAME_OPTLEN 256 |
||
193 | #define FDNAME_NAMELEN 256 |
||
194 | socklen_t optlen; |
||
195 | int opttype; |
||
196 | #ifdef SO_ACCEPTCONN |
||
197 | int optacceptconn; |
||
198 | #endif |
||
199 | int result /*0, i*/; |
||
200 | char namebuff[FDNAME_NAMELEN]; |
||
201 | char peerbuff[FDNAME_NAMELEN]; |
||
202 | /* in Linux these optcodes are 'enum', but on AIX they are bits! */ |
||
203 | union sockaddr_union sockname, peername; /* the longest I know of */ |
||
204 | socklen_t namelen; |
||
205 | #if 0 && defined(SIOCGIFNAME) |
||
206 | /*Linux struct ifreq ifc = {{{ 0 }}};*/ |
||
207 | struct ifreq ifc = {{ 0 }}; |
||
208 | #endif |
||
209 | |||
210 | optlen = FDNAME_OPTLEN; |
||
211 | |||
212 | Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen); |
||
213 | #ifdef SO_ACCEPTCONN |
||
214 | Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen); |
||
215 | #endif |
||
216 | |||
217 | namelen = sizeof(sockname); |
||
218 | result = Getsockname(fd, &sockname.soa, &namelen); |
||
219 | if (result < 0) { |
||
220 | Error2("getsockname(%d): %s", fd, strerror(errno)); |
||
221 | return -1; |
||
222 | } |
||
223 | |||
224 | namelen = sizeof(peername); |
||
225 | result = Getpeername(fd, (struct sockaddr *)&peername, &namelen); |
||
226 | if (result < 0) { |
||
227 | Error2("getpeername(%d): %s", fd, strerror(errno)); |
||
228 | } |
||
229 | |||
230 | switch (sockname.soa.sa_family) { |
||
231 | #if WITH_UNIX |
||
232 | case AF_UNIX: |
||
233 | fprintf(outfile, "unix%s%s %s", |
||
234 | opttype==SOCK_DGRAM?"datagram":"", |
||
235 | #ifdef SO_ACCEPTCONN |
||
236 | optacceptconn?"(listening)": |
||
237 | #endif |
||
238 | "", |
||
239 | sockaddr_unix_info(&sockname.un, namelen, |
||
240 | namebuff, sizeof(namebuff))); |
||
241 | break; |
||
242 | #endif |
||
243 | #if WITH_IP4 |
||
244 | case AF_INET: |
||
245 | switch (opttype) { |
||
246 | #if WITH_TCP |
||
247 | case SOCK_STREAM: |
||
248 | fprintf(outfile, "tcp%s %s %s", |
||
249 | #ifdef SO_ACCEPTCONN |
||
250 | optacceptconn?"(listening)": |
||
251 | #endif |
||
252 | "", |
||
253 | sockaddr_inet4_info(&sockname.ip4, |
||
254 | namebuff, sizeof(namebuff)), |
||
255 | sockaddr_inet4_info(&peername.ip4, |
||
256 | peerbuff, sizeof(peerbuff))); |
||
257 | break; |
||
258 | #endif |
||
259 | #if WITH_UDP |
||
260 | case SOCK_DGRAM: |
||
261 | fprintf(outfile, "udp%s %s %s", |
||
262 | #ifdef SO_ACCEPTCONN |
||
263 | optacceptconn?"(listening)": |
||
264 | #endif |
||
265 | "", |
||
266 | sockaddr_inet4_info(&sockname.ip4, |
||
267 | namebuff, sizeof(namebuff)), |
||
268 | sockaddr_inet4_info(&peername.ip4, |
||
269 | peerbuff, sizeof(peerbuff))); |
||
270 | break; |
||
271 | #endif |
||
272 | default: |
||
273 | fprintf(outfile, "ip %s", |
||
274 | sockaddr_inet4_info(&sockname.ip4, |
||
275 | namebuff, sizeof(namebuff))); |
||
276 | break; |
||
277 | } |
||
278 | break; |
||
279 | #endif /* WITH_IP4 */ |
||
280 | |||
281 | #if WITH_IP6 |
||
282 | case AF_INET6: |
||
283 | switch (opttype) { |
||
284 | #if WITH_TCP |
||
285 | case SOCK_STREAM: |
||
286 | fprintf(outfile, "tcp6%s %s %s", |
||
287 | #ifdef SO_ACCEPTCONN |
||
288 | optacceptconn?"(listening)": |
||
289 | #endif |
||
290 | "", |
||
291 | sockaddr_inet6_info(&sockname.ip6, |
||
292 | namebuff, sizeof(namebuff)), |
||
293 | sockaddr_inet6_info(&peername.ip6, |
||
294 | peerbuff, sizeof(peerbuff))); |
||
295 | break; |
||
296 | #endif |
||
297 | #if WITH_UDP |
||
298 | case SOCK_DGRAM: |
||
299 | fprintf(outfile, "udp6%s %s %s", |
||
300 | #ifdef SO_ACCEPTCONN |
||
301 | optacceptconn?"(listening)": |
||
302 | #endif |
||
303 | "", |
||
304 | sockaddr_inet6_info(&sockname.ip6, |
||
305 | namebuff, sizeof(namebuff)), |
||
306 | sockaddr_inet6_info(&peername.ip6, |
||
307 | peerbuff, sizeof(peerbuff))); |
||
308 | break; |
||
309 | #endif |
||
310 | default: |
||
311 | fprintf(outfile, "ip6 %s", |
||
312 | sockaddr_inet6_info(&sockname.ip6, |
||
313 | namebuff, sizeof(namebuff))); |
||
314 | break; |
||
315 | } |
||
316 | #endif /* WITH_IP6 */ |
||
317 | default: |
||
318 | fputs("socket", outfile); |
||
319 | } |
||
320 | |||
321 | return result; |
||
322 | #undef FDNAME_OPTLEN |
||
323 | #undef FDNAME_NAMELEN |
||
324 | } |
||
325 | #endif /* _WITH_SOCKET */ |
||
326 | |||
327 | |||
328 | |||
329 |