diff -c -N -r ppp-221R.org/Makefile ppp/Makefile *** ppp-221R.org/Makefile Sun Feb 23 02:59:04 1997 --- ppp/Makefile Sat Mar 29 01:44:00 1997 *************** *** 5,11 **** 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 alias.c alias_db.c alias_ftp.c alias_util.c \ ! passwdauth.c sig.c #CFLAGS+= -DHAVE_SHELL_CMD_WITH_ANY_MODE CFLAGS += -Wall -DUSE_PERROR -DMSEXT -DPASSWDAUTH LDADD += -lmd -lcrypt -lutil --- 5,11 ---- 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 alias.c alias_db.c alias_ftp.c alias_util.c \ ! passwdauth.c sig.c nat.c #CFLAGS+= -DHAVE_SHELL_CMD_WITH_ANY_MODE CFLAGS += -Wall -DUSE_PERROR -DMSEXT -DPASSWDAUTH LDADD += -lmd -lcrypt -lutil diff -c -N -r ppp-221R.org/command.c ppp/command.c *** ppp-221R.org/command.c Mon Feb 3 04:14:08 1997 --- ppp/command.c Sat Mar 29 01:44:00 1997 *************** *** 847,852 **** --- 847,898 ---- 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); + } + #ifdef MSEXT void *************** *** 1015,1020 **** --- 1061,1070 ---- "Set escape characters", "hex-digit ..."}, { "ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "Set destination address", "[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", "..."}, { "login", NULL, SetVariable, LOCAL_AUTH, diff -c -N -r ppp-221R.org/filter.c ppp/filter.c *** ppp-221R.org/filter.c Thu Jan 11 06:27:43 1996 --- ppp/filter.c Sat Mar 29 23:14:50 1997 *************** *** 206,217 **** filterdata.opt.srcop = filterdata.opt.dstop = A_NONE; return(1); } - if (argc < 3) { - #ifdef notdef - printf("bad udp syntax.\n"); - #endif - return(0); - } if (argc >= 3 && STREQ(*argv, "src")) { filterdata.opt.srcop = ParseOp(argv[1]); if (filterdata.opt.srcop == OP_NONE) { --- 206,211 ---- *************** *** 238,250 **** if (argc == 0) return(1); } ! if (argc == 1) { ! if (STREQ(*argv, "estab")) { filterdata.opt.estab = 1; return(1); - } - printf("estab is expected: %s\n", *argv); - return(0); } if (argc > 0) printf("bad src/dst port syntax: %s\n", *argv); --- 232,254 ---- 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) printf("bad src/dst port syntax: %s\n", *argv); *************** *** 359,364 **** --- 363,370 ---- printf("src: %s (%d)\n", opname[fp->opt.srcop], fp->opt.srcport); printf("dst: %s (%d)\n", opname[fp->opt.dstop], fp->opt.dstport); printf("estab: %d\n", fp->opt.estab); + printf("syn: %d\n", fp->opt.syn); + printf("finrst: %d\n", fp->opt.finrst); #endif if (val) *************** *** 448,453 **** --- 454,463 ---- printf(" dst %s %d", opname[fp->opt.dstop], fp->opt.dstport); if (fp->opt.estab) printf(" estab"); + if (fp->opt.syn) + printf(" syn"); + if (fp->opt.finrst) + printf(" finrst"); } printf("\n"); diff -c -N -r ppp-221R.org/filter.h ppp/filter.h *** ppp-221R.org/filter.h Fri Jan 12 02:48:43 1996 --- ppp/filter.h Sat Mar 29 01:53:43 1997 *************** *** 65,70 **** --- 65,72 ---- short dstop; u_short dstport; int estab; + int syn; + int finrst; } opt; }; diff -c -N -r ppp-221R.org/ip.c ppp/ip.c *** ppp-221R.org/ip.c Tue Dec 24 03:13:32 1996 --- ppp/ip.c Sun Apr 6 20:48:07 1997 *************** *** 38,43 **** --- 38,46 ---- extern void SendPppFrame(); extern void LcpClose(); + extern int CheckTrans(); + extern void ChangeDestIPAddress(); + extern int CheckCheckSum(); static struct pppTimer IdleTimer; *************** *** 121,127 **** int direction; { struct filterent *fp = Filters[direction]; ! int gotinfo, cproto, estab, n; struct tcphdr *th; struct udphdr *uh; struct icmp *ih; --- 124,130 ---- int direction; { struct filterent *fp = Filters[direction]; ! int gotinfo, cproto, estab, syn, finrst, n; struct tcphdr *th; struct udphdr *uh; struct icmp *ih; *************** *** 129,135 **** u_short sport, dport; if (fp->action) { ! cproto = gotinfo = estab = 0; sport = dport = 0; for (n = 0; n < MAXFILTERS; n++) { if (fp->action) { --- 132,138 ---- 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) { *************** *** 150,166 **** switch (pip->ip_p) { case IPPROTO_ICMP: 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; th = (struct tcphdr *)ptop; sport = ntohs(th->th_sport); dport = ntohs(th->th_dport); estab = (th->th_flags & TH_ACK); #ifdef DEBUG if (estab == 0) logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport); --- 153,171 ---- switch (pip->ip_p) { case IPPROTO_ICMP: 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; th = (struct tcphdr *)ptop; sport = ntohs(th->th_sport); dport = ntohs(th->th_dport); estab = (th->th_flags & TH_ACK); + syn = (th->th_flags & TH_SYN); + finrst = (th->th_flags & (TH_FIN | TH_RST)); #ifdef DEBUG if (estab == 0) logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport); *************** *** 171,178 **** } gotinfo = 1; #ifdef DEBUG ! logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n", ! direction, cproto, fp->opt.srcop, fp->opt.dstop, estab); #endif } #ifdef DEBUG --- 176,183 ---- } gotinfo = 1; #ifdef DEBUG ! logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d, syn = %d, finrst = %d\n", ! direction, cproto, fp->opt.srcop, fp->opt.dstop, estab, syn, finrst); #endif } #ifdef DEBUG *************** *** 187,194 **** (fp->opt.dstop == OP_NONE || PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && ! (fp->opt.estab == 0 || estab)) { ! return(fp->action); } } } else { --- 192,203 ---- (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); } } } else { *************** *** 321,328 **** { u_char *cp; struct mbuf *wp; ! int nb, nw; u_char tunbuff[MAX_MRU]; cp = tunbuff; nb = 0; --- 330,339 ---- { 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; *************** *** 330,335 **** --- 341,352 ---- 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 -c -N -r ppp-221R.org/ipcp.c ppp/ipcp.c *** ppp-221R.org/ipcp.c Mon Jan 13 06:52:47 1997 --- ppp/ipcp.c Sat Mar 29 01:44:00 1997 *************** *** 43,48 **** --- 43,49 ---- struct ipcpstate IpcpInfo; struct in_range DefMyAddress, DefHisAddress, DefTriggerAddress; + struct in_range DefTransAddress, DefXTransAddress; #ifdef MSEXT struct in_addr ns_entries[2], nbns_entries[2]; *************** *** 154,159 **** --- 155,162 ---- 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 -c -N -r ppp-221R.org/ipcp.h ppp/ipcp.h *** ppp-221R.org/ipcp.h Sun Oct 6 22:32:29 1996 --- ppp/ipcp.h Sat Mar 29 01:44:01 1997 *************** *** 68,73 **** --- 68,75 ---- 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; #ifdef MSEXT extern struct in_addr ns_entries[2]; diff -c -N -r ppp-221R.org/main.c ppp/main.c *** ppp-221R.org/main.c Sat Mar 15 19:44:22 1997 --- ppp/main.c Sat Jun 7 23:17:06 1997 *************** *** 23,28 **** --- 23,77 ---- * 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 "Packet Aliasing" is IP masquerade, + * but feature is different. + * + * This NAT patch support more protocols than "Packet Aliasing". + * For example, X, rlogin, RealAudio, VDOLiveVideo, 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. + */ + #include "fsm.h" #include #include *************** *** 37,42 **** --- 86,94 ---- #include #include #include + #include + #include + #include #include "modem.h" #include "os.h" #include "hdlc.h" *************** *** 50,55 **** --- 102,108 ---- #include "ip.h" #include "alias.h" #include "sig.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" *************** *** 68,73 **** --- 121,129 ---- extern int aft_cmd; extern int IsInteractive(); extern struct in_addr ifnetmask; + + extern int SourceAddrCheck(); + static void DoLoop(void); static void TerminalStop(); *************** *** 79,84 **** --- 135,145 ---- struct sockaddr_in ifsin; char pid_filename[128]; + UPORT *utport[65536], *uuport[65536]; + SPUPORT *uraport, *uvdoport, *udiaport; + ICMPADDR *icmpaddr; + u_short sub_port, real_port; + static void TtyInit() { *************** *** 294,303 **** int argc; char **argv; { ! int tunno; argc--; argv++; mode = MODE_INTER; /* default operation is interactive mode */ netfd = -1; ProcessArgs(argc, argv); --- 355,371 ---- int argc; char **argv; { ! int tunno, i; 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 = -1; ProcessArgs(argc, argv); *************** *** 699,720 **** } } static void DoLoop() { fd_set rfds, wfds, efds; int pri, i, n, wfd; struct sockaddr_in hisaddr; struct timeval timeout, *tp; int ssize = sizeof(hisaddr); u_char *cp; ! u_char rbuff[MAX_MRU]; int dial_up; int tries; int qlen; pid_t pgroup; pgroup = getpgrp(); if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { --- 767,1030 ---- } } + 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(LOG_TCPIP, "UDP check sum is recalculated\n"); + break; + case IPPROTO_TCP: + bp = (u_short *)buf; + bp += 2 * ((struct ip *)buf)->ip_hl; + ph.th = (struct tcphdr *)bp; + /* bp/ph.th points to tcp header */ + ph.th->th_sum = 0; + + 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(LOG_TCPIP, "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(loglevel & (1 << LOG_TCPIP)) /* for spped up when logging is disabled */ + sprintf(msgbuff, "%s", inet_ntoa(((struct ip *)buf)->ip_src)); + ((struct ip *)buf)->ip_src = addr; + ((struct ip *)buf)->ip_sum = 0; + + /* recalculating checksum in IP header */ + bp = (u_short *)buf; + changes = 0; + /* IP header length is (hlen * 2) bytes */ + for(hlen = 2 * ((struct ip *)buf)->ip_hl; hlen > 0; hlen--) + changes += *bp++; + changes = (changes & 0xffff) + (changes >> 16); + changes = (changes & 0xffff) + (changes >> 16); + ((struct ip *)buf)->ip_sum = (~changes & 0xffff); + + if(loglevel & (1 << LOG_TCPIP)) /* for spped up when logging is disabled */ + LogPrintf(LOG_TCPIP, "Src address changed: %s ---> %s\n", + msgbuff, + inet_ntoa(((struct ip *)buf)->ip_src)); + } + /* but protocol specific checksum may or may not correct */ + RecalcProtoCksum(buf, 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; + 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 dial_up; int tries; int qlen; pid_t pgroup; + time_t ttimer = (time_t)0; /* expiration timer for tun device */ + struct in_addr oldmyaddr; + int recalc; /* recalculates checksum */ + int nat; /* network address translator */ + recalc = (mode & MODE_AUTO) && (DefMyAddress.width < 32); pgroup = getpgrp(); if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { *************** *** 776,781 **** --- 1086,1092 ---- if (VarDialTries && tries >= VarDialTries) { dial_up = FALSE; tries = 0; + tsavelen = 0; } } } *************** *** 811,817 **** #endif /* If there are aren't many packets queued, look for some more. */ ! if (qlen < 20) FD_SET(tun_in, &rfds); if (netfd > -1) { --- 1122,1128 ---- #endif /* If there are aren't many packets queued, look for some more. */ ! if (qlen < 20 && !tsavelen) FD_SET(tun_in, &rfds); if (netfd > -1) { *************** *** 935,940 **** --- 1246,1265 ---- } } + 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 (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ n = read(tun_in, rbuff, sizeof(rbuff)); if (n < 0) { *************** *** 946,969 **** * 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) { PacketAliasOut((struct ip *)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) { ! PacketAliasOut((struct ip *)rbuff); ! n = ntohs(((struct ip *)rbuff)->ip_len); } - IpEnqueue(pri, rbuff, n); } } } --- 1271,1312 ---- * 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) { PacketAliasOut((struct ip *)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) { ! PacketAliasOut((struct ip *)rbuff); ! n = ntohs(((struct ip *)rbuff)->ip_len); ! } ! IpEnqueue(pri, rbuff, n); } } } } diff -c -N -r ppp-221R.org/nat.c ppp/nat.c *** ppp-221R.org/nat.c Thu Jan 1 09:00:00 1970 --- ppp/nat.c Sat Jun 7 22:34:01 1997 *************** *** 0 **** --- 1,803 ---- + /* + * NAT module for iij-ppp + * Programmed by Junichi SATOH (junichi@astec.co.jp) in 1996,1997. + */ + + #include "fsm.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #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 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); + 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; + 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 */ + 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 -c -N -r ppp-221R.org/nat.h ppp/nat.h *** ppp-221R.org/nat.h Thu Jan 1 09:00:00 1970 --- ppp/nat.h Sat Jun 7 17:44:39 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; + }; + + /* 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; + }; + + 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 4 + #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 + + /* PORT numbers */ + #define POUT 0 + #define PIN 1 + + /* port number used by X-window system */ + #define XPORT_BEGIN 6000 + #define XPORT_END 6063 diff -c -N -r ppp-221R.org/os.c ppp/os.c *** ppp-221R.org/os.c Mon Jan 13 06:52:50 1997 --- ppp/os.c Wed Apr 9 23:26:07 1997 *************** *** 43,52 **** #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 --- 43,53 ---- #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 *************** *** 54,59 **** --- 55,64 ---- #endif extern void HangupModem(); + extern UPORT *utport[65536], *uuport[65536]; + extern SPUPORT *uraport, *uvdoport, *udiaport; + extern ICMPADDR *icmpaddr; + char *IfDevName; static int *************** *** 141,146 **** --- 146,152 ---- sin->sin_len = sizeof(*sin); if (changeaddr) { + oldmask.s_addr = mask; /* * Interface already exists. Just change the address. */ *************** *** 201,215 **** --- 207,262 ---- } void + FreeSpecialUDP(SPUPORT *spport) + { + SPUPORT *tmp_spport; + + while(spport) { + tmp_spport = spport; + spport = spport->next; + free(tmp_spport); + } + } + + void OsLinkdown() { char *s; + struct in_addr zeroaddr; + UPORT *tmp_port; + ICMPADDR *tmp_icmpaddr; + int i; if (linkup) { s = (char *)inet_ntoa(peer_addr); LogPrintf(LOG_LINK_BIT|LOG_LCP_BIT, "OsLinkdown: %s\n", s); if (!(mode & MODE_AUTO)) DeleteIfRoutes(0); + if((mode & MODE_AUTO) && (DefMyAddress.width < 32)){ + zeroaddr.s_addr = 0; + OsSetIpaddress(zeroaddr, oldhis, oldmask); + } + 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; } } *************** *** 358,360 **** --- 405,418 ---- { } + int + isOsLinkup() + { + return linkup; + } + + struct in_addr + getCurMyAddr() + { + return oldmine; + } diff -c -N -r ppp-221R.org/os.h ppp/os.h *** ppp-221R.org/os.h Thu Jan 11 06:27:57 1996 --- ppp/os.h Sat Mar 29 01:44:02 1997 *************** *** 34,37 **** --- 34,39 ---- void DeleteIfRoutes __P((int)); void OsAddInOctets __P((int cnt)); void OsAddOutOctets __P((int cnt)); + int isOsLinkup __P((void)); + struct in_addr getCurMyAddr __P((void)); #endif