diff -r -N -c ppp.ORG/Makefile ppp/Makefile
*** ppp.ORG/Makefile	Sun Sep 28 04:13:31 1997
--- ppp/Makefile	Wed Nov  5 21:20:21 1997
***************
*** 4,10 ****
  SRCS=	alias_cmd.c arp.c async.c auth.c ccp.c chap.c chat.c command.c \
  	filter.c fsm.c hdlc.c ip.c ipcp.c lcp.c loadalias.c log.c lqr.c \
  	main.c mbuf.c modem.c os.c pap.c pred.c route.c server.c sig.c \
! 	slcompress.c systems.c timer.c vars.c vjcomp.c
  CFLAGS+=-Wall
  LDADD+= -lmd -lcrypt -lutil
  DPADD+= ${LIBMD} ${LIBCRYPT} ${LIBUTIL}
--- 4,10 ----
  SRCS=	alias_cmd.c arp.c async.c auth.c ccp.c chap.c chat.c command.c \
  	filter.c fsm.c hdlc.c ip.c ipcp.c lcp.c loadalias.c log.c lqr.c \
  	main.c mbuf.c modem.c os.c pap.c pred.c route.c server.c sig.c \
! 	slcompress.c systems.c timer.c vars.c vjcomp.c nat.c
  CFLAGS+=-Wall
  LDADD+= -lmd -lcrypt -lutil
  DPADD+= ${LIBMD} ${LIBCRYPT} ${LIBUTIL}
diff -r -N -c ppp.ORG/command.c ppp/command.c
*** ppp.ORG/command.c	Sun Oct 12 10:51:23 1997
--- ppp/command.c	Wed Nov  5 21:20:21 1997
***************
*** 1277,1282 ****
--- 1277,1328 ----
    return -1;
  }
  
+ /* Set IP address should be translated. (NAT) */
+ static int
+ SetTranslationAddr(list, argc, argv)
+ struct cmdtab *list;
+ int argc;
+ char **argv;
+ {
+     DefTransAddress.ipaddr.s_addr = 0xffffffff;
+     if (argc > 0) {
+ 	ParseAddr(argc, argv++, &DefTransAddress.ipaddr, 
+ 		  &DefTransAddress.mask, &DefTransAddress.width);
+     }
+     /*
+      *  0.0.0.0 and 255.255.255.255 means no translation
+      */
+     if (DefTransAddress.ipaddr.s_addr == 0xffffffff || 
+ 	DefTransAddress.ipaddr.s_addr == 0) {
+ 	DefTransAddress.mask.s_addr = 0xffffffff;
+ 	DefTransAddress.width = 32;
+     }
+     return(1);
+ }
+ 
+ /* Set X server IP address translation. (NAT) */
+ static int
+ SetXTranslationAddr(list, argc, argv)
+ struct cmdtab *list;
+ int argc;
+ char **argv;
+ {
+     DefXTransAddress.ipaddr.s_addr = 0xffffffff;
+     if (argc > 0) {
+ 	ParseAddr(argc, argv++, &DefXTransAddress.ipaddr, 
+ 		  &DefXTransAddress.mask, &DefXTransAddress.width);
+     }
+     /*
+      *  0.0.0.0 and 255.255.255.255 means no translation
+      */
+     if (DefXTransAddress.ipaddr.s_addr == 0xffffffff || 
+ 	DefXTransAddress.ipaddr.s_addr == 0) {
+ 	DefXTransAddress.mask.s_addr = 0xffffffff;
+ 	DefXTransAddress.width = 32;
+     }
+     return(1);
+ }
+ 
  extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
  
  struct cmdtab const SetCommands[] = {
***************
*** 1302,1307 ****
--- 1348,1357 ----
    "Set hangup script", "set hangup chat-script", (void *) VAR_HANGUP},
    {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH,
    "Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
+   { "taddr",    NULL,   SetTranslationAddr,   LOCAL_AUTH,
+   "Set translation address", "translation-addr"},
+   { "xaddr",    NULL,   SetXTranslationAddr,  LOCAL_AUTH,
+   "Set X translation address", "xtranslation-addr"},
    {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
    "Set input filter", "set ifilter ..."},
    {"loopback", NULL, SetLoopback, LOCAL_AUTH,
diff -r -N -c ppp.ORG/filter.c ppp/filter.c
*** ppp.ORG/filter.c	Mon Sep  1 08:02:10 1997
--- ppp/filter.c	Tue Nov 18 22:07:28 1997
***************
*** 201,210 ****
      filterdata.opt.srcop = filterdata.opt.dstop = A_NONE;
      return (1);
    }
-   if (argc < 3) {
-     LogPrintf(LogWARN, "ParseUdpOrTcp: bad udp/tcp syntax.\n");
-     return (0);
-   }
    if (argc >= 3 && STREQ(*argv, "src")) {
      filterdata.opt.srcop = ParseOp(argv[1]);
      if (filterdata.opt.srcop == OP_NONE) {
--- 201,206 ----
***************
*** 233,245 ****
      if (argc == 0)
        return (1);
    }
!   if (argc == 1) {
!     if (STREQ(*argv, "estab")) {
        filterdata.opt.estab = 1;
        return (1);
!     }
!     LogPrintf(LogWARN, "ParseUdpOrTcp: estab is expected: %s\n", *argv);
!     return (0);
    }
    if (argc > 0)
      LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
--- 229,251 ----
      if (argc == 0)
        return (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);
    }
    if (argc > 0)
      LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
***************
*** 362,367 ****
--- 368,376 ----
    LogPrintf(LogDEBUG, "Parse: dst:  %s (%d)\n", opname[fp->opt.dstop],
  	    fp->opt.dstport);
    LogPrintf(LogDEBUG, "Parse: estab: %d\n", fp->opt.estab);
+   LogPrintf(LogDEBUG, "syn: %d\n", fp->opt.syn);
+   LogPrintf(LogDEBUG, "finrst: %d\n", fp->opt.finrst);
+ 
  
    if (val)
      *ofp = *fp;
***************
*** 440,445 ****
--- 449,458 ----
  		  fp->opt.dstport);
  	if (fp->opt.estab)
  	  fprintf(VarTerm, " estab");
+ 	if (fp->opt.syn)
+ 	  fprintf(VarTerm, " syn");
+ 	if (fp->opt.finrst)
+ 	  fprintf(VarTerm, " finrst");
  
        }
        fprintf(VarTerm, "\n");
diff -r -N -c ppp.ORG/filter.h ppp/filter.h
*** ppp.ORG/filter.h	Mon Aug 25 09:34:25 1997
--- ppp/filter.h	Wed Nov  5 21:20:21 1997
***************
*** 65,70 ****
--- 65,72 ----
      short dstop;
      u_short dstport;
      int estab;
+     int     syn;
+     int     finrst;
    }      opt;
  };
  
diff -r -N -c ppp.ORG/ip.c ppp/ip.c
*** ppp.ORG/ip.c	Sat Oct  4 09:16:36 1997
--- ppp/ip.c	Wed Nov  5 21:20:22 1997
***************
*** 43,48 ****
--- 43,51 ----
  
  extern void SendPppFrame();
  extern void LcpClose();
+ extern int CheckTrans();
+ extern void ChangeDestIPAddress();
+ extern int CheckCheckSum();
  
  static struct pppTimer IdleTimer;
  
***************
*** 131,137 ****
  FilterCheck(struct ip * pip, int direction)
  {
    struct filterent *fp = Filters[direction];
!   int gotinfo, cproto, estab, n;
    struct tcphdr *th;
    struct udphdr *uh;
    struct icmp *ih;
--- 134,140 ----
  FilterCheck(struct ip * pip, int direction)
  {
    struct filterent *fp = Filters[direction];
!   int gotinfo, cproto, estab, syn, finrst, n;
    struct tcphdr *th;
    struct udphdr *uh;
    struct icmp *ih;
***************
*** 139,145 ****
    u_short sport, dport;
  
    if (fp->action) {
!     cproto = gotinfo = estab = 0;
      sport = dport = 0;
      for (n = 0; n < MAXFILTERS; n++) {
        if (fp->action) {
--- 142,148 ----
    u_short sport, dport;
  
    if (fp->action) {
!     cproto = gotinfo = estab = syn = finrst = 0;
      sport = dport = 0;
      for (n = 0; n < MAXFILTERS; n++) {
        if (fp->action) {
***************
*** 160,173 ****
  		cproto = P_ICMP;
  		ih = (struct icmp *) ptop;
  		sport = ih->icmp_type;
! 		estab = 1;
  		break;
  	      case IPPROTO_UDP:
  		cproto = P_UDP;
  		uh = (struct udphdr *) ptop;
  		sport = ntohs(uh->uh_sport);
  		dport = ntohs(uh->uh_dport);
! 		estab = 1;
  		break;
  	      case IPPROTO_TCP:
  		cproto = P_TCP;
--- 163,176 ----
  		cproto = P_ICMP;
  		ih = (struct icmp *) ptop;
  		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 = syn = finrst = 1;
  		break;
  	      case IPPROTO_TCP:
  		cproto = P_TCP;
***************
*** 175,180 ****
--- 178,185 ----
  		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));
  		if (estab == 0)
  		  LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n",
  			    th->th_flags, sport, dport);
***************
*** 184,191 ****
  	      }
  	      gotinfo = 1;
  	      LogPrintf(LogDEBUG, "dir = %d, proto = %d, srcop = %d,"
! 			" dstop = %d, estab = %d\n", direction, cproto,
! 			fp->opt.srcop, fp->opt.dstop, estab);
  	    }
  	    LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d,"
  		      " dport = %d\n", n, cproto, sport, dport);
--- 189,197 ----
  	      }
  	      gotinfo = 1;
  	      LogPrintf(LogDEBUG, "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);
  	    }
  	    LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d,"
  		      " dport = %d\n", n, cproto, sport, dport);
***************
*** 198,204 ****
  		  (fp->opt.dstop == OP_NONE ||
  		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
  		  &&
! 		  (fp->opt.estab == 0 || estab)) {
  		return (fp->action);
  	      }
  	    }
--- 204,214 ----
  		  (fp->opt.dstop == OP_NONE ||
  		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
  		  &&
! 		  (fp->opt.estab == 0 || estab)
! 		  &&
! 		  (fp->opt.syn == 0 || syn)
! 		  &&
! 		  (fp->opt.finrst == 0 || finrst)) {
  		return (fp->action);
  	      }
  	    }
***************
*** 349,356 ****
  {				/* IN: Pointer to IP pakcet */
    u_char *cp;
    struct mbuf *wp;
!   int nb, nw;
    u_char tunbuff[MAX_MRU];
  
    cp = tunbuff;
    nb = 0;
--- 359,368 ----
  {				/* IN: Pointer to IP pakcet */
    u_char *cp;
    struct mbuf *wp;
!   int nb, nw, diff;
    u_char tunbuff[MAX_MRU];
+   struct in_addr realaddr;
+   int ck_sum_status;
  
    cp = tunbuff;
    nb = 0;
***************
*** 358,363 ****
--- 370,381 ----
      bcopy(MBUF_CTOP(wp), cp, wp->cnt);
      cp += wp->cnt;
      nb += wp->cnt;
+   }
+ 
+   ck_sum_status = CheckCheckSum(tunbuff);
+ 
+   if(CheckTrans(tunbuff, &realaddr, &diff)) {        /* NAT */
+       ChangeDestIPAddress(tunbuff, realaddr, diff, ck_sum_status);
    }
  
    if (mode & MODE_ALIAS) {
diff -r -N -c ppp.ORG/ipcp.c ppp/ipcp.c
*** ppp.ORG/ipcp.c	Wed Oct  8 06:56:01 1997
--- ppp/ipcp.c	Wed Nov  5 21:20:22 1997
***************
*** 47,52 ****
--- 47,53 ----
  
  struct ipcpstate IpcpInfo;
  struct in_range DefMyAddress, DefHisAddress;
+ struct in_range DefTransAddress, DefXTransAddress;
  struct in_addr TriggerAddress;
  int HaveTriggerAddress;
  
***************
*** 175,180 ****
--- 176,183 ----
        bcopy(hp->h_addr, (char *) &DefMyAddress.ipaddr.s_addr, hp->h_length);
      }
    }
+   DefTransAddress.ipaddr.s_addr = DefTransAddress.mask.s_addr = 0xffffffff;
+   DefXTransAddress.ipaddr.s_addr = DefXTransAddress.mask.s_addr = 0xffffffff;
  }
  
  void
diff -r -N -c ppp.ORG/ipcp.h ppp/ipcp.h
*** ppp.ORG/ipcp.h	Sat Sep  6 08:22:26 1997
--- ppp/ipcp.h	Wed Nov  5 21:20:22 1997
***************
*** 66,71 ****
--- 66,73 ----
  extern struct in_range DefMyAddress;
  extern struct in_range DefHisAddress;
  extern struct in_addr TriggerAddress;
+ extern struct in_range DefTransAddress;
+ extern struct in_range DefXTransAddress;
  extern int HaveTriggerAddress;
  
  #ifndef NOMSEXT
diff -r -N -c ppp.ORG/main.c ppp/main.c
*** ppp.ORG/main.c	Fri Oct 17 08:58:06 1997
--- ppp/main.c	Sun Dec 28 13:54:45 1997
***************
*** 23,28 ****
--- 23,80 ----
   *		o Add commands for traffic summary, version display, etc.
   *		o Add signal handler for misc controls.
   */
+ 
+ /*
+  *  rfc1631 : NAT(The IP Network Address Translator) is supported.
+  *  Modified by Junichi SATOH (junichi@astec.co.jp)  in 1996,1997.
+  *
+  *  * NOTICE *
+  *     IIJ-PPP in FreeBSD distributions is already include "Packet Aliasing".
+  *     Purpose of both this NAT patch and the "Packet Aliasing" is IP 
+  *     masquerade, but features are different. 
+  *
+  *     This NAT patch support more protocols than "Packet Aliasing".
+  *     For example, X, rlogin, RealAudio, VDOLiveVideo, CU-SeeMe, etc...
+  *     
+  *     After appling this NAT patch, IIJ-PPP includes both IP masquerade
+  *     codes.
+  *
+  *     ** If you use '-alias' option, don't use 'set taddr' command. **
+  *     ** If you use 'set taddr' command, don't use '-alias' option. **
+  *
+  *
+  *  Original distribution sites of NAT patch:
+  *    Japanese : http://www2a.meshnet.or.jp/~junichi/index.html
+  *    English  : http://www2a.meshnet.or.jp/~junichi/index-e.html
+  *
+  *  1996
+  *    Sep.    : first version.
+  *    Oct. 10 : Fully support of ftp(PORT mode).
+  *         18 : Fix of following bugs.
+  *              - miss calculation of SEQ and ACK number when retry
+  *                sending a packet.
+  *              - ppp process is dead by force disconnection
+  *                during ftp execution.
+  *         26 : Fix of Memory leak.
+  *              Fully support of Realaudio.
+  *         28 : Support Time limit of translation table.
+  *    Nov.  2 : Support of ICMP.
+  *    Dec. 23 : Support of Auto mapping port numbers.
+  *              Support of X server's address setting.
+  *  1997
+  *    Jan. 15 : Support of filtering incomming packets after re-addressing.
+  *              Fix of not recalculate checksum on error packets.
+  *    Feb. 15 : Support of VDO Live Video.
+  *    Mar. 29 : Change base iij-ppp source, included in 2.2.1-RELEASE.
+  *              Merge On-demand patch made by NOROP.
+  *              Support of Diablo (Thanks to Miyashita)
+  *    May. 18 : Fix VDOLive.
+  *    Jun.  7 : Fix port number changing problem.
+  *    Oct.  1 : Support CU-SeeMe (Thanks to Kawai)
+  *    Nov.  5 : Change base iij-ppp source, included in 2.2.5-RELEASE.
+  *    Dec. 28 : Fix UDP packet check sum problem.
+  */
+ 
  #include "fsm.h"
  #include <fcntl.h>
  #include <paths.h>
***************
*** 37,42 ****
--- 89,97 ----
  #include <arpa/inet.h>
  #include <netinet/in_systm.h>
  #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+ #include <netinet/udp.h>
+ #include <netinet/ip_icmp.h>
  #include <sysexits.h>
  #include "modem.h"
  #include "os.h"
***************
*** 53,58 ****
--- 108,114 ----
  #include "sig.h"
  #include "server.h"
  #include "lcpproto.h"
+ #include "nat.h"
  
  #ifndef O_NONBLOCK
  #ifdef O_NDELAY
***************
*** 67,72 ****
--- 123,129 ----
  extern void DecodeCommand(), Prompt();
  extern int aft_cmd;
  extern int IsInteractive();
+ extern int SourceAddrCheck();
  static void DoLoop(void);
  static void TerminalStop();
  static char *ex_desc();
***************
*** 80,85 ****
--- 137,147 ----
  int tunno;
  static int dial_up;
  
+ UPORT *utport[65536], *uuport[65536];
+ SPUPORT *uraport, *uvdoport, *udiaport;
+ ICMPADDR *icmpaddr;
+ u_short sub_port, real_port;
+ 
  static void
  TtyInit(int DontWantInt)
  {
***************
*** 320,325 ****
--- 382,388 ----
  {
    FILE *lockfile;
    char *name;
+   int i;
  
    VarTerm = 0;
    name = rindex(argv[0], '/');
***************
*** 327,332 ****
--- 390,402 ----
  
    argc--;
    argv++;
+   for(i = 0; i < 65536; i++) {
+       utport[i] = uuport[i] = NULL;
+   }
+   uraport = NULL;
+   uvdoport = NULL;
+   udiaport = NULL;
+   icmpaddr = NULL;
    mode = MODE_INTER;		/* default operation is interactive mode */
    netfd = modem = tun_in = -1;
    server = -2;
***************
*** 681,702 ****
    }
  }
  
  
  static void
  DoLoop()
  {
    fd_set rfds, wfds, efds;
    int pri, i, n, wfd, nfds;
    struct sockaddr_in hisaddr;
    struct timeval timeout, *tp;
    int ssize = sizeof(hisaddr);
    u_char *cp;
!   u_char rbuff[MAX_MRU];
    int tries;
    int qlen;
    int res;
    pid_t pgroup;
! 
    pgroup = getpgrp();
  
    if (mode & MODE_DIRECT) {
--- 751,1014 ----
    }
  }
  
+ inline
+ void
+ RecalcProtoCksum(buf, direction)
+ u_char *buf;
+ int direction;
+ {
+     static u_short *bp;
+     static union {
+ 	struct tcphdr *th;
+ 	struct udphdr *uh;
+ 	struct icmp *icmp;
+     } 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;
+ 	if(direction == POUT) {
+ 	    if(sub_port == 0) {
+ 		sub_port = ntohs(ph.uh->uh_sport);
+ 	    }
+ 	    ph.uh->uh_sport = 0;
+ 	} else {
+ 	    if(real_port == 0) {
+ 		real_port = ntohs(ph.uh->uh_dport);
+ 	    }
+ 	    ph.uh->uh_dport = 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 */
+ 	bp = (u_short *)&(((struct ip *)buf)->ip_dst);
+ 	changes += *bp++;
+ 	changes += *bp;
+ 	/* protocol */
+ 	changes += htons(IPPROTO_UDP); /* protocol */
+ 	/* UDP length */
+ 	changes += htons(plen);
+  
+ 	if(direction == POUT) {
+ 	    sub_port = ntohs(sub_port);
+ 	    changes += sub_port;
+ 	    ph.uh->uh_sport = sub_port;
+ 	} else {
+ 	    real_port = ntohs(real_port);
+ 	    changes += real_port;
+ 	    ph.uh->uh_dport = real_port;
+ 	}    
+ 	changes = (changes & 0xffff) + (changes >> 16);
+ 	changes = (changes & 0xffff) + (changes >> 16);
+ 	ph.uh->uh_sum = (~changes & 0xffff);
+ 	LogPrintf(LogTCPIP, "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;
+  
+ 	if(direction == POUT) {
+ 	    if(sub_port == 0) {
+ 		sub_port = ntohs(ph.th->th_sport);
+ 	    }
+ 	    ph.th->th_sport = 0;
+ 	} else {
+ 	    if(real_port == 0) {
+ 		real_port = ntohs(ph.th->th_dport);
+ 	    }
+ 	    ph.th->th_dport = 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 */
+ 	bp = (u_short *)&(((struct ip *)buf)->ip_dst);
+ 	changes += *bp++;
+ 	changes += *bp;
+ 	/* protocol */
+ 	changes += htons(IPPROTO_TCP); /* protocol */
+ 	/* TCP length */
+ 	changes += htons(plen);
+  
+ 	if(direction == POUT) {
+ 	    sub_port = ntohs(sub_port);
+ 	    changes += sub_port;
+ 	    ph.th->th_sport = sub_port;
+ 	} else {
+ 	    real_port = ntohs(real_port);
+ 	    changes += real_port;
+ 	    ph.th->th_dport = real_port;
+ 	}
+ 	changes = (changes & 0xffff) + (changes >> 16);
+ 	changes = (changes & 0xffff) + (changes >> 16);
+ 	ph.th->th_sum = (~changes & 0xffff);
+  
+ 	LogPrintf(LogTCPIP, "TCP check sum is recalculated\n");
+ 	break;
+     case IPPROTO_ICMP:
+ 	break;
+     default:
+ 	break;
+     }
+ }
+  
+ 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(LogIsKept(LogTCPIP)) /* 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(LogIsKept(LogTCPIP)) /* for spped up when logging is disabled */
+ 	 LogPrintf(LogTCPIP, "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, POUT);
+ }
+ 
+ /* Change ACK number */
+ void
+ ChangeACKnumber(buf, diff)
+ u_char *buf;
+ int diff;
+ {
+     static u_short *ipheader;
+     static struct tcphdr *tcpheader;
+     u_long acknumber;
+ 
+     switch(((struct ip *)buf)->ip_p) {
+     case IPPROTO_TCP:
+ 	ipheader = (u_short *)buf;
+ 	tcpheader = 
+ 	  (struct tcphdr *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	acknumber = ntohl(tcpheader->th_ack);
+ 	acknumber -= diff;
+ 	tcpheader->th_ack = ntohl(acknumber);
+ 	break;
+     default:
+ 	break;
+      }
+ }
+ 
+ /* Change destination IP address */
+ void
+ ChangeDestIPAddress(buf, realaddr, diff, ck_sum_status)
+ u_char *buf;
+ struct in_addr realaddr;
+ int diff;
+ int ck_sum_status;
+ {
+     static u_int changes;
+     static u_int hlen;
+     static u_short *bp;
+  
+     /* Change destination IP address */
+     ((struct ip *)buf)->ip_dst = realaddr;
+     ((struct ip *)buf)->ip_sum = 0;
+  
+     /* Change ACK number */
+     if(diff) {
+ 	ChangeACKnumber(buf, diff);
+     }
+  
+     /* 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);
+     if(ck_sum_status == 0) {
+ 	((struct ip *)buf)->ip_sum = (~changes & 0xffff);
+     }
+      
+     /* but protocol specific checksum may or may not correct */
+     if(ck_sum_status == 0) {
+ 	RecalcProtoCksum(buf, PIN);
+     }
+ }
  
  static void
  DoLoop()
  {
    fd_set rfds, wfds, efds;
    int pri, i, n, wfd, nfds;
+   int tsavelen = 0;
    struct sockaddr_in hisaddr;
    struct timeval timeout, *tp;
    int ssize = sizeof(hisaddr);
    u_char *cp;
!   u_char rbuff[MAX_MRU], tbuff[MAX_MRU];
    int tries;
    int qlen;
    int res;
    pid_t pgroup;
!   time_t ttimer = (time_t)0;    /* expiration timer for tun device */
!   struct in_addr oldmyaddr;
!   int recalc;                   /* recalculates checksum */
!   int nat;                      /* network address translator */
!   
!   recalc = (mode & MODE_AUTO) && (DefMyAddress.width < 32);
    pgroup = getpgrp();
  
    if (mode & MODE_DIRECT) {
***************
*** 810,815 ****
--- 1122,1128 ----
  	    reconnectState = RECON_UNKNOWN;
  	    reconnectCount = 0;
  	    tries = 0;
+ 	    tsavelen = 0;
  	  } else if (VarNextPhone == NULL)
  	    /* Dial failed. Keep quite during redial wait period. */
  	    StartRedialTimer(VarRedialTimeout);
***************
*** 855,861 ****
  #endif
  
      /* If there are aren't many packets queued, look for some more. */
!     if (qlen < 20 && tun_in >= 0) {
        if (tun_in + 1 > nfds)
  	nfds = tun_in + 1;
        FD_SET(tun_in, &rfds);
--- 1168,1174 ----
  #endif
  
      /* If there are aren't many packets queued, look for some more. */
!     if (qlen < 20 && tun_in >= 0 && !tsavelen) {
        if (tun_in + 1 > nfds)
  	nfds = tun_in + 1;
        FD_SET(tun_in, &rfds);
***************
*** 964,969 ****
--- 1277,1296 ----
  	}
        }
      }
+     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)30; /* src IP address check expires in 5 secs */
+ 	continue;
+     }
+ 
      if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
  							 * from tun */
        n = read(tun_in, rbuff, sizeof(rbuff));
***************
*** 997,1020 ****
         * device until IPCP is opened.
         */
        if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
! 	pri = PacketCheck(rbuff, n, FL_DIAL);
  	if (pri >= 0) {
  	  if (mode & MODE_ALIAS) {
  	    VarPacketAliasOut(rbuff, sizeof rbuff);
  	    n = ntohs(((struct ip *) rbuff)->ip_len);
  	  }
! 	  IpEnqueue(pri, rbuff, n);
  	  dial_up = TRUE;	/* XXX */
  	}
  	continue;
        }
        pri = PacketCheck(rbuff, n, FL_OUT);
        if (pri >= 0) {
! 	if (mode & MODE_ALIAS) {
! 	  VarPacketAliasOut(rbuff, sizeof rbuff);
! 	  n = ntohs(((struct ip *) rbuff)->ip_len);
  	}
- 	IpEnqueue(pri, rbuff, n);
        }
      }
    }
--- 1324,1365 ----
         * device until IPCP is opened.
         */
        if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
! 	pri = PacketCheck(rbuff, n, FL_DIAL); /* 1st time */
  	if (pri >= 0) {
+ 	  oldmyaddr = DefMyAddress.ipaddr; /* getCurMyAddr(); */
  	  if (mode & MODE_ALIAS) {
  	    VarPacketAliasOut(rbuff, sizeof rbuff);
  	    n = ntohs(((struct ip *) rbuff)->ip_len);
  	  }
! 	  /* IpEnqueue(pri, rbuff, n); */
! 	  bcopy(rbuff, tbuff, tsavelen = n);
  	  dial_up = TRUE;	/* XXX */
  	}
  	continue;
        }
        pri = PacketCheck(rbuff, n, FL_OUT);
        if (pri >= 0) {
! 	nat = SourceAddrCheck(rbuff, &n);
! 	if(nat >= 0) {
! 	    if(recalc || nat) {
! 		/* when ttimer is set, recalc is always TRUE */
! 		if(ttimer || nat) {
! 		    if(ttimer > time(NULL) || nat){
! 			/* check & reassign source IP address */
! 			ChangeSrcIPAddress(rbuff, getCurMyAddr());
! 		    }else{
! 			ttimer = (time_t)0;
! 		    }
! 		}else{
! 		    RecalcProtoCksum(rbuff, POUT);
! 		}
! 	    }
! 	    if (mode & MODE_ALIAS) {
! 		VarPacketAliasOut(rbuff, sizeof rbuff);
! 		n = ntohs(((struct ip *) rbuff)->ip_len);
! 	    }
! 	    IpEnqueue(pri, rbuff, n);
  	}
        }
      }
    }
diff -r -N -c ppp.ORG/nat.c ppp/nat.c
*** ppp.ORG/nat.c	Thu Jan  1 09:00:00 1970
--- ppp/nat.c	Sat Dec 27 14:14:57 1997
***************
*** 0 ****
--- 1,905 ----
+ /*
+  *  NAT module for iij-ppp
+  *    Programmed by Junichi SATOH (junichi@astec.co.jp) in 1996,1997.
+  */
+ 
+ #include "fsm.h"
+ #include <string.h>
+ #include <fcntl.h>
+ #include <paths.h>
+ #include <sys/time.h>
+ #include <termios.h>
+ #include <signal.h>
+ #include <sys/wait.h>
+ #include <errno.h>
+ #include <netdb.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 <netinet/ip_icmp.h>
+ #include <time.h>
+ #include "modem.h"
+ #include "os.h"
+ #include "hdlc.h"
+ #include "ccp.h"
+ #include "lcp.h"
+ #include "ipcp.h"
+ #include "loadalias.h"
+ #include "vars.h"
+ #include "auth.h"
+ #include "filter.h"
+ #include "systems.h"
+ #include "ip.h"
+ #include "nat.h"
+ 
+ static UPORT *GetUPortPointer();
+ static UPORT *GetPortPointer();
+ static void cu_check_out();
+ static void cu_check_in();
+ 
+ extern UPORT *utport[65536], *uuport[65536];
+ extern SPUPORT *uraport, *uvdoport, *udiaport;
+ extern ICMPADDR *icmpaddr;
+ extern u_short sub_port, real_port;
+ 
+ /* get pointer to table of PORT and IP ADDERSS for UDP */
+ UPORT *
+ GetUPortPointer(buf, sport, real_port, subport, sc_status)
+ u_char *buf;
+ u_short sport;
+ u_short real_port;
+ u_short *subport;
+ int sc_status;
+ {
+     UPORT *recstart, *tmp_uuport = NULL, *prev_uuport, *ret_port;
+ 
+     *subport = sport;
+     if(uuport[sport] != NULL) {
+ 	recstart = uuport[sport];
+ 	prev_uuport = NULL;
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_dst.s_addr) {
+ 		if(recstart->lm_time + KEEP_UDP < time(NULL) ||
+ 		   recstart->srcaddr.s_addr == ((struct ip *)buf)->ip_src.s_addr) {
+ 		    tmp_uuport = recstart;
+ 		    tmp_uuport->real_port = real_port;
+ 		    tmp_uuport->subport = *subport;
+ 		    break;
+ 		} else {
+ 		    sport--;
+ 		    if(sport < 1000) {
+ 			sport = 30000;
+ 		    }
+ 		    ret_port = GetUPortPointer(buf, sport, real_port, 
+ 					       subport, sc_status);
+ 		    tmp_uuport = (UPORT*)malloc(sizeof(UPORT));
+ 		    tmp_uuport->next = uuport[sport];
+ 		    uuport[sport] = tmp_uuport;
+ 		    tmp_uuport->subport = *subport;
+ 		    tmp_uuport->real_port = real_port;
+ 		    tmp_uuport->dstaddr.s_addr = 
+ 		      ((struct ip *)buf)->ip_dst.s_addr;
+ 		    if(sc_status == 1) {
+ 			tmp_uuport->srcaddr.s_addr =
+ 			  ((struct ip *)buf)->ip_src.s_addr;
+ 		    } else {
+ 			tmp_uuport->srcaddr.s_addr = 0xffffffff;
+ 		    }
+ 		    return ret_port;
+ 		}
+ 	    }
+ 	    if(recstart->lm_time + KEEP_UDP < time(NULL) && prev_uuport) {
+ 		prev_uuport->next = recstart->next;
+ 		free(recstart);
+ 		recstart = prev_uuport->next;
+ 	    } else {
+ 		prev_uuport = recstart;
+ 		recstart = recstart->next;
+ 	    }
+ 	}
+ 	if(recstart == NULL) {
+ 	    tmp_uuport = (UPORT*)malloc(sizeof(UPORT));
+ 	    tmp_uuport->next = uuport[sport];
+ 	    tmp_uuport->real_port = real_port;
+ 	    tmp_uuport->subport = *subport;
+ 	    uuport[sport] = tmp_uuport;
+ 	}
+     } else {
+ 	uuport[sport] = (UPORT*)malloc(sizeof(UPORT));
+ 	uuport[sport]->next = NULL;
+ 	uuport[sport]->real_port = real_port;
+ 	uuport[sport]->subport = *subport;
+ 	tmp_uuport = uuport[sport];
+     }
+     return tmp_uuport;
+ }
+ 
+ /* get pointer to table of PORT and IP ADDERSS for TCP */
+ UPORT *
+ GetPortPointer(buf, sport, real_port, subport, sc_status)
+     u_char *buf;
+     u_short sport;
+     u_short real_port;
+     u_short *subport;
+     int sc_status;
+ {
+     UPORT *recstart, *tmp_utport = NULL, *ret_port;
+     struct in_addr myaddr;
+ 
+     *subport = sport;
+     if(utport[sport] != NULL) {
+ 	recstart = utport[sport];
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_dst.s_addr) {
+ 		myaddr = getCurMyAddr();
+ 		if(recstart->flag == 0 && 
+ 		   recstart->srcaddr.s_addr != ((struct ip *)buf)->ip_src.s_addr &&
+ 		   !(recstart->srcaddr.s_addr == 0xffffffff && ((struct ip *)buf)->ip_src.s_addr == myaddr.s_addr)) {
+ 		    sport--;
+ 		    if(sport < 1000) {
+ 			sport = 30000;
+ 		    }
+ 		    ret_port = GetPortPointer(buf, sport, real_port, 
+ 					      subport, sc_status);
+ 		    tmp_utport = (UPORT*)malloc(sizeof(UPORT));
+ 		    tmp_utport->next = utport[sport];
+ 		    utport[sport] = tmp_utport;
+ 		    tmp_utport->subport = *subport;
+ 		    tmp_utport->real_port = real_port;
+ 		    tmp_utport->dstaddr.s_addr = 
+ 		      ((struct ip *)buf)->ip_dst.s_addr;
+ 		    if(sc_status == 1) {
+ 			tmp_utport->srcaddr.s_addr =
+ 			  ((struct ip *)buf)->ip_src.s_addr;
+ 		    } else {
+ 			tmp_utport->srcaddr.s_addr = 0xffffffff;
+ 		    }
+ 		    return ret_port;
+ 		} else {
+ 		    tmp_utport = recstart;
+ 		    break;
+ 		}
+ 	    }
+ 	    recstart = recstart->next;
+ 	}
+ 	if(recstart == NULL) {
+ 	    tmp_utport = (UPORT*)malloc(sizeof(UPORT));
+ 	    tmp_utport->next = utport[sport];
+ 	    tmp_utport->real_port = real_port;
+ 	    tmp_utport->subport = *subport;
+ 	    utport[sport] = tmp_utport;
+ 	}
+     } else {
+ 	utport[sport] = (UPORT*)malloc(sizeof(UPORT));
+ 	utport[sport]->next = NULL;
+ 	utport[sport]->real_port = real_port;
+ 	utport[sport]->subport = *subport;
+ 	tmp_utport = utport[sport];
+     }
+     return tmp_utport;
+ }
+ 
+ /* get pointer to table of IP ADDERSS for ICMP */
+ ICMPADDR*
+ GetICMPAddrPointer(buf)
+     u_char *buf;
+ {
+     ICMPADDR *tmp_icmpaddr = NULL, *icmp_recstart, *prev_icmpaddr;
+ 
+     if(icmpaddr != NULL) {
+ 	icmp_recstart = icmpaddr;
+ 	prev_icmpaddr = NULL;
+ 	while(icmp_recstart) {
+ 	    if(icmp_recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_dst.s_addr) {
+ 		tmp_icmpaddr = icmp_recstart;
+ 		break;
+ 	    }
+ 	    if(icmp_recstart->lm_time + KEEP_ICMP < time(NULL) && 
+ 	       prev_icmpaddr) {
+ 		prev_icmpaddr->next = icmp_recstart->next;
+ 		free(icmp_recstart);
+ 		icmp_recstart = prev_icmpaddr->next;
+ 	    } else {
+ 		prev_icmpaddr = icmp_recstart;
+ 		icmp_recstart = icmp_recstart->next;
+ 	    }
+ 	}
+ 	if(icmp_recstart == NULL) {
+ 	    tmp_icmpaddr = (ICMPADDR*)malloc(sizeof(ICMPADDR));
+ 	    tmp_icmpaddr->next = icmpaddr;
+ 	    icmpaddr = tmp_icmpaddr;
+ 	}
+     } else {
+ 	icmpaddr = (ICMPADDR*)malloc(sizeof(UPORT));
+ 	icmpaddr->next = NULL;
+ 	tmp_icmpaddr = icmpaddr;
+     }
+     return tmp_icmpaddr;
+ }
+ 
+ /* Change SEQ number */
+ void
+ ChangeSEQnumber(buf, diff)
+ u_char *buf;
+ int diff;
+ {
+     static u_short *ipheader;
+     static struct tcphdr *tcpheader;
+     u_long seqnumber;
+ 
+     switch(((struct ip *)buf)->ip_p) {
+     case IPPROTO_TCP:
+ 	ipheader = (u_short *)buf;
+ 	tcpheader = 
+ 	  (struct tcphdr *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	seqnumber = ntohl(tcpheader->th_seq);
+ 	seqnumber += diff;
+ 	tcpheader->th_seq = ntohl(seqnumber);
+ 	break;
+     default:
+ 	break;
+     }
+ }
+ 
+ void
+ write_subport_difftmp(tmp_utport)
+ UPORT *tmp_utport;
+ {
+     UPORT *recstart;
+ 
+     recstart = utport[tmp_utport->subport];
+     while(recstart) {
+ 	if(recstart->dstaddr.s_addr == tmp_utport->dstaddr.s_addr &&
+ 	   recstart->srcaddr.s_addr == tmp_utport->srcaddr.s_addr) {
+ 	    recstart->diff_tmp = tmp_utport->diff_tmp;
+ 	}
+ 	recstart = recstart->next;
+     }
+ }
+ 
+ /* Check source IP address and record original information, IP, port.... */
+ int
+ SourceAddrCheck(buf, n)
+      u_char *buf;
+      int *n;
+ {
+     static u_short *ipheader;
+     static struct udphdr *udpheader;
+     static struct tcphdr *tcpheader;
+     static struct icmp *icmpheader;
+     static u_short sport, dport, subport, ftpport, ftpsubport;
+     static int ipaddr[5], port[3];
+     UPORT *recstart, *tmp_uuport = NULL, *tmp_utport = NULL;
+     UPORT *data_utport = NULL, *prev_utport;
+     ICMPADDR *tmp_icmpaddr;
+     SPUPORT *tmp_uraport, *tmp_uvdoport, *tmp_udiaport;
+     int sc_status = 0, i, len;
+     char *tcpdata;
+     static char ipbuf[20];
+     int orglen, newlen;
+     static u_short iplen;
+ 
+     if((DefTransAddress.ipaddr.s_addr & DefTransAddress.mask.s_addr) == 
+        (((struct ip*)buf)->ip_src.s_addr & DefTransAddress.mask.s_addr) ||
+        ((struct ip*)buf)->ip_src.s_addr == 0) {
+ 	sc_status = 1;
+     }
+     ipheader = (u_short *)buf;
+     switch(((struct ip *)buf)->ip_p) {
+     case IPPROTO_UDP:
+ 	sub_port = 0;
+ 	udpheader = 
+ 	  (struct udphdr *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	sport = ntohs(udpheader->uh_sport);
+ 	dport = ntohs(udpheader->uh_dport);
+ 	tmp_uuport = GetUPortPointer(buf, sport, sport, &subport, sc_status);
+ 	if(sc_status == 1) {
+ 	    tmp_uuport->srcaddr.s_addr = ((struct ip *)buf)->ip_src.s_addr;
+ 	} else {
+ 	    tmp_uuport->srcaddr.s_addr = 0xffffffff;
+ 	}
+ 	tmp_uuport->dstaddr.s_addr = ((struct ip *)buf)->ip_dst.s_addr;
+ 	tmp_uuport->lm_time = time(NULL);
+ 	if(dport == CUSeeMe) {
+ 	    cu_check_out(buf);
+ 	}
+ 	break;
+     case IPPROTO_TCP:
+ 	sub_port = 0;
+ 	tcpheader = 
+ 	  (struct tcphdr *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	sport = ntohs(tcpheader->th_sport);
+ 	dport = ntohs(tcpheader->th_dport);
+ 	if(sport >= XPORT_BEGIN && sport <= XPORT_END) {
+ 	    break;
+ 	}
+ 	if(tcpheader->th_flags == TH_SYN) {
+ 	    tmp_utport = GetPortPointer(buf, sport, sport, &subport, sc_status);
+ 	    sub_port = subport;
+ 	    if(tmp_utport == NULL) {
+ 		return -1;
+ 	    }
+ 	    if(sc_status == 1) {
+ 		tmp_utport->srcaddr.s_addr = ((struct ip *)buf)->ip_src.s_addr;
+ 	    } else {
+ 		tmp_utport->srcaddr.s_addr = 0xffffffff;
+ 	    }
+ 	    tmp_utport->dstaddr.s_addr = ((struct ip *)buf)->ip_dst.s_addr;
+ 	    tmp_utport->diff = 0;
+ 	    tmp_utport->diff_tmp = 0;
+ 	    tmp_utport->flag = 0;
+ 	    tmp_utport->lm_time = time(NULL);
+ 	    if(dport == RealAudio && sc_status == 1) {
+ 		tmp_uraport = (SPUPORT*)malloc(sizeof(SPUPORT));
+ 		tmp_uraport->udplink = tmp_utport;
+ 		tmp_uraport->next = uraport;
+ 		uraport = tmp_uraport;
+ 	    }
+ 	    if((dport == VDO1 || dport == VDO2) && sc_status == 1) {
+ 		tmp_uvdoport = (SPUPORT*)malloc(sizeof(SPUPORT));
+ 		tmp_uvdoport->udplink = tmp_utport;
+ 		tmp_uvdoport->next = uvdoport;
+ 		uvdoport = tmp_uvdoport;
+ 	    }
+ 	    if((dport == DIATCP0 || dport == DIATCP1) && sc_status == 1) {
+                 tmp_udiaport = (SPUPORT*)malloc(sizeof(SPUPORT));
+                 tmp_udiaport->udplink = tmp_utport;
+                 tmp_udiaport->next = udiaport;
+                 udiaport = tmp_udiaport;
+             }
+ 	}
+ 	if((tcpheader->th_flags & TH_FIN) == TH_FIN) {
+ 	    recstart = utport[sport];
+ 	    prev_utport = NULL;
+ 	    while(recstart) {
+ 		if(recstart->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_dst.s_addr) {
+ 		    recstart->flag |= 1;
+ 		    recstart->lm_time = time(NULL);
+ 		    sub_port = recstart->subport;
+ 		}
+ 		if(recstart->lm_time + KEEP_TCP < time(NULL) && prev_utport) {
+ 		    prev_utport->next = recstart->next;
+ 		    free(recstart);
+ 		    recstart = prev_utport->next;
+ 		} else {
+ 		    prev_utport = recstart;
+ 		    recstart = recstart->next;
+ 		}
+ 	    }
+ 	}
+ 	if(dport == FTPctrl && sc_status == 1) {
+ 	    tmp_utport = utport[sport];
+ 	    while(tmp_utport) {
+ 		if(tmp_utport->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_dst.s_addr) {
+ 		    sub_port = tmp_utport->subport;
+ 		    break;
+ 		}
+ 		tmp_utport = tmp_utport->next;
+ 	    }
+ 	    if(tmp_utport) {
+ 		if(tmp_utport->diff) {
+ 		    ChangeSEQnumber(buf, tmp_utport->diff);
+ 		}
+ 	    }
+ 	    tcpdata = (char*)tcpheader + tcpheader->th_off * 4;
+ 	    if(strncmp(tcpdata, "PORT", 4) == 0) {
+ 		sscanf(tcpdata, "PORT %d,%d,%d,%d,%d,%d", 
+ 		       &ipaddr[0], &ipaddr[1], &ipaddr[2], &ipaddr[3],
+ 		       &port[0], &port[1]);
+ 		ftpport = port[0] * 256 + port[1];
+ 		data_utport = GetPortPointer(buf, ftpport, ftpport, 
+ 					     &ftpsubport, sc_status);
+ 		if(data_utport != NULL) {
+ 		    data_utport->srcaddr.s_addr = 
+ 		      ((struct ip *)buf)->ip_src.s_addr;
+ 		    data_utport->dstaddr.s_addr = 
+ 		      ((struct ip *)buf)->ip_dst.s_addr;
+ 		    data_utport->flag = 0;
+ 		    data_utport->lm_time = time(NULL);
+ 		}
+ 		
+ 		orglen = ntohs(((struct ip *)buf)->ip_len) -
+ 		  (4 * ((struct ip *)buf)->ip_hl + tcpheader->th_off * 4);
+ 		sprintf(ipbuf, "%s", inet_ntoa(getCurMyAddr()));
+ 		len = strlen(ipbuf);
+ 		for(i = 0; i < len; i++) {
+ 		    if(ipbuf[i] == '.') {
+ 			ipbuf[i] = ',';
+ 		    }
+ 		}
+ 		port[0] = ftpsubport >> 8;
+ 		port[1] = ftpsubport & 0xff;
+ 		sprintf(tcpdata, "PORT %s,%d,%d\r\n", 
+ 			ipbuf, port[0], port[1]);
+ 		newlen = strlen(tcpdata);
+ 		
+ 		if(tmp_utport) {
+ 		    tmp_utport->diff_tmp = (newlen - orglen);
+ 		    if(sport != subport) {
+ 			write_subport_difftmp(tmp_utport);
+ 		    }
+ 		}
+ 		iplen = ntohs(((struct ip *)buf)->ip_len);
+ 		iplen += (newlen - orglen);
+ 		*n = iplen;
+ 		((struct ip *)buf)->ip_len = ntohs(iplen);
+ 	    }
+ 	}
+ 	if(sub_port == 0) {
+ 	    tmp_utport = utport[sport];
+ 	    while(tmp_utport) {
+ 		if(tmp_utport->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_dst.s_addr) {
+ 		    if(tmp_utport->srcaddr.s_addr ==
+ 		       ((struct ip *)buf)->ip_src.s_addr ||
+ 		       tmp_utport->srcaddr.s_addr == 0xffffffff) {
+ 			sub_port = tmp_utport->subport;
+ 		    }
+ 		    break;
+ 		}
+ 		tmp_utport = tmp_utport->next;
+ 	    }
+ 	}
+ 	if(sub_port != sport && sub_port) {
+ 	    sc_status = 1;
+ 	}
+ 	break;
+     case IPPROTO_ICMP:
+ 	sub_port = 0;
+ 	icmpheader = 
+ 	  (struct icmp *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	if(icmpheader->icmp_type == ICMP_ECHO) {
+ 	    tmp_icmpaddr = GetICMPAddrPointer(buf);
+ 	    if(sc_status == 1) {
+ 		tmp_icmpaddr->srcaddr.s_addr = 
+ 		  ((struct ip *)buf)->ip_src.s_addr;
+ 	    } else {
+ 		tmp_icmpaddr->srcaddr.s_addr = 0xffffffff;
+ 	    }
+ 	    tmp_icmpaddr->dstaddr.s_addr = ((struct ip *)buf)->ip_dst.s_addr;
+ 	    tmp_icmpaddr->lm_time = time(NULL);
+ 	}
+ 	break;
+     default:
+ 	break;
+     }
+ 
+     return sc_status;
+ }
+ 
+ void
+ write_realport_diff(subport)
+ UPORT *subport;
+ {
+     UPORT *recstart;
+ 
+     recstart = utport[subport->real_port];
+     while(recstart) {
+ 	if(recstart->dstaddr.s_addr == subport->dstaddr.s_addr &&
+ 	   recstart->srcaddr.s_addr == subport->srcaddr.s_addr) {
+ 	    recstart->diff_tmp = subport->diff_tmp;
+ 	    recstart->diff = subport->diff;
+ 	}
+ 	recstart = recstart->next;
+     }
+ }
+ 
+ SPUPORT* CheckSpecialUDP(SPUPORT *spport, u_char *buf, int dport, 
+ 			 struct in_addr *realaddr)
+ {
+     SPUPORT *prev_spport, *tmp_spport;
+     UPORT *tmp_uuport;
+ 
+     prev_spport = NULL;
+     tmp_spport = spport;
+     while(tmp_spport) {
+ 	if(tmp_spport->udplink->dstaddr.s_addr == 
+ 	   ((struct ip *)buf)->ip_src.s_addr) {
+ 	    if(prev_spport == NULL) {
+ 		spport = tmp_spport->next;
+ 	    } else {
+ 		prev_spport->next = tmp_spport->next;
+ 	    }
+ 	    realaddr->s_addr = tmp_spport->udplink->srcaddr.s_addr;
+ 	    tmp_uuport = (UPORT*)malloc(sizeof(UPORT));
+ 	    tmp_uuport->srcaddr.s_addr = 
+ 	      tmp_spport->udplink->srcaddr.s_addr;
+ 	    tmp_uuport->dstaddr.s_addr = 
+ 	      tmp_spport->udplink->dstaddr.s_addr;
+ 	    tmp_uuport->next = uuport[dport];
+ 	    tmp_uuport->real_port = dport;
+ 	    tmp_uuport->subport = dport;
+ 	    uuport[dport] = tmp_uuport;
+ 	    free(tmp_spport);
+ 	    break;
+ 	}
+ 	prev_spport = tmp_spport;
+ 	tmp_spport = tmp_spport->next;
+     }
+     return spport;
+ }
+ 
+ /* Check if packet should be translated */
+ int
+ CheckTrans(buf, realaddr, diff)
+     u_char *buf;
+     struct in_addr *realaddr;
+     int *diff;
+ {
+     static u_short *ipheader;
+     static struct udphdr *udpheader;
+     static struct tcphdr *tcpheader;
+     static struct icmp *icmpheader;
+     static u_short sport, dport;
+     static int ch_flag;
+     UPORT *recstart;
+     ICMPADDR *icmp_recstart;
+     static struct ip *er_ipheader;
+ 
+     ch_flag = 0;
+     ipheader = (u_short *)buf;
+     switch(((struct ip *)buf)->ip_p){
+     case IPPROTO_UDP:
+ 	udpheader = 
+ 	  (struct udphdr *)((char*)ipheader + 
+ 			    (((struct ip *)buf)->ip_hl << 2));
+ 	sport = ntohs(udpheader->uh_sport);
+ 	dport = ntohs(udpheader->uh_dport);
+ 	/* Check RealAudio UDP packet. */
+ 	if(dport >= RAUDP_L && dport <= RAUDP_H) {
+ 	    uraport = CheckSpecialUDP(uraport, buf, dport, realaddr);
+ 	}
+ 	/* Check Diablo UDP packet. */
+ 	if(dport == DIAUDP0) {
+ 	    udiaport = CheckSpecialUDP(udiaport, buf, dport, realaddr);
+         }
+ 	/* Check VDOLiveVideo UDP packet. */
+ 	uvdoport = CheckSpecialUDP(uvdoport, buf, dport, realaddr);
+ 	recstart = uuport[dport];
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_src.s_addr) {
+ 		if(recstart->srcaddr.s_addr != 0xffffffff) {
+ 		    realaddr->s_addr = recstart->srcaddr.s_addr;
+ 		    if(dport == CUSeeMe) {
+ 			cu_check_in(buf, recstart);
+ 		    }
+ 		    ch_flag = 1;
+ 		}
+ 		real_port = recstart->real_port;
+ 		break;
+ 	    }
+ 	    recstart = recstart->next;
+ 	}
+ 	break;
+     case IPPROTO_TCP:
+ 	tcpheader = 
+ 	  (struct tcphdr *)((char*)ipheader + 
+ 			    (((struct ip *)buf)->ip_hl << 2));
+ 	sport = ntohs(tcpheader->th_sport);
+ 	dport = ntohs(tcpheader->th_dport);
+ 	if(dport >= XPORT_BEGIN && dport <= XPORT_END) {
+ 	    if(DefXTransAddress.ipaddr.s_addr != 0 &&
+ 	       DefXTransAddress.ipaddr.s_addr != 0xffffffff) {
+ 		realaddr->s_addr = DefXTransAddress.ipaddr.s_addr;
+ 		real_port = dport;
+ 		ch_flag = 1;
+ 		break;
+ 	    }
+ 	}
+ 	recstart = utport[dport];
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_src.s_addr) {
+ 		if(recstart->srcaddr.s_addr != 0xffffffff) {
+ 		    realaddr->s_addr = recstart->srcaddr.s_addr;
+ 		    if((tcpheader->th_flags & TH_FIN) == TH_FIN) {
+ 			recstart->flag |= 2;
+ 		    }
+ 		    ch_flag = 1;
+ 		    recstart->diff += recstart->diff_tmp;
+ 		    recstart->diff_tmp = 0;
+ 		    if(dport != recstart->real_port) {
+ 			write_realport_diff(recstart);
+ 		    }
+ 		    *diff = recstart->diff;
+ 		}
+ 		real_port = recstart->real_port;
+ 		break;
+ 	    }
+ 	    recstart = recstart->next;
+ 	}
+ 	break;
+     case IPPROTO_ICMP:
+ 	icmpheader = 
+ 	  (struct icmp *)(ipheader + 2 * ((struct ip *)buf)->ip_hl);
+ 	if(icmpheader->icmp_type == ICMP_ECHOREPLY) {
+ 	    icmp_recstart = icmpaddr;
+ 	    while(icmp_recstart) {
+ 		if(icmp_recstart->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_src.s_addr) {
+ 		    if(icmp_recstart->srcaddr.s_addr != 0xffffffff) {
+ 			realaddr->s_addr = icmp_recstart->srcaddr.s_addr;
+ 			ch_flag = 1;
+ 		    }
+ 		    break;
+ 		}
+ 		icmp_recstart = icmp_recstart->next;
+ 	    }
+ 	}
+ 	if(icmpheader->icmp_type == ICMP_UNREACH || 
+ 	   icmpheader->icmp_type == ICMP_TIMXCEED) {
+ 	    er_ipheader = &icmpheader->icmp_ip;
+ 	    switch(er_ipheader->ip_p) {
+ 	    case IPPROTO_UDP:
+ 		udpheader = 
+ 		  (struct udphdr *)((char*)er_ipheader + 
+ 				    (er_ipheader->ip_hl << 2));
+ 		sport = ntohs(udpheader->uh_sport);
+ 		dport = ntohs(udpheader->uh_dport);
+ 		recstart = uuport[sport];
+ 		while(recstart) {
+ 		    if(recstart->dstaddr.s_addr == 
+ 		       er_ipheader->ip_dst.s_addr) {
+ 			if(recstart->srcaddr.s_addr != 0xffffffff) {
+ 			    realaddr->s_addr = recstart->srcaddr.s_addr;
+ 			    ch_flag = 1;
+ 			}
+ 			real_port = recstart->real_port;
+ 			break;
+ 		    }
+ 		    recstart = recstart->next;
+ 		}
+ 		break;
+ 	    case IPPROTO_TCP:
+ 		tcpheader = 
+ 		  (struct tcphdr *)(er_ipheader + 2 * er_ipheader->ip_hl);
+ 		sport = ntohs(tcpheader->th_sport);
+ 		dport = ntohs(tcpheader->th_dport);
+ 		recstart = utport[sport];
+ 		while(recstart) {
+ 		    if(recstart->dstaddr.s_addr == 
+ 		       er_ipheader->ip_dst.s_addr) {
+ 			if(recstart->srcaddr.s_addr != 0xffffffff) {
+ 			    realaddr->s_addr = recstart->srcaddr.s_addr;
+ 			    ch_flag = 1;
+ 			}
+ 			real_port = recstart->real_port;
+ 			break;
+ 		    }
+ 		    recstart = recstart->next;
+ 		}
+ 		break;
+ 	    }
+ 	}
+ 	break;
+     default:
+ 	break;
+     }
+ 
+     return ch_flag;
+ }
+ 
+ int
+ CheckCheckSum(buf)
+ u_char *buf;
+ {
+     static u_int changes;
+     static u_int hlen;
+     static u_short *bp;
+     u_short sum_back;
+ 
+     static union {
+ 	struct tcphdr *th;
+ 	struct udphdr *uh;
+ 	struct icmp *icmp;
+     } ph;
+     static u_char savec, *savecp;
+     static u_int plen;
+ 
+     /* Save CheckSum */
+     sum_back = ((struct ip *)buf)->ip_sum;
+     ((struct ip *)buf)->ip_sum = 0;
+ 
+     /* calculating 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);
+ 
+     /* Check CheckSum */
+     ((struct ip *)buf)->ip_sum = sum_back;
+     if(((struct ip *)buf)->ip_sum != (~changes & 0xffff)) {
+ 	return -1;
+     }
+ 
+     /* check checksum in protocol specific header */
+     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 */
+ 	if (ph.uh->uh_sum == 0) {
+ 	    /* checksum unused */
+ 	    break;
+ 	}
+ 	sum_back = ph.uh->uh_sum;
+ 	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 */
+ 	bp = (u_short *)&(((struct ip *)buf)->ip_dst);
+ 	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 = sum_back;
+ 	if(ph.uh->uh_sum != (~changes & 0xffff)) {
+ 	    return -1;
+ 	}
+ 	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 */
+ 	sum_back = ph.th->th_sum;
+ 	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 */
+ 	bp = (u_short *)&(((struct ip *)buf)->ip_dst);
+ 	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 = sum_back;
+ 	if(ph.th->th_sum != (~changes & 0xffff)) {
+ 	    return -1;
+ 	}
+ 	break;
+     case IPPROTO_ICMP:
+ 	break;
+     default:
+ 	break;
+     }
+ 
+     return 0;
+ }
+ 
+ 
+ /* Check CU-SeeMe packet and translate address */
+ /* This part is based on CUSeeMe masquerading module for Linux */
+ 
+ /*
+  *              IP_MASQ_FTP CUSeeMe masquerading module
+  *
+  *
+  * Version:     @(#)ip_masq_cuseeme.c 0.02   07/23/96
+  *
+  * Author:      Richard Lynch
+  *
+  *
+  * Fixes:
+  *      Richard Lynch           :       Updated patch to conform to new module
+  *                                      specifications
+  *      Nigel Metheringham      :       Multiple port support
+  *      Michael Owings          :       Fixed broken init code
+  *                                      Added code to update inbound
+  *                                      packets with correct local addresses. Fixes audio
+  *                                      and "chat" problems
+  *                                      Thanx to the CU-SeeMe Consortium for
+  *                                      technical docs
+  *
+  *
+  *
+  *      This program is free software; you can redistribute it and/or
+  *      modify it under the terms of the GNU General Public License
+  *      as published by the Free Software Foundation; either version
+  *      2 of the License, or (at your option) any later version.
+  *
+  */
+ void
+ cu_check_out(buf)
+ char *buf;
+ {
+     struct ip *iph = (struct ip*)buf;
+     struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ip_hl * 4]);
+     cu_header *cu_head;
+     char *data = (char *)&uh[1];
+     struct in_addr addr;
+ 
+     if(uh->uh_ulen >= sizeof(cu_header)) {
+ 	cu_head         = (cu_header *) data;
+ 	/* cu_head->port   = ms->mport; */
+ 	if( cu_head->addr ) {
+ 	    addr = getCurMyAddr();
+ 	    cu_head->addr = (u_long)addr.s_addr;
+ 	}
+     }
+     return;
+ }
+ 
+ void
+ cu_check_in(buf, recstart)
+ char *buf;
+ UPORT *recstart;
+ {
+     struct ip *iph = (struct ip*)buf;
+     struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ip_hl * 4]);
+     cu_header *cu_head;
+     oc_header       *oc;
+     client_info     *ci;
+     char *data = (char *)&uh[1];
+     u_short len = uh->uh_ulen;
+     int             i, off;
+ 
+     if (len >= sizeof(cu_header)) {
+ 	cu_head         = (cu_header *) data;
+ 	if(cu_head->dest_addr) /* Correct destination address */
+ 	  cu_head->dest_addr = (u_long)recstart->srcaddr.s_addr;
+ 	if(ntohs(cu_head->data_type) == 101 && len > sizeof(oc_header)) {
+ 	    oc = (oc_header * ) data;
+ 	    /* Spin (grovel) thru client_info structs till we find our own */
+ 	    off = sizeof(oc_header);
+ 	    for(i = 0; i < oc->client_count && off + sizeof(client_info)
+ 		<= len; i++) {       
+ 		ci = (client_info *)(data + off);
+ 		if(ci->address == (u_long)iph->ip_dst.s_addr) {
+ 		    /* Update w/ our real ip address and exit */
+ 		    ci->address = (u_long)recstart->srcaddr.s_addr;
+ 		    break;
+ 		} else
+ 		  off += sizeof(client_info);
+ 	    }
+ 	}
+     }
+ }
diff -r -N -c ppp.ORG/nat.h ppp/nat.h
*** ppp.ORG/nat.h	Thu Jan  1 09:00:00 1970
--- ppp/nat.h	Sat Dec 27 14:15:30 1997
***************
*** 0 ****
--- 1,103 ----
+ /*
+  *  nat.h    for iij-ppp
+  *    by Junichi SATOH (junichi@astec.co.jp)  1996,1997.
+  */
+ 
+ /* using ports */
+ struct useport {
+     struct useport *next;
+     struct in_addr srcaddr;
+     struct in_addr dstaddr;
+     u_short real_port;
+     u_short subport;
+     short diff;
+     short diff_tmp;
+     time_t lm_time;
+     u_char flag;
+ };
+ 
+ /* Special UDP port */
+ struct special_udp {
+     struct useport *udplink;
+     struct special_udp *next;
+ };
+ 
+ /* address translation table for ICMP(echo) packets */
+ struct icmpaddr {
+     struct icmpaddr *next;
+     struct in_addr srcaddr;
+     struct in_addr dstaddr;
+     time_t lm_time;
+ };
+ 
+ /* CU-SeeMe Data Header */
+ typedef struct {
+     u_short dest_family;
+     u_short dest_port;
+     u_long  dest_addr;
+     short family;
+     u_short port;
+     u_long addr;
+     u_long seq;
+     u_short msg;
+     u_short data_type;
+     u_short packet_len;
+ } cu_header;
+ 
+ /* Open Continue Header */
+ typedef struct  {
+     cu_header       cu_head;
+     u_short client_count; /* Number of client info structs */
+     u_long  seq_no;
+     char            user_name[20];
+     char            stuff[4]; /* flags,  version stuff,  etc */
+ } oc_header;
+ 
+ /* client info structures */
+ typedef struct {
+     u_long address; /* Client address */
+     char stuff[8]; /* Flags, pruning bitfield,  packet counts etc */
+ } client_info;
+ 
+ 
+ typedef struct special_udp SPUPORT;
+ typedef struct useport UPORT;
+ typedef struct icmpaddr ICMPADDR;
+ 
+ /* Time to keep a exchanging table. (sec) */
+ #define KEEP_TCP 10 * 60
+ #define KEEP_UDP 10
+ #define KEEP_ICMP 2
+ 
+ /* tcp ports for ftp */
+ #define FTPctrl 21
+ #define FTPdata 20
+ 
+ /* RealAudio */
+ /* server tcp port */
+ #define RealAudio 7070
+ /* client udp port */
+ #define RAUDP_L 1000
+ #define RAUDP_H 9999
+ 
+ /* VDOLive Video */
+ #define VDO1 7000
+ #define VDO2 7010
+ 
+ /* Diablo Battle.net */
+ /* server tcp port */
+ #define DIATCP0        116
+ #define DIATCP1 118
+ /* client udp port */
+ #define DIAUDP0 6112
+ 
+ /* CU-SeeME */
+ #define CUSeeMe 7648
+ 
+ /* PORT numbers */
+ #define POUT 0
+ #define PIN 1
+ 
+ /* port number used by X-window system */
+ #define XPORT_BEGIN 6000
+ #define XPORT_END 6063
diff -r -N -c ppp.ORG/os.c ppp/os.c
*** ppp.ORG/os.c	Sat Sep  6 08:22:31 1997
--- ppp/os.c	Wed Nov  5 21:20:23 1997
***************
*** 44,53 ****
  #include "arp.h"
  #include "systems.h"
  #include "route.h"
  
  static struct ifaliasreq ifra;
  static struct ifreq ifrq;
! static struct in_addr oldmine, oldhis;
  static int linkup;
  
  #ifdef bsdi
--- 44,54 ----
  #include "arp.h"
  #include "systems.h"
  #include "route.h"
+ #include "nat.h"
  
  static struct ifaliasreq ifra;
  static struct ifreq ifrq;
! static struct in_addr oldmine, oldhis, oldmask;
  static int linkup;
  
  #ifdef bsdi
***************
*** 56,61 ****
--- 57,66 ----
  #endif
  extern void HangupModem();
  
+ extern UPORT *utport[65536], *uuport[65536];
+ extern SPUPORT *uraport, *uvdoport, *udiaport;
+ extern ICMPADDR *icmpaddr;
+ 
  char *IfDevName;
  
  static int
***************
*** 146,152 ****
      sin->sin_len = sizeof(*sin);
  
      if (changeaddr) {
! 
        /*
         * Interface already exists. Just change the address.
         */
--- 151,157 ----
      sin->sin_len = sizeof(*sin);
  
      if (changeaddr) {
! 	oldmask.s_addr = mask;
        /*
         * Interface already exists. Just change the address.
         */
***************
*** 230,239 ****
--- 235,260 ----
  }
  
  void
+ FreeSpecialUDP(SPUPORT *spport)
+ {
+     SPUPORT *tmp_spport;
+ 
+     while(spport) {
+ 	tmp_spport = spport;
+ 	spport = spport->next;
+ 	free(tmp_spport);
+     }
+ }
+ 
+ void
  OsLinkdown()
  {
    char *s;
    int Level;
+   struct in_addr zeroaddr;
+   UPORT *tmp_port;
+   ICMPADDR *tmp_icmpaddr;
+   int i;
  
    if (linkup) {
      FsmDown(&CcpFsm);	/* CCP must come down */
***************
*** 246,251 ****
--- 267,297 ----
  
      if (!(mode & MODE_AUTO))
        DeleteIfRoutes(0);
+     if((mode & MODE_AUTO) && (DefMyAddress.width < 32)){
+ 	zeroaddr.s_addr = 0;
+ 	OsSetIpaddress(zeroaddr, oldhis, oldmask);
+     }
+     for(i = 0; i < 65536; i++) {
+ 	while(utport[i]) {
+ 	    tmp_port = utport[i];
+ 	    utport[i] = utport[i]->next;
+ 	    free(tmp_port);
+ 	}
+ 	while(uuport[i]) {
+ 	    tmp_port = uuport[i];
+ 	    uuport[i] = uuport[i]->next;
+ 	    free(tmp_port);
+ 	}
+     }
+     FreeSpecialUDP(uraport);
+     FreeSpecialUDP(uvdoport);
+     FreeSpecialUDP(udiaport);
+     uraport = uvdoport = udiaport = NULL;
+     while(icmpaddr) {
+ 	tmp_icmpaddr = icmpaddr;
+ 	icmpaddr = icmpaddr->next;
+ 	free(tmp_icmpaddr);
+     }
      linkup = 0;
      if (SelectSystem(s, LINKDOWNFILE) < 0) {
        if (dstsystem) {
***************
*** 390,395 ****
--- 436,452 ----
    return (0);
  }
  
+ int
+ isOsLinkup()
+ {
+   return linkup;
+ }
+ 
+ struct in_addr
+ getCurMyAddr()
+ {
+   return oldmine;
+ }
  void
  OsCloseLink(int flag)
  {
diff -r -N -c ppp.ORG/os.h ppp/os.h
*** ppp.ORG/os.h	Wed Sep  3 09:42:16 1997
--- ppp/os.h	Wed Nov  5 21:20:23 1997
***************
*** 34,39 ****
--- 34,41 ----
  void OsLinkdown(void);
  void OsSetRoute(int, struct in_addr, struct in_addr, struct in_addr);
  void DeleteIfRoutes(int);
+ int isOsLinkup __P((void));
+ struct in_addr getCurMyAddr __P((void));
  void OsAddInOctets(int cnt);
  void OsAddOutOctets(int cnt);
  
