2 /* Copyright Gerhard Rieger 2003-2008 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
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! */
9 #include "xioconfig.h" /* what features are enabled */
11 #include "sysincludes.h"
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
);
35 int fdname(const char *file
, int fd
, FILE *outfile
, const char *numform
) {
36 struct stat buf
= {0};
38 Debug1("checking file descriptor %u", fd
);
40 if (Fstat(fd
, &buf
) < 0) {
42 Debug2("fstat(%d): %s", fd
, strerror(errno
));
45 Error2("fstat(%d): %s", fd
, strerror(errno
));
48 filetype
= (buf
.st_mode
&S_IFMT
)>>12;
49 if (numform
!= NULL
) {
50 fprintf(outfile
, numform
, fd
);
52 return statname(file
, fd
, filetype
, outfile
);
54 if (Stat(file
, &buf
) < 0) {
55 Error2("stat(\"%s\"): %s", file
, strerror(errno
));
57 filetype
= (buf
.st_mode
&S_IFMT
)>>12;
58 return statname(file
, -1, filetype
, outfile
);
63 static int procgetfdname(int fd
, char *filepath
, size_t pathsize
) {
64 static pid_t pid
= -1;
65 char procpath
[PATH_MAX
];
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 */
73 if (Stat64("/proc", &buf
) < 0) {
76 if (!S_ISDIR(buf
.st_mode
)) {
80 #else /* !HAVE_STAT64 */
83 if (Stat("/proc", &buf
) < 0) {
86 if (!S_ISDIR(buf
.st_mode
)) {
90 #endif /* !HAVE_STAT64 */
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
));
102 #endif /* HAVE_PROC_DIR_FD */
104 int statname(const char *file
, int fd
, int filetype
, FILE *outfile
) {
105 char filepath
[PATH_MAX
];
111 procgetfdname(fd
, filepath
, sizeof(filepath
));
112 if (filepath
[0] == '/') {
116 #endif /* HAVE_PROC_DIR_FD */
117 /* now see for type specific infos */
119 case (S_IFIFO
>>12): /* 1, FIFO */
120 fputs("pipe", outfile
);
121 if (file
) fprintf(outfile
, " %s", file
);
123 case (S_IFCHR
>>12): /* 2, character device */
124 if (cdevname(fd
, outfile
) == 0) {
125 if (file
) fprintf(outfile
, " %s", file
);
128 case (S_IFDIR
>>12): /* 4, directory */
129 fputs("dir", outfile
);
130 if (file
) fprintf(outfile
, " %s", file
);
132 case (S_IFBLK
>>12): /* 6, block device */
133 fputs("blkdev", outfile
);
134 if (file
) fprintf(outfile
, " %s", file
);
136 case (S_IFREG
>>12): /* 8, regular file */
137 fputs("file", outfile
);
138 if (file
) fprintf(outfile
, " %s", file
);
140 case (S_IFLNK
>>12): /* 10, symbolic link */
141 fputs("link", outfile
);
142 if (file
) fprintf(outfile
, " %s", file
);
144 case (S_IFSOCK
>>12): /* 12, socket */
147 result
= sockname(fd
, outfile
);
149 fprintf(outfile
, "socket %s", file
);
151 fputs("socket", outfile
);
154 Error("SOCKET support not compiled in");
156 #endif /* !_WITH_SOCKET */
160 fputc('\n', outfile
);
166 /* character device analysis */
167 /* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
168 int cdevname(int fd
, FILE *outfile
) {
171 if ((ret
= Isatty(fd
)) < 0) {
172 Error2("isatty(%d): %s", fd
, strerror(errno
));
178 fputs("tty", outfile
);
179 if ((name
= Ttyname(fd
)) != NULL
) {
181 fputs(name
, outfile
);
185 fputs("chrdev", outfile
);
192 int sockname(int fd
, FILE *outfile
) {
193 #define FDNAME_OPTLEN 256
194 #define FDNAME_NAMELEN 256
201 char namebuff
[FDNAME_NAMELEN
];
202 char peerbuff
[FDNAME_NAMELEN
];
203 /* in Linux these optcodes are 'enum', but on AIX they are bits! */
204 union sockaddr_union sockname
, peername
; /* the longest I know of */
206 #if 0 && defined(SIOCGIFNAME)
207 /*Linux struct ifreq ifc = {{{ 0 }}};*/
208 struct ifreq ifc
= {{ 0 }};
211 optlen
= FDNAME_OPTLEN
;
213 Getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &opttype
, &optlen
);
215 Getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &optacceptconn
, &optlen
);
218 namelen
= sizeof(sockname
);
219 result
= Getsockname(fd
, &sockname
.soa
, &namelen
);
221 Error2("getsockname(%d): %s", fd
, strerror(errno
));
225 namelen
= sizeof(peername
);
226 result
= Getpeername(fd
, (struct sockaddr
*)&peername
, &namelen
);
228 Error2("getpeername(%d): %s", fd
, strerror(errno
));
231 switch (sockname
.soa
.sa_family
) {
234 fprintf(outfile
, "unix%s%s %s",
235 opttype
==SOCK_DGRAM
?"datagram":"",
237 optacceptconn
?"(listening)":
240 sockaddr_unix_info(&sockname
.un
, namelen
,
241 namebuff
, sizeof(namebuff
)));
249 fprintf(outfile
, "tcp%s %s %s",
251 optacceptconn
?"(listening)":
254 sockaddr_inet4_info(&sockname
.ip4
,
255 namebuff
, sizeof(namebuff
)),
256 sockaddr_inet4_info(&peername
.ip4
,
257 peerbuff
, sizeof(peerbuff
)));
262 fprintf(outfile
, "udp%s %s %s",
264 optacceptconn
?"(listening)":
267 sockaddr_inet4_info(&sockname
.ip4
,
268 namebuff
, sizeof(namebuff
)),
269 sockaddr_inet4_info(&peername
.ip4
,
270 peerbuff
, sizeof(peerbuff
)));
274 fprintf(outfile
, "ip %s",
275 sockaddr_inet4_info(&sockname
.ip4
,
276 namebuff
, sizeof(namebuff
)));
280 #endif /* WITH_IP4 */
287 fprintf(outfile
, "tcp6%s %s %s",
289 optacceptconn
?"(listening)":
292 sockaddr_inet6_info(&sockname
.ip6
,
293 namebuff
, sizeof(namebuff
)),
294 sockaddr_inet6_info(&peername
.ip6
,
295 peerbuff
, sizeof(peerbuff
)));
300 fprintf(outfile
, "udp6%s %s %s",
302 optacceptconn
?"(listening)":
305 sockaddr_inet6_info(&sockname
.ip6
,
306 namebuff
, sizeof(namebuff
)),
307 sockaddr_inet6_info(&peername
.ip6
,
308 peerbuff
, sizeof(peerbuff
)));
312 fprintf(outfile
, "ip6 %s",
313 sockaddr_inet6_info(&sockname
.ip6
,
314 namebuff
, sizeof(namebuff
)));
317 #endif /* WITH_IP6 */
319 fputs("socket", outfile
);
324 #undef FDNAME_NAMELEN
326 #endif /* _WITH_SOCKET */