diff --git a/CHANGES b/CHANGES index 3f02506..fa28372 100644 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,10 @@ Corrections: Thanks to Brandon Carpenter, Qing Wan, and Pavel Nakonechnyi for sending patches. + filan did not output the socket protocol. + filan -s assumed each stream socket to be TCP and each datagram socket + to be UDP. Now it uses SO_PROTOCOL and getprotoent() for correct output. + Porting: In gcc version 10 the default changed from -fcommon to -fno-common. Consequently, linking filan and procan failed with error @@ -116,6 +120,7 @@ Testing: * renamed testaddrs() to testfeats(), and introduced new testaddrs() New features: +<<<<<<< HEAD GOPEN and UNIX-CLIENT addresses now support sockets of type SEQPACKET. Test: GOPENUNIXSEQPACKET Feature suggested by vi0oss. @@ -127,6 +132,10 @@ Features: has been implemented. See the documentation for info on data types. Tests: SETSOCKOPT SETSOCKOPT_LISTEN Thanks to Steven Danna and Korian Edeline for reporting this issue. +======= + Filan option -S gives short description like -s but with improved + format +>>>>>>> 7cd82d9... Fixed filan -s, added -S ####################### V 1.7.3.4: diff --git a/config.h.in b/config.h.in index c4fb579..cf6115e 100644 --- a/config.h.in +++ b/config.h.in @@ -114,6 +114,12 @@ /* Define if you have the getipnodebyname function. */ #undef HAVE_PROTOTYPE_LIB_getipnodebyname +/* Define if you have the getprotobynumber_r function. */ +#undef HAVE_GETPROTOBYNUMBER_R + +/* Define if you have the getprotobynumber function. */ +#undef HAVE_GETPROTOBYNUMBER + /* Define if you have the setgroups function. */ #undef HAVE_SETGROUPS diff --git a/configure.ac b/configure.ac index 8e3045e..38dc83b 100644 --- a/configure.ac +++ b/configure.ac @@ -771,6 +771,7 @@ AC_TYPE_SIGNAL AC_FUNC_STRFTIME AC_CHECK_FUNCS(putenv select pselect poll socket strtod strtol) AC_CHECK_FUNCS(strtoul uname getpgid getsid gethostbyname getaddrinfo) +AC_CHECK_FUNCS(getprotobynumber getprotobynumber_r) AC_CHECK_FUNCS(setgroups inet_aton) AC_CHECK_FUNCS() diff --git a/fdname.c b/fdname.c index c523efd..8cd3cca 100644 --- a/fdname.c +++ b/fdname.c @@ -25,14 +25,15 @@ struct sockopt { }; -int statname(const char *file, int fd, int filetype, FILE *outfile); +int statname(const char *file, int fd, int filetype, FILE *outfile, char style); int cdevname(int fd, FILE *outfile); -int sockname(int fd, FILE *outfile); +int sockname(int fd, FILE *outfile, char style); int unixame(int fd, FILE *outfile); int tcpname(int fd, FILE *outfile); -int fdname(const char *file, int fd, FILE *outfile, const char *numform) { +int fdname(const char *file, int fd, FILE *outfile, const char *numform, + char style) { struct stat buf = {0}; int filetype; Debug1("checking file descriptor %u", fd); @@ -49,13 +50,13 @@ int fdname(const char *file, int fd, FILE *outfile, const char *numform) { if (numform != NULL) { fprintf(outfile, numform, fd); } - return statname(file, fd, filetype, outfile); + return statname(file, fd, filetype, outfile, style); } else { if (Stat(file, &buf) < 0) { Error2("stat(\"%s\"): %s", file, strerror(errno)); } filetype = (buf.st_mode&S_IFMT)>>12; - return statname(file, -1, filetype, outfile); + return statname(file, -1, filetype, outfile, style); } } @@ -101,7 +102,8 @@ static int procgetfdname(int fd, char *filepath, size_t pathsize) { } #endif /* HAVE_PROC_DIR_FD */ -int statname(const char *file, int fd, int filetype, FILE *outfile) { +int statname(const char *file, int fd, int filetype, FILE *outfile, + char style) { char filepath[PATH_MAX]; filepath[0] = '\0'; @@ -143,7 +145,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) { case (S_IFSOCK>>12): /* 12, socket */ #if _WITH_SOCKET if (fd >= 0) { - sockname(fd, outfile); + sockname(fd, outfile, style); } else if (file) { fprintf(outfile, "socket %s", file); } else { @@ -186,138 +188,264 @@ int cdevname(int fd, FILE *outfile) { return 0; } +int sockettype(int socktype, char *typename, size_t typenamemax) { + switch (socktype) { + case SOCK_STREAM: strncpy(typename, "stream", typenamemax); break; + case SOCK_DGRAM: strncpy(typename, "dgram", typenamemax); break; + case SOCK_SEQPACKET: strncpy(typename, "seqpacket", typenamemax); break; + case SOCK_RAW: strncpy(typename, "raw", typenamemax); break; + case SOCK_RDM: strncpy(typename, "rdm", typenamemax); break; +#ifdef SOCK_PACKET + case SOCK_PACKET: strncpy(typename, "packet", typenamemax); break; +#endif + default: snprintf(typename, typenamemax, "socktype%u", socktype); break; + } + return 0; +} #if _WITH_SOCKET -int sockname(int fd, FILE *outfile) { +int sockname(int fd, FILE *outfile, char style) { #define FDNAME_OPTLEN 256 #define FDNAME_NAMELEN 256 socklen_t optlen; +#if HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R + struct protoent protoent, *protoentp; +#endif +#define PROTONAMEMAX 1024 + char protoname[PROTONAMEMAX]; +#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) + int proto; +#endif int opttype; #ifdef SO_ACCEPTCONN int optacceptconn; #endif int result /*0, i*/; - char namebuff[FDNAME_NAMELEN]; - char peerbuff[FDNAME_NAMELEN]; + char socknamebuff[FDNAME_NAMELEN]; + char peernamebuff[FDNAME_NAMELEN]; /* in Linux these optcodes are 'enum', but on AIX they are bits! */ union sockaddr_union sockname, peername; /* the longest I know of */ - socklen_t namelen; + socklen_t socknamelen, peernamelen; +# define TYPENAMEMAX 16 + char typename[TYPENAMEMAX]; #if 0 && defined(SIOCGIFNAME) /*Linux struct ifreq ifc = {{{ 0 }}};*/ struct ifreq ifc = {{ 0 }}; #endif + int rc; - optlen = FDNAME_OPTLEN; +#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) + optlen = sizeof(proto); +#ifdef SO_PROTOCOL + Getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &proto, &optlen); +#elif defined(SO_PROTOTYPE) + Getsockopt(fd, SOL_SOCKET, SO_PROTOTYPE, &proto, &optlen); +#endif +#endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */ + optlen = sizeof(opttype); Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen); + sockettype(opttype, typename, sizeof(typename)); + + optlen = sizeof(optacceptconn); #ifdef SO_ACCEPTCONN Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen); #endif - namelen = sizeof(sockname); - result = Getsockname(fd, &sockname.soa, &namelen); +#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) +#if HAVE_GETPROTOBYNUMBER_R + rc = getprotobynumber_r(proto, &protoent, protoname, sizeof(protoname), &protoentp); + if (protoentp == NULL) { + Warn2("sockname(): getprotobynumber_r(proto=%d, ...): %s", + proto, strerror(rc)); + } + strncpy(protoname, protoentp->p_name, sizeof(protoname)); +#elif HAVE_GETPROTOBYNUMBER + protoentp = getprotobynumber(proto); + strncpy(protoname, protoentp->p_name, sizeof(protoname)); +#else + switch (proto) { + case IPPROTO_TCP: strcpy(protoname, "tcp"); break; + case IPPROTO_UDP: strcpy(protoname, "udp"); break; + case IPPROTO_SCTP: strcpy(protoname, "sctp"); break; + default: sprintf(protoname, "proto%d", proto); break; + } +#endif +#else + if (opttype == SOCK_STREAM) { + strcpy(protoname, "tcp"); + } else if (opttype == SOCK_DGRAM) { + strcpy(protoname, "udp"); + } else { + strcpy(protoname, "socket"); + } +#endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */ + socknamelen = sizeof(sockname); + result = Getsockname(fd, &sockname.soa, &socknamelen); if (result < 0) { Error2("getsockname(%d): %s", fd, strerror(errno)); return -1; } - namelen = sizeof(peername); - result = Getpeername(fd, (struct sockaddr *)&peername, &namelen); + peernamelen = sizeof(peername); + result = Getpeername(fd, (struct sockaddr *)&peername, &peernamelen); if (result < 0) { - Error2("getpeername(%d): %s", fd, strerror(errno)); + Warn2("getpeername(%d): %s", fd, strerror(errno)); } switch (sockname.soa.sa_family) { #if WITH_UNIX case AF_UNIX: + switch (style) { + case 's': fprintf(outfile, "unix%s%s %s", opttype==SOCK_DGRAM?"datagram":"", #ifdef SO_ACCEPTCONN optacceptconn?"(listening)": #endif "", - sockaddr_unix_info(&sockname.un, namelen, - namebuff, sizeof(namebuff))); + sockaddr_unix_info(&sockname.un, socknamelen, + socknamebuff, sizeof(socknamebuff))); break; + case 'S': + //sockettype(opttype, typename, TYPENAMEMAX); + fprintf(outfile, "unix %s-%s %s %s", + sockaddr_unix_info(&sockname.un, socknamelen, + socknamebuff, sizeof(socknamebuff)), + sockaddr_unix_info(&peername.un, peernamelen, + peernamebuff, sizeof(peernamebuff)), + typename, +#ifdef SO_ACCEPTCONN + optacceptconn?"(listening)": #endif + ""); +#endif /* WITH_UNIX */ + break; + } + break; #if WITH_IP4 case AF_INET: + switch (style) { + case 's': switch (opttype) { #if WITH_TCP case SOCK_STREAM: - fprintf(outfile, "tcp%s %s %s", + fprintf(outfile, "%s%s %s %s", + protoname, #ifdef SO_ACCEPTCONN optacceptconn?"(listening)": #endif "", sockaddr_inet4_info(&sockname.ip4, - namebuff, sizeof(namebuff)), + socknamebuff, sizeof(socknamebuff)), sockaddr_inet4_info(&peername.ip4, - peerbuff, sizeof(peerbuff))); + peernamebuff, sizeof(peernamebuff))); break; #endif #if WITH_UDP case SOCK_DGRAM: - fprintf(outfile, "udp%s %s %s", + fprintf(outfile, "%s%s %s %s", + protoname, #ifdef SO_ACCEPTCONN optacceptconn?"(listening)": #endif "", sockaddr_inet4_info(&sockname.ip4, - namebuff, sizeof(namebuff)), + socknamebuff, sizeof(socknamebuff)), sockaddr_inet4_info(&peername.ip4, - peerbuff, sizeof(peerbuff))); + peernamebuff, sizeof(peernamebuff))); break; #endif default: fprintf(outfile, "ip %s", sockaddr_inet4_info(&sockname.ip4, - namebuff, sizeof(namebuff))); + socknamebuff, sizeof(socknamebuff))); break; } break; + case 'S': + fprintf(outfile, "%s %s-%s (%s) %s", + protoname, + sockaddr_inet4_info(&sockname.ip4, + socknamebuff, sizeof(socknamebuff)), + sockaddr_inet4_info(&peername.ip4, + peernamebuff, sizeof(peernamebuff)), + typename, +#ifdef SO_ACCEPTCONN + optacceptconn?"(listening)": +#endif + ""); + break; + } + break; #endif /* WITH_IP4 */ #if WITH_IP6 case AF_INET6: + switch (style) { + case 's': switch (opttype) { #if WITH_TCP case SOCK_STREAM: - fprintf(outfile, "tcp6%s %s %s", + fprintf(outfile, "%s6%s %s %s", + protoname, #ifdef SO_ACCEPTCONN optacceptconn?"(listening)": #endif "", sockaddr_inet6_info(&sockname.ip6, - namebuff, sizeof(namebuff)), + socknamebuff, sizeof(socknamebuff)), sockaddr_inet6_info(&peername.ip6, - peerbuff, sizeof(peerbuff))); + peernamebuff, sizeof(peernamebuff))); break; #endif #if WITH_UDP case SOCK_DGRAM: - fprintf(outfile, "udp6%s %s %s", + fprintf(outfile, "%s6%s %s %s", + protoname, #ifdef SO_ACCEPTCONN optacceptconn?"(listening)": #endif "", sockaddr_inet6_info(&sockname.ip6, - namebuff, sizeof(namebuff)), + socknamebuff, sizeof(socknamebuff)), sockaddr_inet6_info(&peername.ip6, - peerbuff, sizeof(peerbuff))); + peernamebuff, sizeof(peernamebuff))); break; #endif default: fprintf(outfile, "ip6 %s", sockaddr_inet6_info(&sockname.ip6, - namebuff, sizeof(namebuff))); + socknamebuff, sizeof(socknamebuff))); break; } + break; + case 'S': + fprintf(outfile, "%s6 %s-%s (%s) %s", + protoname, + sockaddr_inet6_info(&sockname.ip6, + socknamebuff, sizeof(socknamebuff)), + sockaddr_inet6_info(&peername.ip6, + peernamebuff, sizeof(peernamebuff)), + typename, +#ifdef SO_ACCEPTCONN + optacceptconn?"(listening)": +#endif + ""); + break; + } + break; #endif /* WITH_IP6 */ + default: - fputs("socket", outfile); + fprintf(outfile, "socket(family/domain=%d)", sockname.soa.sa_family); } +#if HAVE_GETPROTOENT + if (ipproto >= 0) { + endprotoent(); + } +#endif return result; #undef FDNAME_OPTLEN #undef FDNAME_NAMELEN diff --git a/filan.c b/filan.c index c613059..7d7ceb2 100644 --- a/filan.c +++ b/filan.c @@ -527,20 +527,18 @@ int sockan(int fd, FILE *outfile) { #define FILAN_NAMELEN 256 socklen_t optlen; int result /*0, i*/; - static const char *socktypes[] = { - "undef", "STREAM", "DGRAM", "RAW", "RDM", - "SEQPACKET", "undef", "undef", "undef", "undef", - "PACKET", "undef" } ; char nambuff[FILAN_NAMELEN]; /* in Linux these optcodes are 'enum', but on AIX they are bits! */ static const struct sockopt sockopts[] = { {SO_DEBUG, "DEBUG"}, {SO_REUSEADDR, "REUSEADDR"}, - {SO_TYPE, "TYPE"}, - {SO_ERROR, "ERROR"}, -#ifdef SO_PROTOTYPE +#ifdef SO_PROTOCOL + {SO_PROTOCOL, "PROTOCOL"}, +#elif defined(SO_PROTOTYPE) {SO_PROTOTYPE, "PROTOTYPE"}, #endif + {SO_TYPE, "TYPE"}, + {SO_ERROR, "ERROR"}, {SO_DONTROUTE, "DONTROUTE"}, {SO_BROADCAST, "BROADCAST"}, {SO_SNDBUF, "SNDBUF"}, @@ -615,8 +613,12 @@ int sockan(int fd, FILE *outfile) { Debug4("getsockopt(%d, SOL_SOCKET, SO_TYPE, %p, {"F_socklen"}): %s", fd, optval.c, optlen, strerror(errno)); } else { +# define TYPENAMEMAX 16 + char typename[TYPENAMEMAX]; + sockettype(*optval.i, typename, sizeof(typename)); + Debug3("fd %d: socket of type %d (\"%s\")", fd, *optval.i, - socktypes[*optval.i]); + typename); } optname = sockopts; while (optname->so) { @@ -757,22 +759,29 @@ int ipan(int fd, FILE *outfile) { #endif {0, NULL} } ; const struct sockopt *optname; - int opttype; - socklen_t optlen = sizeof(opttype); + int optproto; + socklen_t optlen = sizeof(optproto); optname = ipopts; while (optname->so) { sockoptan(fd, optname, SOL_IP, outfile); ++optname; } - /* want to pass the fd to the next layer protocol. dont know how to get the - protocol number from the fd? use TYPE to identify TCP. */ - if (Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen) >= 0) { - switch (opttype) { + /* want to pass the fd to the next layer protocol. */ +#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) + if (Getsockopt(fd, SOL_SOCKET, +#ifdef SO_PROTOCOL + SO_PROTOCOL, +#elif defined(SO_PROTOTYPE) + SO_PROTOTYPE, +#endif + &optproto, &optlen) >= 0) { + switch (optproto) { #if WITH_TCP - case SOCK_STREAM: tcpan(fd, outfile); break; + case IPPROTO_TCP: tcpan(fd, outfile); break; #endif } } +#endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */ return 0; } #endif /* WITH_IP */ diff --git a/filan.h b/filan.h index 15c5f2f..d42877b 100644 --- a/filan.h +++ b/filan.h @@ -28,12 +28,14 @@ extern int cdevan(int fd, FILE *outfile); #if _WITH_SOCKET extern int isasocket(int fd); +extern int sockettype(int socktype, char *typename, size_t typenamemax); extern int sockan(int fd, FILE *outfile); extern int ipan(int fd, FILE *outfile); extern int ip6an(int fd, FILE *outfile); #endif /* _WITH_SOCKET */ extern - int fdname(const char *file, int fd, FILE *outfile, const char *numform); + int fdname(const char *file, int fd, FILE *outfile, const char *numform, + char style); #endif /* !defined(__filan_h_included) */ diff --git a/filan_main.c b/filan_main.c index dc0c0e8..3f6f7e6 100644 --- a/filan_main.c +++ b/filan_main.c @@ -46,7 +46,8 @@ int main(int argc, const char *argv[]) { #endif case 'L': filan_followsymlinks = true; break; case 'd': diag_set('d', NULL); break; - case 's': style = 1; break; + case 's': style = arg1[0][1]; break; + case 'S': style = arg1[0][1]; break; case 'r': filan_rawoutput = true; break; case 'i': if (arg1[0][2]) { a = *arg1+2; @@ -193,15 +194,15 @@ int main(int argc, const char *argv[]) { Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s", filename, strerror(errno)); } - fdname(filename, fd, fdout, NULL); + fdname(filename, fd, fdout, NULL, style); #endif - fdname(filename, -1, fdout, NULL); + fdname(filename, -1, fdout, NULL, style); } else { if (m == n) { - fdname("", m, fdout, NULL); + fdname("", m, fdout, NULL, style); } else { for (i = m; i < n; ++i) { - fdname("", i, fdout, "%5u "); + fdname("", i, fdout, "%5u ", style); } } } @@ -235,6 +236,7 @@ static void filan_usage(FILE *fd) { fputs(" -i only analyze this fd\n", fd); fprintf(fd, " -n analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE); fputs(" -s simple output with just type and socket address or path\n", fd); + fputs(" -S like -s but improved format and contents\n", fd); /* fputs(" -c alternate device visualization\n", fd);*/ fputs(" -f analyze file system entry\n", fd); fputs(" -T wait before analyzing, useful to connect with debugger\n", fd);