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
, char style
);
29 int cdevname(int fd
, FILE *outfile
);
30 int sockname(int fd
, FILE *outfile
, char style
);
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
,
37 struct stat buf
= {0};
39 Debug1("checking file descriptor %u", fd
);
41 if (Fstat(fd
, &buf
) < 0) {
43 Debug2("fstat(%d): %s", fd
, strerror(errno
));
46 Error2("fstat(%d): %s", fd
, strerror(errno
));
49 filetype
= (buf
.st_mode
&S_IFMT
)>>12;
50 if (numform
!= NULL
) {
51 fprintf(outfile
, numform
, fd
);
53 return statname(file
, fd
, filetype
, outfile
, style
);
55 if (Stat(file
, &buf
) < 0) {
56 Error2("stat(\"%s\"): %s", file
, strerror(errno
));
58 filetype
= (buf
.st_mode
&S_IFMT
)>>12;
59 return statname(file
, -1, filetype
, outfile
, style
);
63 #if HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH
64 static int procgetfdname(int fd
, char *filepath
, size_t pathsize
) {
65 static pid_t pid
= -1;
66 char procpath
[PATH_MAX
];
69 /* even if configure has shown that we have /proc, we must check if it
70 exists at runtime, because we might be in a chroot environment */
74 if (Stat64("/proc", &buf
) < 0) {
77 if (!S_ISDIR(buf
.st_mode
)) {
81 #else /* !HAVE_STAT64 */
84 if (Stat("/proc", &buf
) < 0) {
87 if (!S_ISDIR(buf
.st_mode
)) {
91 #endif /* !HAVE_STAT64 */
93 if (pid
< 0) pid
= Getpid();
94 snprintf(procpath
, sizeof(procpath
), "/proc/"F_pid
"/"
95 #if HAVE_PROC_DIR_PATH
101 if ((len
= Readlink(procpath
, filepath
, pathsize
-1)) < 0) {
102 Notice4("readlink(\"%s\", %p, "F_Zu
"): %s",
103 procpath
, filepath
, pathsize
, strerror(errno
));
106 filepath
[len
] = '\0';
109 #endif /* HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH */
111 int statname(const char *file
, int fd
, int filetype
, FILE *outfile
,
113 char filepath
[PATH_MAX
];
116 #if HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH
118 procgetfdname(fd
, filepath
, sizeof(filepath
));
119 if (filepath
[0] == '/') {
123 #endif /* HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH */
124 /* now see for type specific infos */
126 case (S_IFIFO
>>12): /* 1, FIFO */
127 fputs("pipe", outfile
);
128 if (file
) fprintf(outfile
, " %s", file
);
130 case (S_IFCHR
>>12): /* 2, character device */
131 if (cdevname(fd
, outfile
) == 0) {
132 if (file
) fprintf(outfile
, " %s", file
);
135 case (S_IFDIR
>>12): /* 4, directory */
136 fputs("dir", outfile
);
137 if (file
) fprintf(outfile
, " %s", file
);
139 case (S_IFBLK
>>12): /* 6, block device */
140 fputs("blkdev", outfile
);
141 if (file
) fprintf(outfile
, " %s", file
);
143 case (S_IFREG
>>12): /* 8, regular file */
144 fputs("file", outfile
);
145 if (file
) fprintf(outfile
, " %s", file
);
147 case (S_IFLNK
>>12): /* 10, symbolic link */
148 fputs("link", outfile
);
149 if (file
) fprintf(outfile
, " %s", file
);
151 case (S_IFSOCK
>>12): /* 12, socket */
154 sockname(fd
, outfile
, style
);
156 fprintf(outfile
, "socket %s", file
);
158 fputs("socket", outfile
);
161 Error("SOCKET support not compiled in");
163 #endif /* !_WITH_SOCKET */
166 case (S_IFDOOR
>>12): /* 13, door (Solaris) */
167 fputs("door", outfile
);
168 if (file
) fprintf(outfile
, " %s", file
);
170 #endif /* HAVE_MACRO_S_IFDOOR */
172 case (S_IFPORT
>>12): /* 14, event port (Solaris) */
173 fputs("event_port", outfile
);
174 if (file
) fprintf(outfile
, " %s", file
);
176 #endif /* HAVE_MACRO_S_IFPORT */
179 fputc('\n', outfile
);
185 /* character device analysis */
186 /* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
187 int cdevname(int fd
, FILE *outfile
) {
190 if ((ret
= Isatty(fd
)) < 0) {
191 Error2("isatty(%d): %s", fd
, strerror(errno
));
197 fputs("tty", outfile
);
198 if ((name
= Ttyname(fd
)) != NULL
) {
200 fputs(name
, outfile
);
204 fputs("chrdev", outfile
);
209 int sockettype(int socktype
, char *typename
, size_t typenamemax
) {
211 case SOCK_STREAM
: strncpy(typename
, "stream", typenamemax
); break;
212 case SOCK_DGRAM
: strncpy(typename
, "dgram", typenamemax
); break;
213 case SOCK_SEQPACKET
: strncpy(typename
, "seqpacket", typenamemax
); break;
214 case SOCK_RAW
: strncpy(typename
, "raw", typenamemax
); break;
215 case SOCK_RDM
: strncpy(typename
, "rdm", typenamemax
); break;
217 case SOCK_PACKET
: strncpy(typename
, "packet", typenamemax
); break;
219 default: snprintf(typename
, typenamemax
, "socktype%u", socktype
); break;
225 int sockname(int fd
, FILE *outfile
, char style
) {
226 #define FDNAME_OPTLEN 256
227 #define FDNAME_NAMELEN 256
229 #if HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R
230 struct protoent protoent
, *protoentp
;
232 #define PROTONAMEMAX 1024
233 char protoname
[PROTONAMEMAX
] = "";
234 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
239 int optacceptconn
= 0; /* OpenBSD does not give value on unix dgram */
242 char socknamebuff
[FDNAME_NAMELEN
];
243 char peernamebuff
[FDNAME_NAMELEN
];
244 /* in Linux these optcodes are 'enum', but on AIX they are bits! */
245 union sockaddr_union sockname
, peername
; /* the longest I know of */
246 socklen_t socknamelen
, peernamelen
;
247 # define TYPENAMEMAX 16
248 char typename
[TYPENAMEMAX
];
249 #if 0 && defined(SIOCGIFNAME)
250 /*Linux struct ifreq ifc = {{{ 0 }}};*/
251 struct ifreq ifc
= {{ 0 }};
255 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
256 optlen
= sizeof(proto
);
258 rc
= Getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &proto
, &optlen
);
259 #elif defined(SO_PROTOTYPE)
260 rc
= Getsockopt(fd
, SOL_SOCKET
, SO_PROTOTYPE
, &proto
, &optlen
);
263 Notice5("getsocktop(%d, SOL_SOCKET, "
269 ", &%p, {"F_socklen
"}): errno=%d (%s)", fd
, &proto
, optlen
, errno
, strerror(errno
));
271 #endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */
272 optlen
= sizeof(opttype
);
273 Getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &opttype
, &optlen
);
274 sockettype(opttype
, typename
, sizeof(typename
));
276 optlen
= sizeof(optacceptconn
);
278 Getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &optacceptconn
, &optlen
);
281 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
282 #if HAVE_GETPROTOBYNUMBER_R==1 /* Linux */
283 rc
= getprotobynumber_r(proto
, &protoent
, protoname
, sizeof(protoname
), &protoentp
);
284 if (protoentp
== NULL
) {
285 Warn2("sockname(): getprotobynumber_r(proto=%d, ...): %s",
286 proto
, strerror(rc
));
288 strncpy(protoname
, protoentp
->p_name
, sizeof(protoname
));
289 #elif HAVE_GETPROTOBYNUMBER_R==2 /* Solaris */
291 # define FILAN_GETPROTOBYNUMBER_R_BUFLEN 1024
292 char buffer
[FILAN_GETPROTOBYNUMBER_R_BUFLEN
];
293 protoentp
= getprotobynumber_r(proto
, &protoent
, buffer
, FILAN_GETPROTOBYNUMBER_R_BUFLEN
);
294 strncpy(protoname
, protoentp
->p_name
, sizeof(protoname
));
296 #elif HAVE_GETPROTOBYNUMBER_R==3 /* AIX, OpenBSD */
298 struct protoent_data proto_data
= { 0 }; /* OpenBSD might SIGSEGV */
299 rc
= getprotobynumber_r(proto
, &protoent
, &proto_data
);
301 strncpy(protoname
, protoent
.p_name
, sizeof(protoname
));
302 endprotoent_r(&proto_data
);
307 case IPPROTO_TCP
: strcpy(protoname
, "tcp"); break;
308 case IPPROTO_UDP
: strcpy(protoname
, "udp"); break;
309 case IPPROTO_SCTP
: strcpy(protoname
, "sctp"); break;
310 default: sprintf(protoname
, "proto%d", proto
); break;
313 #else /* ! (defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)) */
314 if (opttype
== SOCK_STREAM
) {
315 strcpy(protoname
, "(stream)");
316 } else if (opttype
== SOCK_DGRAM
) {
317 strcpy(protoname
, "(dgram)");
319 } else if (opttype
== SOCK_RAW
) {
320 strcpy(protoname
, "(raw)");
323 } else if (opttype
== SOCK_RDM
) {
324 strcpy(protoname
, "(rdm)");
326 #ifdef SOCK_SEQPACKET
327 } else if (opttype
== SOCK_SEQPACKET
) {
328 strcpy(protoname
, "(seqpacket)");
331 } else if (opttype
== SOCK_DCCP
) {
332 strcpy(protoname
, "(dccp)");
335 } else if (opttype
== SOCK_PACKET
) {
336 strcpy(protoname
, "(packet)");
339 strcpy(protoname
, "socket");
341 #endif /* ! (defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)) */
342 socknamelen
= sizeof(sockname
);
343 result
= Getsockname(fd
, &sockname
.soa
, &socknamelen
);
345 Error2("getsockname(%d): %s", fd
, strerror(errno
));
349 peernamelen
= sizeof(peername
);
350 result
= Getpeername(fd
, (struct sockaddr
*)&peername
, &peernamelen
);
352 Warn2("getpeername(%d): %s", fd
, strerror(errno
));
355 switch (sockname
.soa
.sa_family
) {
360 fprintf(outfile
, "unix%s%s %s",
361 opttype
==SOCK_DGRAM
?"datagram":"",
363 optacceptconn
?"(listening)":
366 sockaddr_unix_info(&sockname
.un
, socknamelen
,
367 socknamebuff
, sizeof(socknamebuff
)));
370 /* sockettype(opttype, typename, TYPENAMEMAX); */
371 fprintf(outfile
, "unix %s-%s %s %s",
372 sockaddr_unix_info(&sockname
.un
, socknamelen
,
373 socknamebuff
, sizeof(socknamebuff
)),
374 sockaddr_unix_info(&peername
.un
, peernamelen
,
375 peernamebuff
, sizeof(peernamebuff
)),
378 optacceptconn
?"(listening)":
384 #endif /* WITH_UNIX */
392 fprintf(outfile
, "%s%s %s %s",
395 optacceptconn
?"(listening)":
398 sockaddr_inet4_info(&sockname
.ip4
,
399 socknamebuff
, sizeof(socknamebuff
)),
400 sockaddr_inet4_info(&peername
.ip4
,
401 peernamebuff
, sizeof(peernamebuff
)));
406 fprintf(outfile
, "%s%s %s %s",
409 optacceptconn
?"(listening)":
412 sockaddr_inet4_info(&sockname
.ip4
,
413 socknamebuff
, sizeof(socknamebuff
)),
414 sockaddr_inet4_info(&peername
.ip4
,
415 peernamebuff
, sizeof(peernamebuff
)));
419 fprintf(outfile
, "ip %s",
420 sockaddr_inet4_info(&sockname
.ip4
,
421 socknamebuff
, sizeof(socknamebuff
)));
426 fprintf(outfile
, "%s %s-%s (%s) %s",
428 sockaddr_inet4_info(&sockname
.ip4
,
429 socknamebuff
, sizeof(socknamebuff
)),
430 sockaddr_inet4_info(&peername
.ip4
,
431 peernamebuff
, sizeof(peernamebuff
)),
434 optacceptconn
?"(listening)":
440 #endif /* WITH_IP4 */
449 fprintf(outfile
, "%s6%s %s %s",
452 optacceptconn
?"(listening)":
455 sockaddr_inet6_info(&sockname
.ip6
,
456 socknamebuff
, sizeof(socknamebuff
)),
457 sockaddr_inet6_info(&peername
.ip6
,
458 peernamebuff
, sizeof(peernamebuff
)));
463 fprintf(outfile
, "%s6%s %s %s",
466 optacceptconn
?"(listening)":
469 sockaddr_inet6_info(&sockname
.ip6
,
470 socknamebuff
, sizeof(socknamebuff
)),
471 sockaddr_inet6_info(&peername
.ip6
,
472 peernamebuff
, sizeof(peernamebuff
)));
476 fprintf(outfile
, "ip6 %s",
477 sockaddr_inet6_info(&sockname
.ip6
,
478 socknamebuff
, sizeof(socknamebuff
)));
483 fprintf(outfile
, "%s6 %s-%s (%s) %s",
485 sockaddr_inet6_info(&sockname
.ip6
,
486 socknamebuff
, sizeof(socknamebuff
)),
487 sockaddr_inet6_info(&peername
.ip6
,
488 peernamebuff
, sizeof(peernamebuff
)),
491 optacceptconn
?"(listening)":
497 #endif /* WITH_IP6 */
500 fprintf(outfile
, "socket(family/domain=%d)", sockname
.soa
.sa_family
);
510 #undef FDNAME_NAMELEN
512 #endif /* _WITH_SOCKET */