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);

Attachment: signature.asc
Description: Digital signature

Reply via email to