This posting is to record some code cleaning and restructuring I performed with the intention to improve the resolver code of the badly neglected software "netsed". Now that there is has come to our knowledge that there is a live fork of said software, the new upstream author is welcome to fetch the three difference files here, in order to incorporate them on top of his changes.
As two of the patches were part of a "format 3.0" migration plan, they contain some irrelevant text changes. They are immaterial now, but they were part of the prerequisite for the main contribution: use_getaddinfo_ipv6.diff The description of each patch provides further comments on principles and shorcomings. They are to be superimposed in order on top of netsed_0.01c.orig.tar.gz, just move the directory "netsed" to "netsed-0.01c". Best regards, Mats Erik Andersson, fil. dr 2459 41E9 C420 3F6D F68B 2E88 F768 4541 F25B 5D41 Abonnerar på: debian-mentors, debian-devel-games, debian-perl, debian-ipv6, debian-qa
Description: Mend some minor issues. Always set SO_REUSEADDR on litening socket. . Remove O_SYNC on sockets, as it is a no-op. . Incorporate a SIGCHLD handler for proper child process shutdown . Slightly clearify an error message. Author: Roman Shterenzon <ro...@xpert.com>, will, kevlo License: BSD (FreeBSD) X-Comment: Patch from FreeBSD ports collection, slightly altered. X-Original-Patch: http://www.cz.freebsd.org/cgi/cvsweb.cgi/ports/net/netsed/files/patch-netsed.c?rev=1.2;content-type=text%2Fplain Forwarded: no Last-update: 2010-06-11 --- netsed-0.01c/netsed.c.orig Fri Jan 5 18:58:22 2001 +++ netsed-0.01c/netsed.c Sun Aug 11 14:32:29 2002 @@ -2,6 +2,7 @@ #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> @@ -45,11 +46,11 @@ ERR("This will replace all occurences of pat1 with pat2 in matching packets.\n"); ERR("Additional parameter (count) can be used to expire rule after 'count'\n"); ERR("succesful substitutions. Eight-bit characters, including NULL and '/', can\n"); - ERR("be passed using HTTP-alike hex escape sequences (eg. %%0a%%0d). Single '%%'\n"); - ERR("can be reached by using '%%%%'. Examples:\n\n"); - ERR(" 's/anrew/mike/1' - replace 'andrew' with 'mike' (once)\n"); - ERR(" 's/anrew/mike' - replace all occurences of 'andrew' with 'mike'\n"); - ERR(" 's/anrew/mike%%00' - replace 'andrew' with 'mike\\x00' (to keep orig. size)\n"); + ERR("be passed using HTTP-like hex escape sequences (e.g. CRLF as %%0a%%0d).\n"); + ERR("A match on '%%' can be achieved by specifying '%%%%'. Examples:\n\n"); + ERR(" 's/andrew/mike/1' - replace 'andrew' with 'mike' (only first time)\n"); + ERR(" 's/andrew/mike' - replace all occurences of 'andrew' with 'mike'\n"); + ERR(" 's/andrew/mike%%00' - replace 'andrew' with 'mike\\x00' (also padding to keep orig. size)\n"); ERR(" 's/%%%%/%%2f/20' - replace '%%' with '/' in first 20 packets\n\n"); ERR("Rules are not working on cross-packet boundaries and are evaluated from\n"); ERR("first to last not expired rule.\n"); @@ -134,8 +135,10 @@ void bind_and_listen(int tcp,int port) { + int on=1; struct sockaddr_in laddr; lsock=socket(PF_INET,tcp ? SOCK_STREAM:SOCK_DGRAM,0); + setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); fcntl(lsock,F_SETFL,O_NONBLOCK); laddr.sin_family = PF_INET; laddr.sin_port = htons (port); @@ -186,7 +189,6 @@ rd=read(s1,buf,sizeof(buf)); if (rd<0 && errno!=EAGAIN) return 0; // s1 not connected if (rd>0) { - fcntl(s2,F_SETFL,O_SYNC); printf("[+] Caught server -> client packet.\n"); rd=sed_the_buffer(rd); if (write(s2,b2,rd)<=0) return 0; // not able to send @@ -195,7 +197,6 @@ rd=read(s2,buf,sizeof(buf)); if (rd<0 && errno!=EAGAIN) return 0; // s2 not connected if (rd>0) { - fcntl(s1,F_SETFL,O_SYNC); printf("[+] Caught client -> server packet.\n"); rd=sed_the_buffer(rd); if (write(s1,b2,rd)<=0) return 0; // not able to send @@ -204,6 +205,14 @@ return 1; } +void sig_chld(int signo) +{ + pid_t pid; + int stat; + while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) + printf("child %d terminated\n", pid); + return; +} int main(int argc,char* argv[]) { int i; @@ -242,7 +251,7 @@ if (fixedhost && fixedport) printf("[+] Using fixed forwarding to %s:%s.\n",argv[3],argv[4]); else printf("[+] Using dynamic (transparent proxy) forwarding.\n"); signal(SIGPIPE,SIG_IGN); - signal(SIGCHLD,SIG_IGN); + signal(SIGCHLD,sig_chld); // Am I bad coder?;>
Description: Correct compiler warnings and lintian complaints. Mend some warnings, and somewhat rewrite the usage text. Author: Mats Erik Andersson <deb...@gisladisker.se> Forwarded: no Last-Update: 2010-06-11 --- netsed-0.01c.fbsd/netsed.c +++ netsed-0.01c/netsed.c @@ -42,18 +42,18 @@ void usage_hints(const char* why) { ERR(" address of incoming connection, see README)\n"); ERR(" rport - destination port (0 = dst port of incoming connection)\n"); ERR(" ruleN - replacement rules (see below)\n\n"); - ERR("General replacement rules syntax: s/pat1/pat2[/expire]\n\n"); - ERR("This will replace all occurences of pat1 with pat2 in matching packets.\n"); - ERR("Additional parameter (count) can be used to expire rule after 'count'\n"); - ERR("succesful substitutions. Eight-bit characters, including NULL and '/', can\n"); - ERR("be passed using HTTP-like hex escape sequences (e.g. CRLF as %%0a%%0d).\n"); + ERR("General syntax of replacement rules: s/pat1/pat2[/expire]\n\n"); + ERR("This will replace all occurences of pat1 with pat2 in any matching packet.\n"); + ERR("An additional parameter (count) can be used to expire a rule after 'count'\n"); + ERR("successful substitutions. Eight-bit characters, including NULL and '/',\n"); + ERR("can be passed using HTTP-like hex escape sequences (e.g. CRLF as %%0a%%0d).\n"); ERR("A match on '%%' can be achieved by specifying '%%%%'. Examples:\n\n"); ERR(" 's/andrew/mike/1' - replace 'andrew' with 'mike' (only first time)\n"); ERR(" 's/andrew/mike' - replace all occurences of 'andrew' with 'mike'\n"); ERR(" 's/andrew/mike%%00' - replace 'andrew' with 'mike\\x00' (also padding to keep orig. size)\n"); ERR(" 's/%%%%/%%2f/20' - replace '%%' with '/' in first 20 packets\n\n"); - ERR("Rules are not working on cross-packet boundaries and are evaluated from\n"); - ERR("first to last not expired rule.\n"); + ERR("Rules are not active across packet boundaries, and they are evaluated\n"); + ERR("from first to last, not yet expired rule, as stated on the command line.\n"); exit(1); } @@ -257,8 +257,10 @@ int main(int argc,char* argv[]) { while (1) { struct sockaddr_in s; - int x,l=sizeof(struct sockaddr_in); + int x; + socklen_t l = sizeof(struct sockaddr_in); int conho,conpo; + usleep(1000); // Do not wanna select ;P if ((csock=accept(lsock,(struct sockaddr*)&s,&l))>=0) { fcntl(csock,F_SETFL,O_NONBLOCK);
Description: Make resolving address independent. Replace gethostbyname(3) and inet_addr(3) with getaddrinfo(3). This also has the added benefit of allowing symbolic host names and port names as command line options. Both entities are resolved into their numeric equivalents . Replace inet_ntoa(3) with getnameinfo(3). . Replace the inappropriate data types chosen for 'conho' and 'fixedhost' with 'struct sockaddr_storage', thus making it possible to keep records of IPv4 and IPv6. . Thus originally claimed support for "transparent proxies" has not been attended to. Some work around is needed to process local or remote port assigned as zero. . New implementation detects address family of remote target, and uses this to install a local listening socket of the very same family. One could imagining to relax this construction: . "bind_and_listen(fixedhost.ss_family, ...)" . "hints.ai_family = af;" . are responsible for this behaviour. . The calls get_port() and set_port() improve readability, simply by hiding the address family dependence. . WARNING: This patch leaves the inferior polling implementation untouched. Author: Mats Erik Andersson <deb...@gisladisker.se> X-Depends-on-patch: 02_freebsd_netsed_c.diff X-Depends-on-patch: 03_minor_code_cleanup.diff Last-Update: 2010-06-19 --- netsed-0.01c.debian/netsed.c 2010-06-11 18:05:50.000000000 +0200 +++ netsed-0.01c/netsed.c 2010-06-19 17:30:18.000000000 +0200 @@ -5,6 +5,7 @@ #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <netdb.h> #include <fcntl.h> #include <string.h> #include <errno.h> @@ -57,6 +58,28 @@ exit(1); } +in_port_t get_port(struct sockaddr *sa) { + switch (sa->sa_family) { + case AF_INET: + return ntohs(((struct sockaddr_in *) sa)->sin_port); + case AF_INET6: + return ntohs(((struct sockaddr_in6 *) sa)->sin6_port); + default: + return 0; + } +} /* get_port(struct sockaddr *) */ + +void set_port(struct sockaddr *sa, in_port_t port) { + switch (sa->sa_family) { + case AF_INET: + ((struct sockaddr_in *) sa)->sin_port = htons(port); + break; + case AF_INET6: + ((struct sockaddr_in6 *) sa)->sin6_port = htons(port); + default: + break; + } +} /* set_port(struct sockaddr *, in_port_t) */ void error(const char* reason) { ERR("[-] Error: %s\n",reason); @@ -134,19 +157,42 @@ } -void bind_and_listen(int tcp,int port) { - int on=1; - struct sockaddr_in laddr; - lsock=socket(PF_INET,tcp ? SOCK_STREAM:SOCK_DGRAM,0); - setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); - fcntl(lsock,F_SETFL,O_NONBLOCK); - laddr.sin_family = PF_INET; - laddr.sin_port = htons (port); - laddr.sin_addr.s_addr = 0; - if (bind(lsock,(struct sockaddr*)&laddr,sizeof(laddr))) - error("cannot bind to given port / protocol"); - if (listen(lsock,16)) - error("cannot listen on the socket (strange)"); +void bind_and_listen(int af, int tcp, const char *portstr) { + int ret; + struct addrinfo hints, *res, *reslist; + + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = af; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM; + + if ((ret = getaddrinfo(NULL, portstr, &hints, &reslist))) { + ERR("getaddrinfo(): %s\n", gai_strerror(ret)); + error("Impossible to resolve listening port."); + } + /* We have useful addresses. */ + for (res = reslist; res; res = res->ai_next) { + int one = 1; + + if ( (lsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) + continue; + setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + fcntl(lsock,F_SETFL,O_NONBLOCK); + if (bind(lsock, res->ai_addr, res->ai_addrlen) < 0) { + ERR("bind(): %s", strerror(errno)); + close(lsock); + continue; + } + if (listen(lsock, 16) < 0) { + close(lsock); + continue; + } + /* Successfully bound and now also listening. */ + break; + } + freeaddrinfo(reslist); + if (res == NULL) + error("Listening socket failed."); } char buf[MAX_BUF]; @@ -215,12 +261,16 @@ } int main(int argc,char* argv[]) { - int i; - int fixedhost=0,fixedport=0; + int i, ret; + in_port_t fixedport = 0; + struct sockaddr_storage fixedhost; + struct addrinfo hints, *res, *reslist; + + memset(&fixedhost, '\0', sizeof(fixedhost)); printf("netsed " VERSION " by Michal Zalewski <lcam...@ids.pl>\n"); setbuffer(stdout,NULL,0); if (argc<6) usage_hints("not enough parameters"); - if (strcmp(argv[1],"tcp")*strcmp(argv[1],"udp")) usage_hints("incorrect procotol"); + if (strcasecmp(argv[1],"tcp")*strcasecmp(argv[1],"udp")) usage_hints("incorrect procotol"); // parse rules for (i=5;i<argc;i++) { char *fs=0, *ts=0, *cs=0; @@ -242,44 +292,86 @@ rules++; } - printf("[+] Loaded %d rules...\n",rules); - if (!atoi(argv[2])) error("incorrect local port"); - bind_and_listen(strcmp(argv[1],"udp"),atoi(argv[2])); - printf("[+] Listening on port %d/%s.\n",atoi(argv[2]),argv[1]); - fixedport=atoi(argv[4]); - fixedhost=inet_addr(argv[3]); - if (fixedhost && fixedport) printf("[+] Using fixed forwarding to %s:%s.\n",argv[3],argv[4]); - else printf("[+] Using dynamic (transparent proxy) forwarding.\n"); + printf("[+] Loaded %d rule%s...\n", rules, (rules > 1) ? "s" : ""); + + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + hints.ai_socktype = strncasecmp(argv[1], "udp", 3) ? SOCK_STREAM : SOCK_DGRAM; + + if ((ret = getaddrinfo(argv[3], argv[4], &hints, &reslist))) { + ERR("getaddrinfo(): %s\n", gai_strerror(ret)); + error("Impossible to resolve remote address or port."); + } + /* We have candidates for remote host. */ + for (res = reslist; res; res = res->ai_next) { + int sd = -1; + + if ( (sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) + continue; + /* Has successfully built a socket for this address family. */ + /* Record the address structure and the port. */ + fixedport = get_port(res->ai_addr); + memcpy(&fixedhost, res->ai_addr, res->ai_addrlen); + close(sd); + break; + } + freeaddrinfo(reslist); + if (res == NULL) + error("Failed in resolving remote host."); + + if (fixedhost.ss_family && fixedport) + printf("[+] Using fixed forwarding to %s,%s.\n",argv[3],argv[4]); + else + printf("[+] Using dynamic (transparent proxy) forwarding.\n"); + + bind_and_listen(fixedhost.ss_family, strncasecmp(argv[1], "udp", 3), argv[2]); + + printf("[+] Listening on port %s/%s.\n", argv[2], argv[1]); + signal(SIGPIPE,SIG_IGN); signal(SIGCHLD,sig_chld); // Am I bad coder?;> while (1) { - struct sockaddr_in s; + struct sockaddr_storage s; int x; - socklen_t l = sizeof(struct sockaddr_in); - int conho,conpo; + socklen_t l = sizeof(s); + struct sockaddr_storage conho; + in_port_t conpo; + char ipstr[INET6_ADDRSTRLEN], portstr[12]; usleep(1000); // Do not wanna select ;P if ((csock=accept(lsock,(struct sockaddr*)&s,&l))>=0) { fcntl(csock,F_SETFL,O_NONBLOCK); - printf("[+] Got incoming connection from %s:%d",inet_ntoa(s.sin_addr),ntohs(s.sin_port)); - l=sizeof(struct sockaddr_in); + getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + printf("[+] Got incoming connection from %s,%s", ipstr, portstr); + l = sizeof(s); getsockname(csock,(struct sockaddr*)&s,&l); - printf(" to %s:%d\n", inet_ntoa(s.sin_addr), ntohs(s.sin_port)); - conpo=ntohs(s.sin_port); - conho=s.sin_addr.s_addr; + getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + printf(" to %s,%s\n", ipstr, portstr); + conpo = get_port((struct sockaddr *) &s); + + memcpy(&conho, &s, sizeof(conho)); + if (fixedport) conpo=fixedport; - if (fixedhost) conho=fixedhost; - s.sin_addr.s_addr=conho; - printf("[*] Forwarding connection to %s:%d\n", inet_ntoa(s.sin_addr),conpo); + if (fixedhost.ss_family) + memcpy(&conho, &fixedhost, sizeof(conho)); + + memcpy(&s, &conho, sizeof(s)); + getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + printf("[*] Forwarding connection to %s,%s\n", ipstr, portstr); if (!(x=fork())) { int fsock; int one=1; - s.sin_addr.s_addr=conho; - s.sin_port=htons(conpo); - fsock=socket(PF_INET,strcmp(argv[1],"udp") ? SOCK_STREAM:SOCK_DGRAM,0); + + memcpy(&s, &conho, sizeof(s)); + set_port((struct sockaddr *) &s, conpo); + fsock = socket(s.ss_family, strncasecmp(argv[1], "udp", 3) ? SOCK_STREAM : SOCK_DGRAM, 0); if (connect(fsock,(struct sockaddr*)&s,l)) { printf("[!] Cannot connect to remote server, dropping connection.\n"); close(fsock);close(csock); @@ -287,7 +379,8 @@ } setsockopt(csock,SOL_SOCKET,SO_OOBINLINE,&one,sizeof(int)); setsockopt(fsock,SOL_SOCKET,SO_OOBINLINE,&one,sizeof(int)); - while (read_write_sed(fsock,csock)); + while (read_write_sed(fsock,csock)) + ; printf("[-] Client or server disconnect (%d).\n",getpid()); close(fsock); close(csock); exit(0);
signature.asc
Description: Digital signature