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
);
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
"/fd/%d", pid
, fd
);
95 if ((len
= Readlink(procpath
, filepath
, pathsize
-1)) < 0) {
96 Error4("readlink(\"%s\", %p, "F_Zu
"): %s",
97 procpath
, filepath
, pathsize
, strerror(errno
));
100 filepath
[len
] = '\0';
103 #endif /* HAVE_PROC_DIR_FD */
105 int statname(const char *file
, int fd
, int filetype
, FILE *outfile
,
107 char filepath
[PATH_MAX
];
112 procgetfdname(fd
, filepath
, sizeof(filepath
));
113 if (filepath
[0] == '/') {
117 #endif /* HAVE_PROC_DIR_FD */
118 /* now see for type specific infos */
120 case (S_IFIFO
>>12): /* 1, FIFO */
121 fputs("pipe", outfile
);
122 if (file
) fprintf(outfile
, " %s", file
);
124 case (S_IFCHR
>>12): /* 2, character device */
125 if (cdevname(fd
, outfile
) == 0) {
126 if (file
) fprintf(outfile
, " %s", file
);
129 case (S_IFDIR
>>12): /* 4, directory */
130 fputs("dir", outfile
);
131 if (file
) fprintf(outfile
, " %s", file
);
133 case (S_IFBLK
>>12): /* 6, block device */
134 fputs("blkdev", outfile
);
135 if (file
) fprintf(outfile
, " %s", file
);
137 case (S_IFREG
>>12): /* 8, regular file */
138 fputs("file", outfile
);
139 if (file
) fprintf(outfile
, " %s", file
);
141 case (S_IFLNK
>>12): /* 10, symbolic link */
142 fputs("link", outfile
);
143 if (file
) fprintf(outfile
, " %s", file
);
145 case (S_IFSOCK
>>12): /* 12, socket */
148 sockname(fd
, outfile
, style
);
150 fprintf(outfile
, "socket %s", file
);
152 fputs("socket", outfile
);
155 Error("SOCKET support not compiled in");
157 #endif /* !_WITH_SOCKET */
161 fputc('\n', outfile
);
167 /* character device analysis */
168 /* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
169 int cdevname(int fd
, FILE *outfile
) {
172 if ((ret
= Isatty(fd
)) < 0) {
173 Error2("isatty(%d): %s", fd
, strerror(errno
));
179 fputs("tty", outfile
);
180 if ((name
= Ttyname(fd
)) != NULL
) {
182 fputs(name
, outfile
);
186 fputs("chrdev", outfile
);
191 int sockettype(int socktype
, char *typename
, size_t typenamemax
) {
193 case SOCK_STREAM
: strncpy(typename
, "stream", typenamemax
); break;
194 case SOCK_DGRAM
: strncpy(typename
, "dgram", typenamemax
); break;
195 case SOCK_SEQPACKET
: strncpy(typename
, "seqpacket", typenamemax
); break;
196 case SOCK_RAW
: strncpy(typename
, "raw", typenamemax
); break;
197 case SOCK_RDM
: strncpy(typename
, "rdm", typenamemax
); break;
199 case SOCK_PACKET
: strncpy(typename
, "packet", typenamemax
); break;
201 default: snprintf(typename
, typenamemax
, "socktype%u", socktype
); break;
207 int sockname(int fd
, FILE *outfile
, char style
) {
208 #define FDNAME_OPTLEN 256
209 #define FDNAME_NAMELEN 256
211 #if HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R
212 struct protoent protoent
, *protoentp
;
214 #define PROTONAMEMAX 1024
215 char protoname
[PROTONAMEMAX
];
216 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
224 char socknamebuff
[FDNAME_NAMELEN
];
225 char peernamebuff
[FDNAME_NAMELEN
];
226 /* in Linux these optcodes are 'enum', but on AIX they are bits! */
227 union sockaddr_union sockname
, peername
; /* the longest I know of */
228 socklen_t socknamelen
, peernamelen
;
229 # define TYPENAMEMAX 16
230 char typename
[TYPENAMEMAX
];
231 #if 0 && defined(SIOCGIFNAME)
232 /*Linux struct ifreq ifc = {{{ 0 }}};*/
233 struct ifreq ifc
= {{ 0 }};
237 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
238 optlen
= sizeof(proto
);
240 Getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &proto
, &optlen
);
241 #elif defined(SO_PROTOTYPE)
242 Getsockopt(fd
, SOL_SOCKET
, SO_PROTOTYPE
, &proto
, &optlen
);
244 #endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */
246 optlen
= sizeof(opttype
);
247 Getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &opttype
, &optlen
);
248 sockettype(opttype
, typename
, sizeof(typename
));
250 optlen
= sizeof(optacceptconn
);
252 Getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &optacceptconn
, &optlen
);
255 #if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
256 #if HAVE_GETPROTOBYNUMBER_R==1 /* Linux */
257 rc
= getprotobynumber_r(proto
, &protoent
, protoname
, sizeof(protoname
), &protoentp
);
258 if (protoentp
== NULL
) {
259 Warn2("sockname(): getprotobynumber_r(proto=%d, ...): %s",
260 proto
, strerror(rc
));
262 strncpy(protoname
, protoentp
->p_name
, sizeof(protoname
));
263 #elif HAVE_GETPROTOBYNUMBER_R==2 /* Solaris */
264 protoentp
= getprotobynumber(proto
);
265 strncpy(protoname
, protoentp
->p_name
, sizeof(protoname
));
268 case IPPROTO_TCP
: strcpy(protoname
, "tcp"); break;
269 case IPPROTO_UDP
: strcpy(protoname
, "udp"); break;
270 case IPPROTO_SCTP
: strcpy(protoname
, "sctp"); break;
271 default: sprintf(protoname
, "proto%d", proto
); break;
275 if (opttype
== SOCK_STREAM
) {
276 strcpy(protoname
, "tcp");
277 } else if (opttype
== SOCK_DGRAM
) {
278 strcpy(protoname
, "udp");
280 strcpy(protoname
, "socket");
282 #endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */
283 socknamelen
= sizeof(sockname
);
284 result
= Getsockname(fd
, &sockname
.soa
, &socknamelen
);
286 Error2("getsockname(%d): %s", fd
, strerror(errno
));
290 peernamelen
= sizeof(peername
);
291 result
= Getpeername(fd
, (struct sockaddr
*)&peername
, &peernamelen
);
293 Warn2("getpeername(%d): %s", fd
, strerror(errno
));
296 switch (sockname
.soa
.sa_family
) {
301 fprintf(outfile
, "unix%s%s %s",
302 opttype
==SOCK_DGRAM
?"datagram":"",
304 optacceptconn
?"(listening)":
307 sockaddr_unix_info(&sockname
.un
, socknamelen
,
308 socknamebuff
, sizeof(socknamebuff
)));
311 //sockettype(opttype, typename, TYPENAMEMAX);
312 fprintf(outfile
, "unix %s-%s %s %s",
313 sockaddr_unix_info(&sockname
.un
, socknamelen
,
314 socknamebuff
, sizeof(socknamebuff
)),
315 sockaddr_unix_info(&peername
.un
, peernamelen
,
316 peernamebuff
, sizeof(peernamebuff
)),
319 optacceptconn
?"(listening)":
325 #endif /* WITH_UNIX */
333 fprintf(outfile
, "%s%s %s %s",
336 optacceptconn
?"(listening)":
339 sockaddr_inet4_info(&sockname
.ip4
,
340 socknamebuff
, sizeof(socknamebuff
)),
341 sockaddr_inet4_info(&peername
.ip4
,
342 peernamebuff
, sizeof(peernamebuff
)));
347 fprintf(outfile
, "%s%s %s %s",
350 optacceptconn
?"(listening)":
353 sockaddr_inet4_info(&sockname
.ip4
,
354 socknamebuff
, sizeof(socknamebuff
)),
355 sockaddr_inet4_info(&peername
.ip4
,
356 peernamebuff
, sizeof(peernamebuff
)));
360 fprintf(outfile
, "ip %s",
361 sockaddr_inet4_info(&sockname
.ip4
,
362 socknamebuff
, sizeof(socknamebuff
)));
367 fprintf(outfile
, "%s %s-%s (%s) %s",
369 sockaddr_inet4_info(&sockname
.ip4
,
370 socknamebuff
, sizeof(socknamebuff
)),
371 sockaddr_inet4_info(&peername
.ip4
,
372 peernamebuff
, sizeof(peernamebuff
)),
375 optacceptconn
?"(listening)":
381 #endif /* WITH_IP4 */
390 fprintf(outfile
, "%s6%s %s %s",
393 optacceptconn
?"(listening)":
396 sockaddr_inet6_info(&sockname
.ip6
,
397 socknamebuff
, sizeof(socknamebuff
)),
398 sockaddr_inet6_info(&peername
.ip6
,
399 peernamebuff
, sizeof(peernamebuff
)));
404 fprintf(outfile
, "%s6%s %s %s",
407 optacceptconn
?"(listening)":
410 sockaddr_inet6_info(&sockname
.ip6
,
411 socknamebuff
, sizeof(socknamebuff
)),
412 sockaddr_inet6_info(&peername
.ip6
,
413 peernamebuff
, sizeof(peernamebuff
)));
417 fprintf(outfile
, "ip6 %s",
418 sockaddr_inet6_info(&sockname
.ip6
,
419 socknamebuff
, sizeof(socknamebuff
)));
424 fprintf(outfile
, "%s6 %s-%s (%s) %s",
426 sockaddr_inet6_info(&sockname
.ip6
,
427 socknamebuff
, sizeof(socknamebuff
)),
428 sockaddr_inet6_info(&peername
.ip6
,
429 peernamebuff
, sizeof(peernamebuff
)),
432 optacceptconn
?"(listening)":
438 #endif /* WITH_IP6 */
441 fprintf(outfile
, "socket(family/domain=%d)", sockname
.soa
.sa_family
);
451 #undef FDNAME_NAMELEN
453 #endif /* _WITH_SOCKET */