From 47b8d34564614bad73d7cc5f656bd259463b5a43 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Tue, 17 Nov 2020 05:11:37 -0700 Subject: [PATCH] peek_packet.c: provide local and remote address info If the socket on fd 0 is either an AF_INET or AF_INET6 socket, then provide additional output lines with the local and remote address and the local port. Signed-off-by: Kyle J. McKay --- src/peek_packet.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/src/peek_packet.c b/src/peek_packet.c index 220e2dc..8a95baa 100644 --- a/src/peek_packet.c +++ b/src/peek_packet.c @@ -101,6 +101,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. If the incoming packet looks invalid (or a timeout occurs) then no output is produced, but a non-zero exit code is set. + + If the remote address is available (getpeername) then a line of the form + + remote_addr=
+ + will be output where
is either a dotted IPv4 or an IPv6 + (without brackets). + + If the local address is available (getsockname) then two lines of the form + + server_addr=
+ server_port= + + will be output where
is in the same format as remote_addr and + server_port is in the same format as port. */ /* @@ -195,10 +210,18 @@ NON-NULL-BYTE = %x01-FF */ +#define HAVE_STDINT_H 1 +#define HAVE_IPV6 1 +#define HAVE_INET_NTOP 1 +#define HAVE_SNPRINTF 1 #ifdef CONFIG_H #include CONFIG_H #endif +#include +#ifdef HAVE_STDINT_H +#include +#endif #include #include #include @@ -208,6 +231,23 @@ NON-NULL-BYTE = %x01-FF #include #include #include +#include +#include +#ifdef HAVE_IPV6 +#include +#endif +#ifndef HAVE_STDINT_H +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; +#endif + +#ifdef HAVE_IPV6 +#define IPTOASIZE (INET6_ADDRSTRLEN+IF_NAMESIZE+INET6_ADDRSTRLEN+IF_NAMESIZE+1) +#else +#define IPTOASIZE (15+1) /* IPv4 only */ +#endif +static const char *iptoa(const struct sockaddr *ip, char *outstr, size_t s); +static uint16_t xsockport(const struct sockaddr *ip); /* Note that mod_reqtimeout has a default configuration of 20 seconds * maximum to wait for the first byte of the initial request line and @@ -239,6 +279,19 @@ static size_t xstrnlen(const char *s, size_t maxlen) return l; } +/* avoid requiring C99 library */ +#ifdef HAVE_IPV6 +static char *xstrncat(char *s1, const char *s2, size_t n) +{ + char *p; + if (!s1 || !s2 || !n) return s1; + p = s1 + strlen(s1); + while (n-- && *s2) { *p++ = *s2++; } + *p = '\0'; + return s1; +} +#endif /* HAVE_IPV6 */ + #define LC(c) (((c)<'A'||(c)>'Z')?(c):((c)+('a'-'A'))) /* returns >0 if m1 and m2 are NOT equal comparing first len bytes @@ -304,6 +357,15 @@ static int parse_host_and_port(char *ptr, size_t zlen, char **host, static size_t has_controls(const void *_ptr, size_t zlen); +typedef union { + struct sockaddr sa; + struct sockaddr_in in; +#ifdef HAVE_IPV6 + struct sockaddr_in6 in6; +#endif + char padding[128]; +} sockaddr_univ_t; + int main(int argc, char *argv[]) { int len; @@ -313,6 +375,9 @@ int main(int argc, char *argv[]) char *ptr, *gitcmd, *host=NULL; const char *pktend, *port=NULL; int optval; + sockaddr_univ_t sockname; + socklen_t socknamelen; + char ipstr[IPTOASIZE]; (void)argc; (void)argv; @@ -409,6 +474,20 @@ int main(int argc, char *argv[]) if (port != NULL) printf("port=%.*s\n", (int)plen, port); + socknamelen = (socklen_t)sizeof(sockname); + if (!getpeername(0, &sockname.sa, &socknamelen) && + iptoa(&sockname.sa, ipstr, sizeof(ipstr)) && ipstr[0]) { + printf("remote_addr=%s\n", ipstr); + } + socknamelen = (socklen_t)sizeof(sockname); + if (!getsockname(0, &sockname.sa, &socknamelen) && + iptoa(&sockname.sa, ipstr, sizeof(ipstr)) && ipstr[0]) { + uint16_t p = xsockport(&sockname.sa); + printf("server_addr=%s\n", ipstr); + if (p) + printf("server_port=%u\n", (unsigned)p); + } + return 0; } @@ -504,3 +583,62 @@ static size_t has_controls_or_spaces(const void *_ptr, size_t zlen) } return zlen; } + +static const char *iptoa(const struct sockaddr *ip, char *outstr, size_t s) +{ + if (outstr) + *outstr = '\0'; + if (ip && outstr && s) { + if (ip->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const struct sockaddr_in *)ip; + inet_ntop(AF_INET, &sin->sin_addr, outstr, (socklen_t)s); + } +#ifdef HAVE_IPV6 + else if (ip->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)ip; + inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, outstr, (socklen_t)s); + if (sin6->sin6_scope_id) { + size_t outlen = strlen(outstr); +#if IF_NAMESIZE < 9 +#define XIF_NAMESIZE 9 +#else +#define XIF_NAMESIZE IF_NAMESIZE +#endif + char scope[XIF_NAMESIZE+1]; + char *ifname = if_indextoname(sin6->sin6_scope_id, scope+1); + if (ifname) { + scope[0] = '%'; + } else { + /* This can happen on odd systems */ +#ifdef HAVE_SNPRINTF + snprintf(scope, sizeof(scope), "%%%d", (int)sin6->sin6_scope_id); +#else + /* 0xFFFFFFFF only requires 9 digits and XIF_NAMESIZE is >= 9 + * therefore it's guaranteed to fit and not overflow */ + sprintf(scope, "%%%u", (unsigned)(sin6->sin6_scope_id & 0xFFFFFFFF)); +#endif + } + scope[sizeof(scope)-1] = 0; + if (outlen+1 < s) + xstrncat(outstr, scope, s-outlen-1); + } + } +#endif /* HAVE_IPV6 */ + } + return outstr; +} + +static uint16_t xsockport(const struct sockaddr *ip) +{ + if (ip->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const struct sockaddr_in *)ip; + return (uint16_t)ntohs(sin->sin_port); + } +#ifdef HAVE_IPV6 + if (ip->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)ip; + return (uint16_t)ntohs(sin6->sin6_port); + } +#endif + return 0; +} -- 2.11.4.GIT