diff -r -N -c ppp-ondemand-0918/Makefile ppp/Makefile
*** ppp-ondemand-0918/Makefile	Tue Feb  6 02:02:37 1996
--- ppp/Makefile	Thu Oct 31 23:35:37 1996
***************
*** 4,10 ****
  SRCS=	async.c auth.c ccp.c chap.c chat.c command.c filter.c fsm.c hdlc.c \
  	ip.c ipcp.c lcp.c lqr.c log.c main.c mbuf.c modem.c os.c \
  	pap.c pred.c route.c slcompress.c timer.c systems.c uucplock.c vars.c \
! 	vjcomp.c arp.c
  #CFLAGS+= -DHAVE_SHELL_CMD_WITH_ANY_MODE
  CFLAGS += -Wall
  LDADD += -lmd
--- 4,10 ----
  SRCS=	async.c auth.c ccp.c chap.c chat.c command.c filter.c fsm.c hdlc.c \
  	ip.c ipcp.c lcp.c lqr.c log.c main.c mbuf.c modem.c os.c \
  	pap.c pred.c route.c slcompress.c timer.c systems.c uucplock.c vars.c \
! 	vjcomp.c arp.c nat.c
  #CFLAGS+= -DHAVE_SHELL_CMD_WITH_ANY_MODE
  CFLAGS += -Wall
  LDADD += -lmd
diff -r -N -c ppp-ondemand-0918/command.c ppp/command.c
*** ppp-ondemand-0918/command.c	Mon Jun 10 18:41:49 1996
--- ppp/command.c	Sat Dec 21 23:41:11 1996
***************
*** 803,808 ****
--- 803,854 ----
    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);
+ }
+ 
  
  #define	VAR_AUTHKEY	0
  #define	VAR_DIAL	1
***************
*** 892,897 ****
--- 938,947 ----
  	"Set escape characters", "hex-digit ..."},
    { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
  	"Set destination address", "src-addr dst-addr netmask"},
+   { "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", "..."},
    { "login",    NULL,     SetVariable,		LOCAL_AUTH,
diff -r -N -c ppp-ondemand-0918/ip.c ppp/ip.c
*** ppp-ondemand-0918/ip.c	Wed Sep 18 22:22:43 1996
--- ppp/ip.c	Wed Jan 15 16:42:47 1997
***************
*** 37,42 ****
--- 37,45 ----
  
  extern void SendPppFrame();
  extern void LcpClose();
+ extern int CheckTrans();
+ extern void ChangeDestIPAddress();
+ extern int CheckCheckSum();
  
  static struct pppTimer IdleTimer;
  
***************
*** 326,333 ****
  {
    u_char *cp;
    struct mbuf *wp;
!   int nb, nw;
    u_char tunbuff[MAX_MRU];
  
    cp = tunbuff;
    nb = 0;
--- 329,338 ----
  {
    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;
***************
*** 335,340 ****
--- 340,351 ----
      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 ( PacketCheck(tunbuff, nb, FL_IN ) < 0) {
diff -r -N -c ppp-ondemand-0918/ipcp.c ppp/ipcp.c
*** ppp-ondemand-0918/ipcp.c	Tue Feb  6 02:03:04 1996
--- ppp/ipcp.c	Sat Dec 21 23:38:06 1996
***************
*** 42,47 ****
--- 42,48 ----
  
  struct ipcpstate IpcpInfo;
  struct in_range DefMyAddress, DefHisAddress, DefTriggerAddress;
+ struct in_range DefTransAddress, DefXTransAddress;
  
  static void IpcpSendConfigReq __P((struct fsm *));
  static void IpcpSendTerminateAck __P((struct fsm *));
***************
*** 149,154 ****
--- 150,157 ----
  	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-ondemand-0918/ipcp.h ppp/ipcp.h
*** ppp-ondemand-0918/ipcp.h	Sat Aug 26 21:11:43 1995
--- ppp/ipcp.h	Sat Dec 21 23:39:19 1996
***************
*** 57,62 ****
--- 57,64 ----
  extern struct in_range DefMyAddress;
  extern struct in_range DefHisAddress;
  extern struct in_range DefTriggerAddress;
+ extern struct in_range DefTransAddress;
+ extern struct in_range DefXTransAddress;
  
  extern void IpcpInit __P((void));
  extern void IpcpDefAddress __P((void));
diff -r -N -c ppp-ondemand-0918/main.c ppp/main.c
*** ppp-ondemand-0918/main.c	Wed Sep 18 22:22:43 1996
--- ppp/main.c	Sat Feb 15 18:27:21 1997
***************
*** 23,29 ****
--- 23,59 ----
   *		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.
+  *
+  *  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.
+  */
+ 
  #include "fsm.h"
+ #include <string.h>
  #include <fcntl.h>
  #include <paths.h>
  #include <sys/time.h>
***************
*** 38,43 ****
--- 68,75 ----
  #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"
***************
*** 49,58 ****
  #include "filter.h"
  #include "systems.h"
  #include "ip.h"
  
  #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
  #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n"
- 
  #ifndef O_NONBLOCK
  #ifdef O_NDELAY
  #define	O_NONBLOCK O_NDELAY
--- 81,90 ----
  #include "filter.h"
  #include "systems.h"
  #include "ip.h"
+ #include "nat.h"
  
  #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
  #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n"
  #ifndef O_NONBLOCK
  #ifdef O_NDELAY
  #define	O_NONBLOCK O_NDELAY
***************
*** 66,71 ****
--- 98,106 ----
  extern void DecodeCommand(), Prompt();
  extern int IsInteractive();
  extern struct in_addr ifnetmask;
+ 
+ extern int SourceAddrCheck();
+ 
  static void DoLoop(void);
  static void TerminalStop();
  
***************
*** 75,80 ****
--- 110,120 ----
  static int server;
  struct sockaddr_in ifsin;
  char pid_filename[128];
+ UPORT *utport[65536], *uuport[65536];
+ URAPORT *uraport;
+ UVDOPORT *uvdoport;
+ ICMPADDR *icmpaddr;
+ u_short sub_port, real_port;
  
  static void
  TtyInit()
***************
*** 260,265 ****
--- 300,307 ----
  
    argc--; argv++;
  
+   uraport = NULL;
+   uvdoport = NULL;
    mode = MODE_INTER;		/* default operation is interactive mode */
    netfd = -1;
    ProcessArgs(argc, argv);
***************
*** 609,625 ****
  
  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:
--- 651,669 ----
  
  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:
***************
*** 628,633 ****
--- 672,688 ----
      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;
***************
*** 645,657 ****
      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);
--- 700,722 ----
      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);
***************
*** 663,668 ****
--- 728,745 ----
      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;
***************
*** 680,701 ****
      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;
--- 757,793 ----
      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(LOG_TCPIP, "TCP check sum is recalculated\n");
      break;
!   case IPPROTO_ICMP:
!     break;
!   default:
!     break;
    }
  }
  
+ 
  void
  ChangeSrcIPAddress(buf, addr)
       u_char *buf;
***************
*** 729,735 ****
  		inet_ntoa(((struct ip *)buf)->ip_src));
    }
    /* but protocol specific checksum may or may not correct */
!   RecalcProtoCksum(buf);
  }
  
  static void
--- 821,890 ----
  		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
***************
*** 750,755 ****
--- 905,911 ----
    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();
***************
*** 994,1014 ****
        }
        pri = PacketCheck(rbuff, n, FL_OUT);
        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");
  }
--- 1150,1175 ----
        }
        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);
! 		}
  	    }
! 	    IpEnqueue(pri, rbuff, n);
  	}
        }
      }
    }
    logprintf("job done.\n");
  }
+ 
diff -r -N -c ppp-ondemand-0918/nat.c ppp/nat.c
*** ppp-ondemand-0918/nat.c	Thu Jan  1 09:00:00 1970
--- ppp/nat.c	Sat Feb 15 18:18:45 1997
***************
*** 0 ****
--- 1,799 ----
+ /*
+  *  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 "vars.h"
+ #include "auth.h"
+ #include "filter.h"
+ #include "systems.h"
+ #include "ip.h"
+ #include "nat.h"
+ 
+ static UPORT *GetUPortPointer();
+ static UPORT *GetPortPointer();
+ 
+ extern UPORT *utport[65536], *uuport[65536];
+ extern URAPORT *uraport;
+ extern UVDOPORT *uvdoport;
+ 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;
+ 		} else {
+ 		    sport--;
+ 		    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 = 0;
+ 		    }
+ 		    return ret_port;
+ 		}
+ 		break;
+ 	    }
+ 	    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;
+ 
+     *subport = sport;
+     if(utport[sport] != NULL) {
+ 	recstart = utport[sport];
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_dst.s_addr) {
+ 		if(recstart->flag == 0) {
+ 		    sport--;
+ 		    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 = 0;
+ 		    }
+ 		    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;
+     URAPORT *tmp_uraport;
+     UVDOPORT *tmp_uvdoport;
+     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)) {
+ 	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 = 0;
+ 	}
+ 	tmp_uuport->dstaddr.s_addr = ((struct ip *)buf)->ip_dst.s_addr;
+ 	tmp_uuport->lm_time = time(NULL);
+ 	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 = 0;
+ 	    }
+ 	    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 = (URAPORT*)malloc(sizeof(URAPORT));
+ 		tmp_uraport->ralink = tmp_utport;
+ 		tmp_uraport->next = uraport;
+ 		uraport = tmp_uraport;
+ 	    }
+ 	    if((dport == VDO1 || dport == VDO2) && sc_status == 1) {
+ 		tmp_uvdoport = (UVDOPORT*)malloc(sizeof(UVDOPORT));
+ 		tmp_uvdoport->vdolink = tmp_utport;
+ 		tmp_uvdoport->next = uvdoport;
+ 		uvdoport = tmp_uvdoport;
+ 	    }
+ 	}
+ 	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 == 0) {
+ 			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 = 0;
+ 	    }
+ 	    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;
+     }
+ }
+ 
+ /* 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, *tmp_uuport;
+     URAPORT *tmp_uraport, *prev_uraport;
+     UVDOPORT *tmp_uvdoport, *prev_uvdoport;
+     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);
+ 	recstart = uuport[dport];
+ 	while(recstart) {
+ 	    if(recstart->dstaddr.s_addr == 
+ 	       ((struct ip *)buf)->ip_src.s_addr) {
+ 		if(recstart->srcaddr.s_addr != 0) {
+ 		    realaddr->s_addr = recstart->srcaddr.s_addr;
+ 		    ch_flag = 1;
+ 		}
+ 		real_port = recstart->real_port;
+ 		break;
+ 	    }
+ 	    recstart = recstart->next;
+ 	}
+ 	if(ch_flag == 0 && dport >= RAUDP_L && dport <= RAUDP_H) {
+ 	    /* Check RealAudio UDP packet. */
+ 	    prev_uraport = NULL;
+ 	    tmp_uraport = uraport;
+ 	    while(tmp_uraport) {
+ 		if(tmp_uraport->ralink->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_src.s_addr) {
+ 		    ch_flag = 1;
+ 		    if(prev_uraport == NULL) {
+ 			uraport = tmp_uraport->next;
+ 		    } else {
+ 			prev_uraport->next = tmp_uraport->next;
+ 		    }
+ 		    realaddr->s_addr = tmp_uraport->ralink->srcaddr.s_addr;
+ 		    tmp_uuport = (UPORT*)malloc(sizeof(UPORT));
+ 		    tmp_uuport->srcaddr.s_addr = 
+ 		      tmp_uraport->ralink->srcaddr.s_addr;
+ 		    tmp_uuport->dstaddr.s_addr = 
+ 		      tmp_uraport->ralink->dstaddr.s_addr;
+ 		    tmp_uuport->next = uuport[dport];
+ 		    uuport[dport] = tmp_uuport;
+ 		    free(tmp_uraport);
+ 		    break;
+ 		}
+ 		prev_uraport = tmp_uraport;
+ 		tmp_uraport = tmp_uraport->next;
+ 	    }
+ 	}
+ 	if(ch_flag == 0) {
+ 	    /* Check VDOLiveVideo UDP packet. */
+ 	    prev_uvdoport = NULL;
+ 	    tmp_uvdoport = uvdoport;
+ 	    while(tmp_uvdoport) {
+ 		if(tmp_uvdoport->vdolink->dstaddr.s_addr == 
+ 		   ((struct ip *)buf)->ip_src.s_addr) {
+ 		    ch_flag = 1;
+ 		    if(prev_uvdoport == NULL) {
+ 			uvdoport = tmp_uvdoport->next;
+ 		    } else {
+ 			prev_uvdoport->next = tmp_uvdoport->next;
+ 		    }
+ 		    realaddr->s_addr = tmp_uvdoport->vdolink->srcaddr.s_addr;
+ 		    tmp_uuport = (UPORT*)malloc(sizeof(UPORT));
+ 		    tmp_uuport->srcaddr.s_addr = 
+ 		      tmp_uvdoport->vdolink->srcaddr.s_addr;
+ 		    tmp_uuport->dstaddr.s_addr = 
+ 		      tmp_uvdoport->vdolink->dstaddr.s_addr;
+ 		    tmp_uuport->next = uuport[dport];
+ 		    uuport[dport] = tmp_uuport;
+ 		    free(tmp_uvdoport);
+ 		    break;
+ 		}
+ 		prev_uvdoport = tmp_uvdoport;
+ 		tmp_uvdoport = tmp_uvdoport->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 != 0) {
+ 		    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 != 0) {
+ 			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 != 0) {
+ 			    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 != 0) {
+ 			    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 */
+ 	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;
+ }
diff -r -N -c ppp-ondemand-0918/nat.h ppp/nat.h
*** ppp-ondemand-0918/nat.h	Mon Sep 23 23:15:39 1996
--- ppp/nat.h	Sat Feb 15 18:15:55 1997
***************
*** 0 ****
--- 1,70 ----
+ /*
+  *  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;
+ };
+ 
+ /* using ports used by RealAudio */
+ struct usera {
+     struct useport *ralink;
+     struct usera *next;
+ };
+ 
+ /* using ports used by VDOLive Video */
+ struct usevdo {
+     struct useport *vdolink;
+     struct usevdo *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;
+ };
+ 
+ typedef struct useport UPORT;
+ typedef struct usera URAPORT;
+ typedef struct usevdo UVDOPORT;
+ typedef struct icmpaddr ICMPADDR;
+ 
+ /* Time to keep a exchanging table. (sec) */
+ #define KEEP_TCP 20 * 60
+ #define KEEP_UDP 5 * 60
+ #define KEEP_ICMP 10
+ 
+ /* 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
+ 
+ /* 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-ondemand-0918/os.c ppp/os.c
*** ppp-ondemand-0918/os.c	Wed Sep 18 22:22:44 1996
--- ppp/os.c	Fri Nov  1 00:10:32 1996
***************
*** 39,44 ****
--- 39,45 ----
  #include "arp.h"
  #include "systems.h"
  #include "route.h"
+ #include "nat.h"
  
  static struct ifaliasreq ifra;
  static struct ifreq ifrq;
***************
*** 50,55 ****
--- 51,60 ----
  #endif
  extern void HangupModem();
  
+ extern UPORT *utport[65536], *uuport[65536];
+ extern URAPORT *uraport;
+ extern ICMPADDR *icmpaddr;
+ 
  char *IfDevName;
  
  static int
***************
*** 202,207 ****
--- 207,216 ----
  {
    char *s;
    struct in_addr zeroaddr;
+   UPORT *tmp_port;
+   URAPORT *tmp_uraport;
+   ICMPADDR *tmp_icmpaddr;
+   int i;
  
    if (linkup) {
      s = (char *)inet_ntoa(peer_addr);
***************
*** 211,216 ****
--- 220,247 ----
      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);
+ 	}
+     }
+     while(uraport) {
+ 	tmp_uraport = uraport;
+ 	uraport = uraport->next;
+ 	free(tmp_uraport);
+     }
+     while(icmpaddr) {
+ 	tmp_icmpaddr = icmpaddr;
+ 	icmpaddr = icmpaddr->next;
+ 	free(tmp_icmpaddr);
      }
      linkup = 0;
    }
