2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
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
];
110 procgetfdname(fd
, filepath
, sizeof(filepath
));
111 if (filepath
[0] == '/') {
115 #endif /* HAVE_PROC_DIR_FD */
116 /* now see for type specific infos */
118 case (S_IFIFO
>>12): /* 1, FIFO */
119 fputs("pipe", outfile
);
120 if (file
) fprintf(outfile
, " %s", file
);
122 case (S_IFCHR
>>12): /* 2, character device */
123 if (cdevname(fd
, outfile
) == 0) {
124 if (file
) fprintf(outfile
, " %s", file
);
127 case (S_IFDIR
>>12): /* 4, directory */
128 fputs("dir", outfile
);
129 if (file
) fprintf(outfile
, " %s", file
);
131 case (S_IFBLK
>>12): /* 6, block device */
132 fputs("blkdev", outfile
);
133 if (file
) fprintf(outfile
, " %s", file
);
135 case (S_IFREG
>>12): /* 8, regular file */
136 fputs("file", outfile
);
137 if (file
) fprintf(outfile
, " %s", file
);
139 case (S_IFLNK
>>12): /* 10, symbolic link */
140 fputs("link", outfile
);
141 if (file
) fprintf(outfile
, " %s", file
);
143 case (S_IFSOCK
>>12): /* 12, socket */
146 sockname(fd
, outfile
);
148 fprintf(outfile
, "socket %s", file
);
150 fputs("socket", outfile
);
153 Error("SOCKET support not compiled in");
155 #endif /* !_WITH_SOCKET */
159 fputc('\n', outfile
);
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
) {
170 if ((ret
= Isatty(fd
)) < 0) {
171 Error2("isatty(%d): %s", fd
, strerror(errno
));
177 fputs("tty", outfile
);
178 if ((name
= Ttyname(fd
)) != NULL
) {
180 fputs(name
, outfile
);
184 fputs("chrdev", outfile
);
191 int sockname(int fd
, FILE *outfile
) {
192 #define FDNAME_OPTLEN 256
193 #define FDNAME_NAMELEN 256
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 */
205 #if 0 && defined(SIOCGIFNAME)
206 /*Linux struct ifreq ifc = {{{ 0 }}};*/
207 struct ifreq ifc
= {{ 0 }};
210 optlen
= FDNAME_OPTLEN
;
212 Getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &opttype
, &optlen
);
214 Getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &optacceptconn
, &optlen
);
217 namelen
= sizeof(sockname
);
218 result
= Getsockname(fd
, &sockname
.soa
, &namelen
);
220 Error2("getsockname(%d): %s", fd
, strerror(errno
));
224 namelen
= sizeof(peername
);
225 result
= Getpeername(fd
, (struct sockaddr
*)&peername
, &namelen
);
227 Error2("getpeername(%d): %s", fd
, strerror(errno
));
230 switch (sockname
.soa
.sa_family
) {
233 fprintf(outfile
, "unix%s%s %s",
234 opttype
==SOCK_DGRAM
?"datagram":"",
236 optacceptconn
?"(listening)":
239 sockaddr_unix_info(&sockname
.un
, namelen
,
240 namebuff
, sizeof(namebuff
)));
248 fprintf(outfile
, "tcp%s %s %s",
250 optacceptconn
?"(listening)":
253 sockaddr_inet4_info(&sockname
.ip4
,
254 namebuff
, sizeof(namebuff
)),
255 sockaddr_inet4_info(&peername
.ip4
,
256 peerbuff
, sizeof(peerbuff
)));
261 fprintf(outfile
, "udp%s %s %s",
263 optacceptconn
?"(listening)":
266 sockaddr_inet4_info(&sockname
.ip4
,
267 namebuff
, sizeof(namebuff
)),
268 sockaddr_inet4_info(&peername
.ip4
,
269 peerbuff
, sizeof(peerbuff
)));
273 fprintf(outfile
, "ip %s",
274 sockaddr_inet4_info(&sockname
.ip4
,
275 namebuff
, sizeof(namebuff
)));
279 #endif /* WITH_IP4 */
286 fprintf(outfile
, "tcp6%s %s %s",
288 optacceptconn
?"(listening)":
291 sockaddr_inet6_info(&sockname
.ip6
,
292 namebuff
, sizeof(namebuff
)),
293 sockaddr_inet6_info(&peername
.ip6
,
294 peerbuff
, sizeof(peerbuff
)));
299 fprintf(outfile
, "udp6%s %s %s",
301 optacceptconn
?"(listening)":
304 sockaddr_inet6_info(&sockname
.ip6
,
305 namebuff
, sizeof(namebuff
)),
306 sockaddr_inet6_info(&peername
.ip6
,
307 peerbuff
, sizeof(peerbuff
)));
311 fprintf(outfile
, "ip6 %s",
312 sockaddr_inet6_info(&sockname
.ip6
,
313 namebuff
, sizeof(namebuff
)));
316 #endif /* WITH_IP6 */
318 fputs("socket", outfile
);
323 #undef FDNAME_NAMELEN
325 #endif /* _WITH_SOCKET */