nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
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