Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Oct 1996 03:33:41 +0900
From:      Masafumi NAKANE/=?ISO-2022-JP?B?GyRCQ2Y6LDJtSjgbKEI=?= <max@wide.ad.jp>
To:        freebsd-current@freebsd.org
Cc:        max@wide.ad.jp
Subject:   IIJ-PPP patch, please review
Message-ID:  <199610121833.DAA18858@mail.tky007.tth.expo96.ad.jp>

next in thread | raw e-mail | index | archive | help
----Next_Part(Sun_Oct_13_03:30:22_1996)--
Content-Type: Text/Plain; charset=us-ascii

Hi,

Recently I found a nice modification to IIJ-PPP by Hideo NORO
<norop@fastnet.or.jp>.  With this patch applied, the auto mode
(dial-on-demand mode) of IIJ-PPP doesn't require any dummy packet to
be sent before the link is established.  So, it's like true
dial-on-demand.

The features added/modified by this patch are:

1.  Added two options, ``syn'' and ``finrst'' , as the packet
filtering options to be specified in the ppp.conf file.  These are for
TCP's syn packet and fin/rst packet respectively.

2. When executed in automatic mode and netmask of the source (or
local) address given in the set ifaddr is less than 32, followings are
performed.  If these conditions are not met, normal operations are
done (just as with the non-modified version of IIJ-PPP).

2.1 For 4~5 seconds after the link is established (an address is
assigned to the tunnel device), PPP changes the source IP address in
the IP header to the assigned address if it differs from the assigned
address and re-calculate the IP checksum.

2.2 Re-calculate the checksum for TCP and UDP packets.

2.3 Change the address of the tunnel device to 0.0.0.0 upon
disconnection of the line.


The patch was originally made to work with IIJ-PPP included in the
FreeBSD 2.1.5R, and I modified it to work with the PPP in
FreeBSD-current.

I tested the modified version and it seems running fine.

Could someone review this?  If things are ok, the author of this patch
and I would like to merge this patch into FreeBSD-current.

     Thanks.

Max

----Next_Part(Sun_Oct_13_03:30:22_1996)--
Content-Type: Text/Plain; charset=us-ascii

Index: ppp/filter.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/filter.c,v
retrieving revision 1.6
diff -u -r1.6 filter.c
--- filter.c	1996/01/10 21:27:43	1.6
+++ filter.c	1996/10/12 17:30:31
@@ -238,13 +238,23 @@
     if (argc == 0)
       return(1);
   }
-  if (argc == 1) {
-    if (STREQ(*argv, "estab")) {
-      filterdata.opt.estab = 1;
+  if (argc >= 1 && STREQ(*argv, "estab")) {
+    filterdata.opt.estab = 1;
+    argc -= 1; argv += 1;
+    if (argc == 0)
+      return(1);
+  }
+  if (argc >= 1 && STREQ(*argv, "syn")) {
+    filterdata.opt.syn = 1;
+    argc -= 1; argv += 1;
+    if (argc == 0)
+      return(1);
+  }
+  if (argc >= 1 && STREQ(*argv, "finrst")) {
+    filterdata.opt.finrst = 1;
+    /* argc -= 1; argv += 1; */
+    if (argc == 0)
       return(1);
-    }
-    printf("estab is expected: %s\n", *argv);
-    return(0);
   }
   if (argc > 0)
     printf("bad src/dst port syntax: %s\n", *argv);
@@ -359,6 +369,8 @@
   printf("src:  %s (%d)\n", opname[fp->opt.srcop], fp->opt.srcport);
   printf("dst:  %s (%d)\n", opname[fp->opt.dstop], fp->opt.dstport);
   printf("estab: %d\n", fp->opt.estab);
+  printf("syn: %d\n", fp->opt.syn);
+  printf("finrst: %d\n", fp->opt.finrst);
 #endif
 
   if (val)
@@ -448,6 +460,10 @@
 	  printf(" dst %s %d", opname[fp->opt.dstop], fp->opt.dstport);
 	if (fp->opt.estab)
 	  printf(" estab");
+	if (fp->opt.syn)
+	  printf(" syn");
+	if (fp->opt.finrst)
+          printf(" finrst");
 
       }
       printf("\n");
Index: ppp/filter.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/filter.h,v
retrieving revision 1.4
diff -u -r1.4 filter.h
--- filter.h	1996/01/11 17:48:43	1.4
+++ filter.h	1996/10/12 17:30:31
@@ -65,6 +65,8 @@
     short   dstop;
     u_short dstport;
     int     estab;
+    int     syn;
+    int     finrst;
   } opt;
 };
 
Index: ppp/ip.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/ip.c,v
retrieving revision 1.9
diff -u -r1.9 ip.c
--- ip.c	1996/05/11 20:48:25	1.9
+++ ip.c	1996/10/12 17:30:31
@@ -120,7 +120,7 @@
 int direction;
 {
   struct filterent *fp = Filters[direction];
-  int gotinfo, cproto, estab, n;
+  int gotinfo, cproto, estab, syn, finrst, n;
   struct tcphdr *th;
   struct udphdr *uh;
   struct icmp *ih;
@@ -128,7 +128,7 @@
   u_short sport, dport;
 
   if (fp->action) {
-    cproto = gotinfo = estab = 0;
+    cproto = gotinfo = estab = syn = finrst = 0;
     sport = dport = 0;
     for (n = 0; n < MAXFILTERS; n++) {
       if (fp->action) {
@@ -149,17 +149,19 @@
 	      switch (pip->ip_p) {
 	      case IPPROTO_ICMP:
 		cproto = P_ICMP; ih = (struct icmp *)ptop;
-		sport = ih->icmp_type; estab = 1;
+		sport = ih->icmp_type; estab = syn = finrst = 1;
 		break;
 	      case IPPROTO_UDP:
 		cproto = P_UDP; uh = (struct udphdr *)ptop;
 		sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport);
-		estab = 1;
+		estab = syn = finrst = 1;
 		break;
 	      case IPPROTO_TCP:
 		cproto = P_TCP; th = (struct tcphdr *)ptop;
 		sport = ntohs(th->th_sport); dport = ntohs(th->th_dport);
 		estab = (th->th_flags & TH_ACK);
+		syn = (th->th_flags & TH_SYN);
+		finrst = (th->th_flags & (TH_FIN | TH_RST));
 #ifdef DEBUG
 if (estab == 0)
 logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport);
@@ -170,8 +172,8 @@
 	      }
 	      gotinfo = 1;
 #ifdef DEBUG
-logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n",
-direction, cproto, fp->opt.srcop, fp->opt.dstop, estab);
+logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d, syn = %d, finrst = %d\n",
+direction, cproto, fp->opt.srcop, fp->opt.dstop, estab, syn, finrst);
 #endif
 	    }
 #ifdef DEBUG
@@ -186,7 +188,11 @@
 		  (fp->opt.dstop == OP_NONE ||
 		  PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
 	       &&
-		  (fp->opt.estab == 0 || estab)) {
+		  (fp->opt.estab == 0 || estab)
+		&&
+		  (fp->opt.syn == 0 || syn)
+		&&
+		  (fp->opt.finrst == 0 || finrst)) {
 		return(fp->action);
 	      }
 	    }
Index: ppp/main.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/main.c,v
retrieving revision 1.22
diff -u -r1.22 main.c
--- main.c	1996/10/12 16:20:32	1.22
+++ main.c	1996/10/12 17:30:31
@@ -35,6 +35,10 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
 #include "modem.h"
 #include "os.h"
 #include "hdlc.h"
@@ -626,22 +630,144 @@
   }
 }
 
+inline
+void
+RecalcProtoCksum(buf)
+     u_char *buf;
+{
+  static u_short *bp;
+  static union {
+    struct tcphdr *th;
+    struct udphdr *uh;
+  } ph;
+  static u_char savec, *savecp;
+  static u_int hlen, plen, changes;
+  /* recalculate checksum in protocol specific header if needed */
+  switch(((struct ip *)buf)->ip_p){
+  case IPPROTO_UDP:
+    bp = (u_short *)buf;
+    bp += 2 * ((struct ip *)buf)->ip_hl;
+    ph.uh = (struct udphdr *)bp;
+    /* bp/ph.uh points to udp header */
+    ph.uh->uh_sum = 0;
+    hlen = ntohs(((struct ip *)buf)->ip_len);
+    savecp = buf + hlen;
+    savec = *savecp;
+    *savecp = (u_char)0;
+    plen = (hlen -= 4 * ((struct ip *)buf)->ip_hl);
+    changes = 0;
+    hlen++;
+    hlen /= 2;
+    for(; hlen > 0; hlen--)
+      changes += *bp++;
+    *savecp = savec;
+    /* calculate pseudo UDP header */
+    /* source address */
+    bp = (u_short *)&(((struct ip *)buf)->ip_src);
+    changes += *bp++;
+    changes += *bp++;
+    /* destination address */
+    changes += *bp++;
+    changes += *bp;
+    /* protocol */
+    changes += htons(IPPROTO_UDP); /* protocol */
+    /* UDP length */
+    changes += htons(plen);
+    changes = (changes & 0xffff) + (changes >> 16);
+    changes = (changes & 0xffff) + (changes >> 16);
+    ph.uh->uh_sum = (~changes & 0xffff);
+    LogPrintf(LOG_TCPIP, "UDP check sum is recalculated\n");
+    break;
+  case IPPROTO_TCP:
+    bp = (u_short *)buf;
+    bp += 2 * ((struct ip *)buf)->ip_hl;
+    ph.th = (struct tcphdr *)bp;
+    /* bp/ph.th points to tcp header */
+    ph.th->th_sum = 0;
+    hlen = ntohs(((struct ip *)buf)->ip_len);
+    savecp = buf + hlen;
+    savec = *savecp;
+    *savecp = (u_char)0;
+    plen = (hlen -= 4 * ((struct ip *)buf)->ip_hl);
+    changes = 0;
+    hlen++;
+    hlen /= 2;
+    for(; hlen > 0; hlen--)
+      changes += *bp++;
+    *savecp = savec;
+    /* calculate pseudo TCP header */
+    /* source address */
+    bp = (u_short *)&(((struct ip *)buf)->ip_src);
+    changes += *bp++;
+    changes += *bp++;
+    /* destination address */
+    changes += *bp++;
+    changes += *bp;
+    /* protocol */
+    changes += htons(IPPROTO_TCP); /* protocol */
+    /* TCP length */
+    changes += htons(plen);
+    changes = (changes & 0xffff) + (changes >> 16);
+    changes = (changes & 0xffff) + (changes >> 16);
+    ph.th->th_sum = (~changes & 0xffff);
+    LogPrintf(LOG_TCPIP, "TCP check sum is recalculated\n");
+    break;
+  default: /* IPPROTO_ICMP */
+  }
+}
+void
+ChangeSrcIPAddress(buf, addr)
+     u_char *buf;
+     struct in_addr addr;
+{
+  static u_int changes;
+  static u_int hlen;
+  static u_short *bp;
+  static char msgbuff[100]; /* for debugging message */
+  /* if buf has correct IP address, assume it has correct IP checksum */
+  if(((struct ip *)buf)->ip_src.s_addr != addr.s_addr){
+    if(loglevel & (1 << LOG_TCPIP)) /* for spped up when logging is disabled */
+      sprintf(msgbuff, "%s", inet_ntoa(((struct ip *)buf)->ip_src));
+    ((struct ip *)buf)->ip_src = addr;
+    ((struct ip *)buf)->ip_sum = 0;
+    /* recalculating checksum in IP header */
+    bp = (u_short *)buf;
+    changes = 0;
+    /* IP header length is (hlen * 2) bytes */
+    for(hlen = 2 * ((struct ip *)buf)->ip_hl; hlen > 0; hlen--)
+      changes += *bp++;
+    changes = (changes & 0xffff) + (changes >> 16);
+    changes = (changes & 0xffff) + (changes >> 16);
+    ((struct ip *)buf)->ip_sum = (~changes & 0xffff);
+    if(loglevel & (1 << LOG_TCPIP)) /* for spped up when logging is disabled */
+      LogPrintf(LOG_TCPIP, "Src address changed: %s ---> %s\n",
+              msgbuff,
+              inet_ntoa(((struct ip *)buf)->ip_src));
+  }
+  /* but protocol specific checksum may or may not correct */
+  RecalcProtoCksum(buf);
+}
 
 static void
 DoLoop()
 {
   fd_set rfds, wfds, efds;
   int pri, i, n, wfd;
+  int tsavelen = 0;
   struct sockaddr_in hisaddr;
   struct timeval timeout, *tp;
   int ssize = sizeof(hisaddr);
   u_char *cp;
-  u_char rbuff[MAX_MRU];
+  u_char rbuff[MAX_MRU], tbuff[MAX_MRU];
   int dial_up;
   int tries;
   int qlen;
   pid_t pgroup;
+  time_t ttimer = (time_t)0;  /* expiration timer for tun device */
+  struct in_addr oldmyaddr;
+  int recalc;                 /* recalculates checksum */
 
+  recalc = (mode & MODE_AUTO) && (DefMyAddress.width < 32);
   pgroup = getpgrp();
 
   if (mode & MODE_DIRECT) {
@@ -693,6 +819,7 @@
 	  if (VarDialTries && tries >= VarDialTries) {
 	      dial_up = FALSE;
 	      tries = 0;
+            tsavelen = 0;
 	  }
 	}
       }
@@ -726,7 +853,7 @@
 #endif
 
     /* If there are aren't many packets queued, look for some more. */
-    if (qlen < 20)
+    if (qlen < 20 && !tsavelen)
       FD_SET(tun_in, &rfds);
 
     if (netfd > -1) {
@@ -848,6 +975,19 @@
       }
     }
 
+    if (tsavelen && isOsLinkup()){
+      /* check & reassign source IP address */
+      if(recalc)
+      ChangeSrcIPAddress(tbuff, getCurMyAddr());
+        pri = PacketCheck(tbuff, tsavelen, FL_OUT);
+      if (pri >= 0){
+        IpEnqueue(pri, tbuff, tsavelen);
+      }
+      tsavelen = 0;
+      ttimer = time(NULL) + (time_t)5; /* src IP address check expires in 5 secs */
+      continue;
+    }
+
     if (FD_ISSET(tun_in, &rfds)) {	/* something to read from tun */
       n = read(tun_in, rbuff, sizeof(rbuff));
       if (n < 0) {
@@ -859,16 +999,31 @@
        *  device until IPCP is opened.
        */
       if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
-	pri = PacketCheck(rbuff, n, FL_DIAL);
+      pri = PacketCheck(rbuff, n, FL_DIAL); /* 1st time */
 	if (pri >= 0) {
-	  IpEnqueue(pri, rbuff, n);
+        oldmyaddr = DefMyAddress.ipaddr; /* getCurMyAddr(); */
+        /* IpEnqueue(pri, rbuff, n); */
+        bcopy(rbuff, tbuff, tsavelen = n);
           dial_up = TRUE;		/* XXX */
 	}
 	continue;
       }
       pri = PacketCheck(rbuff, n, FL_OUT);
-      if (pri >= 0)
+      if (pri >= 0){
+      if(recalc){ /* when ttimer is set, recalc is always TRUE */
+        if(ttimer){
+          if(ttimer > time(NULL)){
+            /* check & reassign source IP address */
+            ChangeSrcIPAddress(rbuff, getCurMyAddr());
+          }else{
+            ttimer = (time_t)0;
+          }
+        }else{
+          RecalcProtoCksum(rbuff);
+        }
+      }
 	IpEnqueue(pri, rbuff, n);
+      }
     }
   }
   logprintf("job done.\n");
Index: ppp/os.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/os.c,v
retrieving revision 1.7
diff -u -r1.7 os.c
--- os.c	1996/06/03 21:35:21	1.7
+++ os.c	1996/10/12 17:30:31
@@ -42,7 +42,7 @@
 
 static struct ifaliasreq ifra;
 static struct ifreq ifrq;
-static struct in_addr oldmine, oldhis;
+static struct in_addr oldmine, oldhis, oldmask;
 static int linkup;
 
 #ifdef bsdi
@@ -137,6 +137,7 @@
     sin->sin_len = sizeof(*sin);
 
     if (changeaddr) {
+      oldmask.s_addr = mask;
       /*
        * Interface already exists. Just change the address.
        */
@@ -200,12 +201,17 @@
 OsLinkdown()
 {
   char *s;
+  struct in_addr zeroaddr;
 
   if (linkup) {
     s = (char *)inet_ntoa(peer_addr);
     LogPrintf(LOG_LINK_BIT|LOG_LCP_BIT, "OsLinkdown: %s\n", s);
     if (!(mode & MODE_AUTO))
       DeleteIfRoutes(0);
+    if((mode & MODE_AUTO) && (DefMyAddress.width < 32)){
+      zeroaddr.s_addr = 0;
+      OsSetIpaddress(zeroaddr, oldhis, oldmask);
+    }
     linkup = 0;
   }
 }
@@ -348,6 +354,16 @@
 {
 }
 
+int
+isOsLinkup()
+{
+  return linkup;
+}
+struct in_addr
+getCurMyAddr()
+{
+  return oldmine;
+}
 void
 OsAddOutOctets(cnt)
 int cnt;
Index: ppp/os.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ppp/os.h,v
retrieving revision 1.3
diff -u -r1.3 os.h
--- os.h	1996/01/10 21:27:57	1.3
+++ os.h	1996/10/12 17:30:32
@@ -34,4 +34,6 @@
 void DeleteIfRoutes __P((int));
 void OsAddInOctets __P((int cnt));
 void OsAddOutOctets __P((int cnt));
+int isOsLinkup __P((void));
+struct in_addr getCurMyAddr __P((void));
 #endif

----Next_Part(Sun_Oct_13_03:30:22_1996)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199610121833.DAA18858>