11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * PPP IP Protocol Interface 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 2063f98b41SBrian Somers * $Id: ip.c,v 1.38.2.21 1998/04/07 23:45:52 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o Return ICMP message for filterd packet 241ae349f5Scvs2svn * and optionaly record it into log. 251ae349f5Scvs2svn */ 262764b86aSBrian Somers #include <sys/types.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn #include <netinet/in_systm.h> 291ae349f5Scvs2svn #include <netinet/ip.h> 301ae349f5Scvs2svn #include <netinet/ip_icmp.h> 311ae349f5Scvs2svn #include <netinet/udp.h> 321ae349f5Scvs2svn #include <netinet/tcp.h> 331ae349f5Scvs2svn #include <arpa/inet.h> 341ae349f5Scvs2svn 351ae349f5Scvs2svn #ifndef NOALIAS 361ae349f5Scvs2svn #include <alias.h> 371ae349f5Scvs2svn #endif 381ae349f5Scvs2svn #include <errno.h> 391ae349f5Scvs2svn #include <stdio.h> 401ae349f5Scvs2svn #include <stdlib.h> 411ae349f5Scvs2svn #include <string.h> 421ae349f5Scvs2svn #include <unistd.h> 431ae349f5Scvs2svn 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "defs.h" 471ae349f5Scvs2svn #include "timer.h" 481ae349f5Scvs2svn #include "fsm.h" 49879ed6faSBrian Somers #include "lqr.h" 501ae349f5Scvs2svn #include "hdlc.h" 511ae349f5Scvs2svn #include "loadalias.h" 525828db6dSBrian Somers #include "throughput.h" 535828db6dSBrian Somers #include "iplist.h" 54eaa4df37SBrian Somers #include "slcompress.h" 555828db6dSBrian Somers #include "ipcp.h" 561ae349f5Scvs2svn #include "filter.h" 572f786681SBrian Somers #include "descriptor.h" 583b0f8d2eSBrian Somers #include "lcp.h" 593b0f8d2eSBrian Somers #include "ccp.h" 603b0f8d2eSBrian Somers #include "link.h" 613b0f8d2eSBrian Somers #include "mp.h" 627a6f8720SBrian Somers #include "bundle.h" 631ae349f5Scvs2svn #include "vjcomp.h" 641ae349f5Scvs2svn #include "tun.h" 651ae349f5Scvs2svn #include "ip.h" 661ae349f5Scvs2svn 671ae349f5Scvs2svn static const u_short interactive_ports[32] = { 681ae349f5Scvs2svn 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 691ae349f5Scvs2svn 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 701ae349f5Scvs2svn }; 711ae349f5Scvs2svn 721ae349f5Scvs2svn #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 731ae349f5Scvs2svn 741ae349f5Scvs2svn static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 751ae349f5Scvs2svn 761ae349f5Scvs2svn static int 771ae349f5Scvs2svn PortMatch(int op, u_short pport, u_short rport) 781ae349f5Scvs2svn { 791ae349f5Scvs2svn switch (op) { 801ae349f5Scvs2svn case OP_EQ: 811ae349f5Scvs2svn return (pport == rport); 821ae349f5Scvs2svn case OP_GT: 831ae349f5Scvs2svn return (pport > rport); 841ae349f5Scvs2svn case OP_LT: 851ae349f5Scvs2svn return (pport < rport); 861ae349f5Scvs2svn default: 871ae349f5Scvs2svn return (0); 881ae349f5Scvs2svn } 891ae349f5Scvs2svn } 901ae349f5Scvs2svn 911ae349f5Scvs2svn /* 921ae349f5Scvs2svn * Check a packet against with defined filters 931ae349f5Scvs2svn */ 941ae349f5Scvs2svn static int 955ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 961ae349f5Scvs2svn { 9763f98b41SBrian Somers int gotinfo, cproto, estab, syn, finrst, n, len, didname; 981ae349f5Scvs2svn struct tcphdr *th; 991ae349f5Scvs2svn struct udphdr *uh; 1001ae349f5Scvs2svn struct icmp *ih; 1011ae349f5Scvs2svn char *ptop; 1021ae349f5Scvs2svn u_short sport, dport; 1035ca5389aSBrian Somers struct filterent *fp = filter->rule; 1048390b576SBrian Somers char dbuff[100]; 1051ae349f5Scvs2svn 1061ae349f5Scvs2svn if (fp->action) { 10763f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 1081ae349f5Scvs2svn sport = dport = 0; 1091ae349f5Scvs2svn for (n = 0; n < MAXFILTERS; n++) { 1101ae349f5Scvs2svn if (fp->action) { 1111ae349f5Scvs2svn /* permit fragments on in and out filter */ 1125ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 1131ae349f5Scvs2svn return (A_PERMIT); 1145ca5389aSBrian Somers 1158390b576SBrian Somers if (!didname) 1168390b576SBrian Somers LogPrintf(LogDEBUG, "%s filter:\n", filter->name); 1178390b576SBrian Somers didname = 1; 1188390b576SBrian Somers 1191ae349f5Scvs2svn if ((pip->ip_src.s_addr & fp->smask.s_addr) == 1201ae349f5Scvs2svn (fp->saddr.s_addr & fp->smask.s_addr) && 1211ae349f5Scvs2svn (pip->ip_dst.s_addr & fp->dmask.s_addr) == 1221ae349f5Scvs2svn (fp->daddr.s_addr & fp->dmask.s_addr)) { 1231ae349f5Scvs2svn if (fp->proto) { 1241ae349f5Scvs2svn if (!gotinfo) { 1251ae349f5Scvs2svn ptop = (char *) pip + (pip->ip_hl << 2); 1261ae349f5Scvs2svn 1271ae349f5Scvs2svn switch (pip->ip_p) { 1281ae349f5Scvs2svn case IPPROTO_ICMP: 1291ae349f5Scvs2svn cproto = P_ICMP; 1301ae349f5Scvs2svn ih = (struct icmp *) ptop; 1311ae349f5Scvs2svn sport = ih->icmp_type; 13263f98b41SBrian Somers estab = syn = finrst = -1; 1338390b576SBrian Somers if (LogIsKept(LogDEBUG)) 1348390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 1351ae349f5Scvs2svn break; 1361ae349f5Scvs2svn case IPPROTO_UDP: 1371ae349f5Scvs2svn cproto = P_UDP; 1381ae349f5Scvs2svn uh = (struct udphdr *) ptop; 1391ae349f5Scvs2svn sport = ntohs(uh->uh_sport); 1401ae349f5Scvs2svn dport = ntohs(uh->uh_dport); 14163f98b41SBrian Somers estab = syn = finrst = -1; 1428390b576SBrian Somers if (LogIsKept(LogDEBUG)) 1438390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1448390b576SBrian Somers sport, dport); 1451ae349f5Scvs2svn break; 1461ae349f5Scvs2svn case IPPROTO_TCP: 1471ae349f5Scvs2svn cproto = P_TCP; 1481ae349f5Scvs2svn th = (struct tcphdr *) ptop; 1491ae349f5Scvs2svn sport = ntohs(th->th_sport); 1501ae349f5Scvs2svn dport = ntohs(th->th_dport); 1511ae349f5Scvs2svn estab = (th->th_flags & TH_ACK); 15263f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 15363f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 1548390b576SBrian Somers if (LogIsKept(LogDEBUG) && !estab) 1558390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 1568390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 1571ae349f5Scvs2svn th->th_flags, sport, dport); 1581ae349f5Scvs2svn break; 1591ae349f5Scvs2svn default: 1601ae349f5Scvs2svn return (A_DENY); /* We'll block unknown type of packet */ 1611ae349f5Scvs2svn } 1628390b576SBrian Somers if (LogIsKept(LogDEBUG)) { 1638390b576SBrian Somers if (estab != -1) { 1648390b576SBrian Somers len = strlen(dbuff); 16563f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 16663f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 16763f98b41SBrian Somers estab, syn, finrst); 1681ae349f5Scvs2svn } 1698390b576SBrian Somers LogPrintf(LogDEBUG, " Filter: proto = %s, %s\n", 1708390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 1718390b576SBrian Somers } 1728390b576SBrian Somers gotinfo = 1; 1738390b576SBrian Somers } 1748390b576SBrian Somers if (LogIsKept(LogDEBUG)) { 1758390b576SBrian Somers if (fp->opt.srcop != OP_NONE) { 1768390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 1778390b576SBrian Somers filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 1788390b576SBrian Somers len = strlen(dbuff); 1798390b576SBrian Somers } else 1808390b576SBrian Somers len = 0; 1818390b576SBrian Somers if (fp->opt.dstop != OP_NONE) { 1828390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 1838390b576SBrian Somers ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 1848390b576SBrian Somers fp->opt.dstport); 1858390b576SBrian Somers } else if (!len) 1868390b576SBrian Somers *dbuff = '\0'; 1878390b576SBrian Somers 1888390b576SBrian Somers LogPrintf(LogDEBUG, " rule = %d: Address match, " 1898390b576SBrian Somers "check against proto %s%s, action = %s\n", 1908390b576SBrian Somers n, filter_Proto2Nam(fp->proto), 1918390b576SBrian Somers dbuff, filter_Action2Nam(fp->action)); 1928390b576SBrian Somers } 1931ae349f5Scvs2svn 1941ae349f5Scvs2svn if (cproto == fp->proto) { 1951ae349f5Scvs2svn if ((fp->opt.srcop == OP_NONE || 19663f98b41SBrian Somers PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 1971ae349f5Scvs2svn (fp->opt.dstop == OP_NONE || 19863f98b41SBrian Somers PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 19963f98b41SBrian Somers (fp->opt.estab == 0 || estab) && 20063f98b41SBrian Somers (fp->opt.syn == 0 || syn) && 20163f98b41SBrian Somers (fp->opt.finrst == 0 || finrst)) { 2021ae349f5Scvs2svn return (fp->action); 2031ae349f5Scvs2svn } 2041ae349f5Scvs2svn } 2051ae349f5Scvs2svn } else { 2061ae349f5Scvs2svn /* Address is mached. Make a decision. */ 2078390b576SBrian Somers LogPrintf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 2088390b576SBrian Somers filter_Action2Nam(fp->action)); 2091ae349f5Scvs2svn return (fp->action); 2101ae349f5Scvs2svn } 2118390b576SBrian Somers } else 2128390b576SBrian Somers LogPrintf(LogDEBUG, " rule = %d: Address mismatch\n", n); 2131ae349f5Scvs2svn } 2141ae349f5Scvs2svn fp++; 2151ae349f5Scvs2svn } 2161ae349f5Scvs2svn return (A_DENY); /* No rule is mached. Deny this packet */ 2171ae349f5Scvs2svn } 2181ae349f5Scvs2svn return (A_PERMIT); /* No rule is given. Permit this packet */ 2191ae349f5Scvs2svn } 2201ae349f5Scvs2svn 2215ca5389aSBrian Somers #ifdef notdef 2221ae349f5Scvs2svn static void 2231ae349f5Scvs2svn IcmpError(struct ip * pip, int code) 2241ae349f5Scvs2svn { 2251ae349f5Scvs2svn struct mbuf *bp; 2261ae349f5Scvs2svn 2271ae349f5Scvs2svn if (pip->ip_p != IPPROTO_ICMP) { 2281ae349f5Scvs2svn bp = mballoc(cnt, MB_IPIN); 2291ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), ptr, cnt); 2301ae349f5Scvs2svn SendPppFrame(bp); 2315828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2321ae349f5Scvs2svn } 2331ae349f5Scvs2svn } 2345ca5389aSBrian Somers #endif 2351ae349f5Scvs2svn 2361ae349f5Scvs2svn /* 2371ae349f5Scvs2svn * For debugging aid. 2381ae349f5Scvs2svn */ 2391ae349f5Scvs2svn int 2405ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 2411ae349f5Scvs2svn { 2421ae349f5Scvs2svn struct ip *pip; 2431ae349f5Scvs2svn struct tcphdr *th; 2441ae349f5Scvs2svn struct udphdr *uh; 2451ae349f5Scvs2svn struct icmp *icmph; 2461ae349f5Scvs2svn char *ptop; 2471ae349f5Scvs2svn int mask, len, n; 2481ae349f5Scvs2svn int pri = PRI_NORMAL; 2491ae349f5Scvs2svn int logit, loglen; 2501ae349f5Scvs2svn static char logbuf[200]; 2511ae349f5Scvs2svn 2525ca5389aSBrian Somers logit = LogIsKept(LogTCPIP) && filter->logok; 2531ae349f5Scvs2svn loglen = 0; 2541ae349f5Scvs2svn 2551ae349f5Scvs2svn pip = (struct ip *) cp; 2561ae349f5Scvs2svn 2571ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2585ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 2591ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2601ae349f5Scvs2svn } 2611ae349f5Scvs2svn ptop = (cp + (pip->ip_hl << 2)); 2621ae349f5Scvs2svn 2631ae349f5Scvs2svn switch (pip->ip_p) { 2641ae349f5Scvs2svn case IPPROTO_ICMP: 2651ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2661ae349f5Scvs2svn icmph = (struct icmp *) ptop; 2671ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2681ae349f5Scvs2svn "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 2691ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2701ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2711ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 2721ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2731ae349f5Scvs2svn } 2741ae349f5Scvs2svn break; 2751ae349f5Scvs2svn case IPPROTO_UDP: 2761ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2771ae349f5Scvs2svn uh = (struct udphdr *) ptop; 2781ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2791ae349f5Scvs2svn "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 2801ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2811ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2821ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 2831ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2841ae349f5Scvs2svn } 2851ae349f5Scvs2svn break; 2861ae349f5Scvs2svn case IPPROTO_TCP: 2871ae349f5Scvs2svn th = (struct tcphdr *) ptop; 2881ae349f5Scvs2svn if (pip->ip_tos == IPTOS_LOWDELAY) 2891ae349f5Scvs2svn pri = PRI_FAST; 2901ae349f5Scvs2svn else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 2911ae349f5Scvs2svn if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 2921ae349f5Scvs2svn pri = PRI_FAST; 2931ae349f5Scvs2svn } 2941ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2951ae349f5Scvs2svn len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 2961ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2971ae349f5Scvs2svn "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 2981ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2991ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 3001ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 3011ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 3021ae349f5Scvs2svn n = 0; 3031ae349f5Scvs2svn for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 3041ae349f5Scvs2svn if (th->th_flags & mask) { 3051ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 3061ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 3071ae349f5Scvs2svn } 3081ae349f5Scvs2svn n++; 3091ae349f5Scvs2svn } 3101ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 3111ae349f5Scvs2svn " seq:%x ack:%x (%d/%d)", 3121ae349f5Scvs2svn ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 3131ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 3141ae349f5Scvs2svn if ((th->th_flags & TH_SYN) && nb > 40) { 3151ae349f5Scvs2svn u_short *sp; 3161ae349f5Scvs2svn 3171ae349f5Scvs2svn ptop += 20; 3181ae349f5Scvs2svn sp = (u_short *) ptop; 3191ae349f5Scvs2svn if (ntohs(sp[0]) == 0x0204) { 3201ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 3211ae349f5Scvs2svn " MSS = %d", ntohs(sp[1])); 3221ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 3231ae349f5Scvs2svn } 3241ae349f5Scvs2svn } 3251ae349f5Scvs2svn } 3261ae349f5Scvs2svn break; 3271ae349f5Scvs2svn } 3281ae349f5Scvs2svn 3295ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 3301ae349f5Scvs2svn if (logit) 3311ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3325ca5389aSBrian Somers #ifdef notdef 3331ae349f5Scvs2svn if (direction == 0) 3341ae349f5Scvs2svn IcmpError(pip, pri); 3355ca5389aSBrian Somers #endif 3361ae349f5Scvs2svn return (-1); 3371ae349f5Scvs2svn } else { 3385ca5389aSBrian Somers /* Check Keep Alive filter */ 3391ae349f5Scvs2svn if (logit) 3401e991daaSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 3411ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3421e991daaSBrian Somers else 3431ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s\n", logbuf); 3441ae349f5Scvs2svn return (pri); 3451ae349f5Scvs2svn } 3461ae349f5Scvs2svn } 3471ae349f5Scvs2svn 3481ae349f5Scvs2svn void 3497a6f8720SBrian Somers IpInput(struct bundle *bundle, struct mbuf * bp) 3507a6f8720SBrian Somers { 3511ae349f5Scvs2svn u_char *cp; 3521ae349f5Scvs2svn struct mbuf *wp; 3531ae349f5Scvs2svn int nb, nw; 3541ae349f5Scvs2svn struct tun_data tun; 3551e991daaSBrian Somers struct ip *pip = (struct ip *)tun.data; 3561ae349f5Scvs2svn 3571ae349f5Scvs2svn tun_fill_header(tun, AF_INET); 3581ae349f5Scvs2svn cp = tun.data; 3591ae349f5Scvs2svn nb = 0; 3601ae349f5Scvs2svn for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 3611ae349f5Scvs2svn if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 3621ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: Packet too large (%d) - dropped\n", 3631ae349f5Scvs2svn plength(bp)); 3641ae349f5Scvs2svn pfree(bp); 3651ae349f5Scvs2svn return; 3661ae349f5Scvs2svn } 3671ae349f5Scvs2svn memcpy(cp, MBUF_CTOP(wp), wp->cnt); 3681ae349f5Scvs2svn cp += wp->cnt; 3691ae349f5Scvs2svn nb += wp->cnt; 3701ae349f5Scvs2svn } 3711ae349f5Scvs2svn 3721ae349f5Scvs2svn #ifndef NOALIAS 37385602e52SBrian Somers if (AliasEnabled()) { 3741ae349f5Scvs2svn struct tun_data *frag; 3751ae349f5Scvs2svn int iresult; 3761ae349f5Scvs2svn char *fptr; 3771ae349f5Scvs2svn 3782764b86aSBrian Somers iresult = (*PacketAlias.In)(tun.data, sizeof tun.data); 3791ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 3801ae349f5Scvs2svn 3811ae349f5Scvs2svn if (nb > MAX_MRU) { 3821ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: Problem with IP header length\n"); 3831ae349f5Scvs2svn pfree(bp); 3841ae349f5Scvs2svn return; 3851ae349f5Scvs2svn } 3861ae349f5Scvs2svn if (iresult == PKT_ALIAS_OK 3871ae349f5Scvs2svn || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 3885ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 3891ae349f5Scvs2svn pfree(bp); 3901ae349f5Scvs2svn return; 3911ae349f5Scvs2svn } 3921e991daaSBrian Somers 3931e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 3941e991daaSBrian Somers bundle_StartIdleTimer(bundle); 3951e991daaSBrian Somers 3965828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 3971ae349f5Scvs2svn 3981ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 3991ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 4007a6f8720SBrian Somers nw = write(bundle->tun_fd, &tun, nb); 4011ae349f5Scvs2svn if (nw != nb) 4021ae349f5Scvs2svn if (nw == -1) 4031ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 4041ae349f5Scvs2svn strerror(errno)); 4051ae349f5Scvs2svn else 4061ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 4071ae349f5Scvs2svn 4081ae349f5Scvs2svn if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 4092764b86aSBrian Somers while ((fptr = (*PacketAlias.GetFragment)(tun.data)) != NULL) { 4102764b86aSBrian Somers (*PacketAlias.FragmentIn)(tun.data, fptr); 4111ae349f5Scvs2svn nb = ntohs(((struct ip *) fptr)->ip_len); 4121ae349f5Scvs2svn frag = (struct tun_data *) 4131ae349f5Scvs2svn ((char *)fptr - sizeof tun + sizeof tun.data); 4141ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 4157a6f8720SBrian Somers nw = write(bundle->tun_fd, frag, nb); 4161ae349f5Scvs2svn if (nw != nb) 4171ae349f5Scvs2svn if (nw == -1) 4181ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 4191ae349f5Scvs2svn strerror(errno)); 4201ae349f5Scvs2svn else 4211ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 4221ae349f5Scvs2svn free(frag); 4231ae349f5Scvs2svn } 4241ae349f5Scvs2svn } 4251ae349f5Scvs2svn } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 4261ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 4271ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 4281ae349f5Scvs2svn frag = (struct tun_data *)malloc(nb); 4291ae349f5Scvs2svn if (frag == NULL) 4301ae349f5Scvs2svn LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n"); 4311ae349f5Scvs2svn else { 4321ae349f5Scvs2svn tun_fill_header(*frag, AF_INET); 4331ae349f5Scvs2svn memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 4342764b86aSBrian Somers (*PacketAlias.SaveFragment)(frag->data); 4351ae349f5Scvs2svn } 4361ae349f5Scvs2svn } 4371ae349f5Scvs2svn } else 4381ae349f5Scvs2svn #endif /* #ifndef NOALIAS */ 4391ae349f5Scvs2svn { /* no aliasing */ 4405ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 4411ae349f5Scvs2svn pfree(bp); 4421ae349f5Scvs2svn return; 4431ae349f5Scvs2svn } 4441e991daaSBrian Somers 4451e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4461e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4471e991daaSBrian Somers 4485828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4491e991daaSBrian Somers 4501ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 4517a6f8720SBrian Somers nw = write(bundle->tun_fd, &tun, nb); 4521ae349f5Scvs2svn if (nw != nb) 4531ae349f5Scvs2svn if (nw == -1) 4541ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, strerror(errno)); 4551ae349f5Scvs2svn else 4561ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 4571ae349f5Scvs2svn } 4581ae349f5Scvs2svn pfree(bp); 4591ae349f5Scvs2svn } 4601ae349f5Scvs2svn 4611ae349f5Scvs2svn static struct mqueue IpOutputQueues[PRI_FAST + 1]; 4621ae349f5Scvs2svn 4631ae349f5Scvs2svn void 4641ae349f5Scvs2svn IpEnqueue(int pri, char *ptr, int count) 4651ae349f5Scvs2svn { 4661ae349f5Scvs2svn struct mbuf *bp; 4671ae349f5Scvs2svn 4681ae349f5Scvs2svn bp = mballoc(count, MB_IPQ); 4691ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), ptr, count); 4701ae349f5Scvs2svn Enqueue(&IpOutputQueues[pri], bp); 4711ae349f5Scvs2svn } 4721ae349f5Scvs2svn 4731ae349f5Scvs2svn int 474f4768038SBrian Somers ip_QueueLen() 4751ae349f5Scvs2svn { 4761ae349f5Scvs2svn struct mqueue *queue; 477f4768038SBrian Somers int result = 0; 4781ae349f5Scvs2svn 479f4768038SBrian Somers for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--) 480f4768038SBrian Somers result += queue->qlen; 481f4768038SBrian Somers 482f4768038SBrian Somers return result; 4831ae349f5Scvs2svn } 4841ae349f5Scvs2svn 4853b0f8d2eSBrian Somers int 4863b0f8d2eSBrian Somers IpFlushPacket(struct link *l, struct bundle *bundle) 4871ae349f5Scvs2svn { 4881ae349f5Scvs2svn struct mqueue *queue; 4891ae349f5Scvs2svn struct mbuf *bp; 4901ae349f5Scvs2svn int cnt; 4911ae349f5Scvs2svn 4925828db6dSBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) 4933b0f8d2eSBrian Somers return 0; 4941e991daaSBrian Somers 4951e991daaSBrian Somers for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) 4961ae349f5Scvs2svn if (queue->top) { 4971ae349f5Scvs2svn bp = Dequeue(queue); 4981ae349f5Scvs2svn if (bp) { 4991e991daaSBrian Somers struct ip *pip = (struct ip *)MBUF_CTOP(bp); 5001e991daaSBrian Somers 5011ae349f5Scvs2svn cnt = plength(bp); 502f4768038SBrian Somers SendPppFrame(l, bp, bundle); 5031e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 504ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 5055828db6dSBrian Somers ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt); 5063b0f8d2eSBrian Somers return 1; 5071ae349f5Scvs2svn } 5081ae349f5Scvs2svn } 5091e991daaSBrian Somers 5103b0f8d2eSBrian Somers return 0; 5111ae349f5Scvs2svn } 512