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 * 20eaa4df37SBrian Somers * $Id: ip.c,v 1.38.2.13 1998/03/16 22:52:17 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o Return ICMP message for filterd packet 241ae349f5Scvs2svn * and optionaly record it into log. 251ae349f5Scvs2svn */ 261ae349f5Scvs2svn #include <sys/param.h> 271ae349f5Scvs2svn #include <sys/time.h> 281ae349f5Scvs2svn #include <sys/socket.h> 291ae349f5Scvs2svn #include <net/if.h> 30d2fd8d77SBrian Somers #include <sys/select.h> 311ae349f5Scvs2svn #include <net/if_tun.h> 321ae349f5Scvs2svn #include <netinet/in.h> 331ae349f5Scvs2svn #include <netinet/in_systm.h> 341ae349f5Scvs2svn #include <netinet/ip.h> 351ae349f5Scvs2svn #include <netinet/ip_icmp.h> 361ae349f5Scvs2svn #include <netinet/udp.h> 371ae349f5Scvs2svn #include <netinet/tcp.h> 381ae349f5Scvs2svn #include <arpa/inet.h> 391ae349f5Scvs2svn 401ae349f5Scvs2svn #ifndef NOALIAS 411ae349f5Scvs2svn #include <alias.h> 421ae349f5Scvs2svn #endif 431ae349f5Scvs2svn #include <errno.h> 441ae349f5Scvs2svn #include <stdio.h> 451ae349f5Scvs2svn #include <stdlib.h> 461ae349f5Scvs2svn #include <string.h> 471ae349f5Scvs2svn #include <termios.h> 481ae349f5Scvs2svn #include <unistd.h> 491ae349f5Scvs2svn 501ae349f5Scvs2svn #include "command.h" 511ae349f5Scvs2svn #include "mbuf.h" 521ae349f5Scvs2svn #include "log.h" 531ae349f5Scvs2svn #include "defs.h" 541ae349f5Scvs2svn #include "timer.h" 551ae349f5Scvs2svn #include "fsm.h" 56879ed6faSBrian Somers #include "lqr.h" 571ae349f5Scvs2svn #include "hdlc.h" 581ae349f5Scvs2svn #include "loadalias.h" 591ae349f5Scvs2svn #include "vars.h" 605828db6dSBrian Somers #include "throughput.h" 615828db6dSBrian Somers #include "iplist.h" 62eaa4df37SBrian Somers #include "slcompress.h" 635828db6dSBrian Somers #include "ipcp.h" 641ae349f5Scvs2svn #include "filter.h" 657a6f8720SBrian Somers #include "bundle.h" 661ae349f5Scvs2svn #include "vjcomp.h" 671ae349f5Scvs2svn #include "lcp.h" 681ae349f5Scvs2svn #include "modem.h" 691ae349f5Scvs2svn #include "tun.h" 701ae349f5Scvs2svn #include "ip.h" 711ae349f5Scvs2svn 721ae349f5Scvs2svn static const u_short interactive_ports[32] = { 731ae349f5Scvs2svn 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 741ae349f5Scvs2svn 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 751ae349f5Scvs2svn }; 761ae349f5Scvs2svn 771ae349f5Scvs2svn #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 781ae349f5Scvs2svn 791ae349f5Scvs2svn static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 801ae349f5Scvs2svn 811ae349f5Scvs2svn static int 821ae349f5Scvs2svn PortMatch(int op, u_short pport, u_short rport) 831ae349f5Scvs2svn { 841ae349f5Scvs2svn switch (op) { 851ae349f5Scvs2svn case OP_EQ: 861ae349f5Scvs2svn return (pport == rport); 871ae349f5Scvs2svn case OP_GT: 881ae349f5Scvs2svn return (pport > rport); 891ae349f5Scvs2svn case OP_LT: 901ae349f5Scvs2svn return (pport < rport); 911ae349f5Scvs2svn default: 921ae349f5Scvs2svn return (0); 931ae349f5Scvs2svn } 941ae349f5Scvs2svn } 951ae349f5Scvs2svn 961ae349f5Scvs2svn /* 971ae349f5Scvs2svn * Check a packet against with defined filters 981ae349f5Scvs2svn */ 991ae349f5Scvs2svn static int 1005ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 1011ae349f5Scvs2svn { 1021ae349f5Scvs2svn int gotinfo, cproto, estab, n; 1031ae349f5Scvs2svn struct tcphdr *th; 1041ae349f5Scvs2svn struct udphdr *uh; 1051ae349f5Scvs2svn struct icmp *ih; 1061ae349f5Scvs2svn char *ptop; 1071ae349f5Scvs2svn u_short sport, dport; 1085ca5389aSBrian Somers struct filterent *fp = filter->rule; 1091ae349f5Scvs2svn 1101ae349f5Scvs2svn if (fp->action) { 1111ae349f5Scvs2svn cproto = gotinfo = estab = 0; 1121ae349f5Scvs2svn sport = dport = 0; 1131ae349f5Scvs2svn for (n = 0; n < MAXFILTERS; n++) { 1141ae349f5Scvs2svn if (fp->action) { 1151ae349f5Scvs2svn /* permit fragments on in and out filter */ 1165ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 1171ae349f5Scvs2svn return (A_PERMIT); 1185ca5389aSBrian Somers 1191ae349f5Scvs2svn LogPrintf(LogDEBUG, "rule = %d\n", n); 1201ae349f5Scvs2svn if ((pip->ip_src.s_addr & fp->smask.s_addr) == 1211ae349f5Scvs2svn (fp->saddr.s_addr & fp->smask.s_addr) && 1221ae349f5Scvs2svn (pip->ip_dst.s_addr & fp->dmask.s_addr) == 1231ae349f5Scvs2svn (fp->daddr.s_addr & fp->dmask.s_addr)) { 1241ae349f5Scvs2svn if (fp->proto) { 1251ae349f5Scvs2svn if (!gotinfo) { 1261ae349f5Scvs2svn ptop = (char *) pip + (pip->ip_hl << 2); 1271ae349f5Scvs2svn 1281ae349f5Scvs2svn switch (pip->ip_p) { 1291ae349f5Scvs2svn case IPPROTO_ICMP: 1301ae349f5Scvs2svn cproto = P_ICMP; 1311ae349f5Scvs2svn ih = (struct icmp *) ptop; 1321ae349f5Scvs2svn sport = ih->icmp_type; 1331ae349f5Scvs2svn estab = 1; 1341ae349f5Scvs2svn break; 1351ae349f5Scvs2svn case IPPROTO_UDP: 1361ae349f5Scvs2svn cproto = P_UDP; 1371ae349f5Scvs2svn uh = (struct udphdr *) ptop; 1381ae349f5Scvs2svn sport = ntohs(uh->uh_sport); 1391ae349f5Scvs2svn dport = ntohs(uh->uh_dport); 1401ae349f5Scvs2svn estab = 1; 1411ae349f5Scvs2svn break; 1421ae349f5Scvs2svn case IPPROTO_TCP: 1431ae349f5Scvs2svn cproto = P_TCP; 1441ae349f5Scvs2svn th = (struct tcphdr *) ptop; 1451ae349f5Scvs2svn sport = ntohs(th->th_sport); 1461ae349f5Scvs2svn dport = ntohs(th->th_dport); 1471ae349f5Scvs2svn estab = (th->th_flags & TH_ACK); 1481ae349f5Scvs2svn if (estab == 0) 1491ae349f5Scvs2svn LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n", 1501ae349f5Scvs2svn th->th_flags, sport, dport); 1511ae349f5Scvs2svn break; 1521ae349f5Scvs2svn default: 1531ae349f5Scvs2svn return (A_DENY);/* We'll block unknown type of packet */ 1541ae349f5Scvs2svn } 1551ae349f5Scvs2svn gotinfo = 1; 1565ca5389aSBrian Somers LogPrintf(LogDEBUG, "dir = %p, proto = %d, srcop = %d," 1575ca5389aSBrian Somers " dstop = %d, estab = %d\n", fp, cproto, 1581ae349f5Scvs2svn fp->opt.srcop, fp->opt.dstop, estab); 1591ae349f5Scvs2svn } 1601ae349f5Scvs2svn LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d," 1611ae349f5Scvs2svn " dport = %d\n", n, cproto, sport, dport); 1621ae349f5Scvs2svn LogPrintf(LogDEBUG, "check0: action = %d\n", fp->action); 1631ae349f5Scvs2svn 1641ae349f5Scvs2svn if (cproto == fp->proto) { 1651ae349f5Scvs2svn if ((fp->opt.srcop == OP_NONE || 1661ae349f5Scvs2svn PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) 1671ae349f5Scvs2svn && 1681ae349f5Scvs2svn (fp->opt.dstop == OP_NONE || 1691ae349f5Scvs2svn PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) 1701ae349f5Scvs2svn && 1711ae349f5Scvs2svn (fp->opt.estab == 0 || estab)) { 1721ae349f5Scvs2svn return (fp->action); 1731ae349f5Scvs2svn } 1741ae349f5Scvs2svn } 1751ae349f5Scvs2svn } else { 1761ae349f5Scvs2svn /* Address is mached. Make a decision. */ 1771ae349f5Scvs2svn LogPrintf(LogDEBUG, "check1: action = %d\n", fp->action); 1781ae349f5Scvs2svn return (fp->action); 1791ae349f5Scvs2svn } 1801ae349f5Scvs2svn } 1811ae349f5Scvs2svn } 1821ae349f5Scvs2svn fp++; 1831ae349f5Scvs2svn } 1841ae349f5Scvs2svn return (A_DENY); /* No rule is mached. Deny this packet */ 1851ae349f5Scvs2svn } 1861ae349f5Scvs2svn return (A_PERMIT); /* No rule is given. Permit this packet */ 1871ae349f5Scvs2svn } 1881ae349f5Scvs2svn 1895ca5389aSBrian Somers #ifdef notdef 1901ae349f5Scvs2svn static void 1911ae349f5Scvs2svn IcmpError(struct ip * pip, int code) 1921ae349f5Scvs2svn { 1931ae349f5Scvs2svn struct mbuf *bp; 1941ae349f5Scvs2svn 1951ae349f5Scvs2svn if (pip->ip_p != IPPROTO_ICMP) { 1961ae349f5Scvs2svn bp = mballoc(cnt, MB_IPIN); 1971ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), ptr, cnt); 1981ae349f5Scvs2svn SendPppFrame(bp); 199ab886ad0SBrian Somers if (ipKeepAlive) 200ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 2015828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2021ae349f5Scvs2svn } 2031ae349f5Scvs2svn } 2045ca5389aSBrian Somers #endif 2051ae349f5Scvs2svn 2061ae349f5Scvs2svn /* 2071ae349f5Scvs2svn * For debugging aid. 2081ae349f5Scvs2svn */ 2091ae349f5Scvs2svn int 2105ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 2111ae349f5Scvs2svn { 2121ae349f5Scvs2svn struct ip *pip; 2131ae349f5Scvs2svn struct tcphdr *th; 2141ae349f5Scvs2svn struct udphdr *uh; 2151ae349f5Scvs2svn struct icmp *icmph; 2161ae349f5Scvs2svn char *ptop; 2171ae349f5Scvs2svn int mask, len, n; 2181ae349f5Scvs2svn int pri = PRI_NORMAL; 2191ae349f5Scvs2svn int logit, loglen; 2201ae349f5Scvs2svn static char logbuf[200]; 2211ae349f5Scvs2svn 2225ca5389aSBrian Somers logit = LogIsKept(LogTCPIP) && filter->logok; 2231ae349f5Scvs2svn loglen = 0; 2241ae349f5Scvs2svn 2251ae349f5Scvs2svn pip = (struct ip *) cp; 2261ae349f5Scvs2svn 2271ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2285ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 2291ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2301ae349f5Scvs2svn } 2311ae349f5Scvs2svn ptop = (cp + (pip->ip_hl << 2)); 2321ae349f5Scvs2svn 2331ae349f5Scvs2svn switch (pip->ip_p) { 2341ae349f5Scvs2svn case IPPROTO_ICMP: 2351ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2361ae349f5Scvs2svn icmph = (struct icmp *) ptop; 2371ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2381ae349f5Scvs2svn "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 2391ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2401ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2411ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 2421ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2431ae349f5Scvs2svn } 2441ae349f5Scvs2svn break; 2451ae349f5Scvs2svn case IPPROTO_UDP: 2461ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2471ae349f5Scvs2svn uh = (struct udphdr *) ptop; 2481ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2491ae349f5Scvs2svn "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 2501ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2511ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2521ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 2531ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2541ae349f5Scvs2svn } 2551ae349f5Scvs2svn break; 2561ae349f5Scvs2svn case IPPROTO_TCP: 2571ae349f5Scvs2svn th = (struct tcphdr *) ptop; 2581ae349f5Scvs2svn if (pip->ip_tos == IPTOS_LOWDELAY) 2591ae349f5Scvs2svn pri = PRI_FAST; 2601ae349f5Scvs2svn else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 2611ae349f5Scvs2svn if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 2621ae349f5Scvs2svn pri = PRI_FAST; 2631ae349f5Scvs2svn } 2641ae349f5Scvs2svn if (logit && loglen < sizeof logbuf) { 2651ae349f5Scvs2svn len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 2661ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2671ae349f5Scvs2svn "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 2681ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2691ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2701ae349f5Scvs2svn "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 2711ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2721ae349f5Scvs2svn n = 0; 2731ae349f5Scvs2svn for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 2741ae349f5Scvs2svn if (th->th_flags & mask) { 2751ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 2761ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2771ae349f5Scvs2svn } 2781ae349f5Scvs2svn n++; 2791ae349f5Scvs2svn } 2801ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2811ae349f5Scvs2svn " seq:%x ack:%x (%d/%d)", 2821ae349f5Scvs2svn ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 2831ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2841ae349f5Scvs2svn if ((th->th_flags & TH_SYN) && nb > 40) { 2851ae349f5Scvs2svn u_short *sp; 2861ae349f5Scvs2svn 2871ae349f5Scvs2svn ptop += 20; 2881ae349f5Scvs2svn sp = (u_short *) ptop; 2891ae349f5Scvs2svn if (ntohs(sp[0]) == 0x0204) { 2901ae349f5Scvs2svn snprintf(logbuf + loglen, sizeof logbuf - loglen, 2911ae349f5Scvs2svn " MSS = %d", ntohs(sp[1])); 2921ae349f5Scvs2svn loglen += strlen(logbuf + loglen); 2931ae349f5Scvs2svn } 2941ae349f5Scvs2svn } 2951ae349f5Scvs2svn } 2961ae349f5Scvs2svn break; 2971ae349f5Scvs2svn } 2981ae349f5Scvs2svn 2995ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 3001ae349f5Scvs2svn if (logit) 3011ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3025ca5389aSBrian Somers #ifdef notdef 3031ae349f5Scvs2svn if (direction == 0) 3041ae349f5Scvs2svn IcmpError(pip, pri); 3055ca5389aSBrian Somers #endif 3061ae349f5Scvs2svn return (-1); 3071ae349f5Scvs2svn } else { 3085ca5389aSBrian Somers /* Check Keep Alive filter */ 3095ca5389aSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) { 3101ae349f5Scvs2svn if (logit) 3111ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3121ae349f5Scvs2svn ipKeepAlive = 0; 3131ae349f5Scvs2svn } else { 3141ae349f5Scvs2svn if (logit) 3151ae349f5Scvs2svn LogPrintf(LogTCPIP, "%s\n", logbuf); 3161ae349f5Scvs2svn ipKeepAlive = 1; 3171ae349f5Scvs2svn } 3181ae349f5Scvs2svn return (pri); 3191ae349f5Scvs2svn } 3201ae349f5Scvs2svn } 3211ae349f5Scvs2svn 3221ae349f5Scvs2svn void 3237a6f8720SBrian Somers IpInput(struct bundle *bundle, struct mbuf * bp) 3247a6f8720SBrian Somers { 3251ae349f5Scvs2svn u_char *cp; 3261ae349f5Scvs2svn struct mbuf *wp; 3271ae349f5Scvs2svn int nb, nw; 3281ae349f5Scvs2svn struct tun_data tun; 3291ae349f5Scvs2svn 3301ae349f5Scvs2svn tun_fill_header(tun, AF_INET); 3311ae349f5Scvs2svn cp = tun.data; 3321ae349f5Scvs2svn nb = 0; 3331ae349f5Scvs2svn for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 3341ae349f5Scvs2svn if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 3351ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: Packet too large (%d) - dropped\n", 3361ae349f5Scvs2svn plength(bp)); 3371ae349f5Scvs2svn pfree(bp); 3381ae349f5Scvs2svn return; 3391ae349f5Scvs2svn } 3401ae349f5Scvs2svn memcpy(cp, MBUF_CTOP(wp), wp->cnt); 3411ae349f5Scvs2svn cp += wp->cnt; 3421ae349f5Scvs2svn nb += wp->cnt; 3431ae349f5Scvs2svn } 3441ae349f5Scvs2svn 3451ae349f5Scvs2svn #ifndef NOALIAS 3461ae349f5Scvs2svn if (mode & MODE_ALIAS) { 3471ae349f5Scvs2svn struct tun_data *frag; 3481ae349f5Scvs2svn int iresult; 3491ae349f5Scvs2svn char *fptr; 3501ae349f5Scvs2svn 3511ae349f5Scvs2svn iresult = VarPacketAliasIn(tun.data, sizeof tun.data); 3521ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 3531ae349f5Scvs2svn 3541ae349f5Scvs2svn if (nb > MAX_MRU) { 3551ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: Problem with IP header length\n"); 3561ae349f5Scvs2svn pfree(bp); 3571ae349f5Scvs2svn return; 3581ae349f5Scvs2svn } 3591ae349f5Scvs2svn if (iresult == PKT_ALIAS_OK 3601ae349f5Scvs2svn || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 3615ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 3621ae349f5Scvs2svn pfree(bp); 3631ae349f5Scvs2svn return; 3641ae349f5Scvs2svn } 3655828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 3661ae349f5Scvs2svn 3671ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 3681ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 3697a6f8720SBrian Somers nw = write(bundle->tun_fd, &tun, nb); 3701ae349f5Scvs2svn if (nw != nb) 3711ae349f5Scvs2svn if (nw == -1) 3721ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 3731ae349f5Scvs2svn strerror(errno)); 3741ae349f5Scvs2svn else 3751ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 3761ae349f5Scvs2svn 3771ae349f5Scvs2svn if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 3781ae349f5Scvs2svn while ((fptr = VarPacketAliasGetFragment(tun.data)) != NULL) { 3791ae349f5Scvs2svn VarPacketAliasFragmentIn(tun.data, fptr); 3801ae349f5Scvs2svn nb = ntohs(((struct ip *) fptr)->ip_len); 3811ae349f5Scvs2svn frag = (struct tun_data *) 3821ae349f5Scvs2svn ((char *)fptr - sizeof tun + sizeof tun.data); 3831ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 3847a6f8720SBrian Somers nw = write(bundle->tun_fd, frag, nb); 3851ae349f5Scvs2svn if (nw != nb) 3861ae349f5Scvs2svn if (nw == -1) 3871ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 3881ae349f5Scvs2svn strerror(errno)); 3891ae349f5Scvs2svn else 3901ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 3911ae349f5Scvs2svn free(frag); 3921ae349f5Scvs2svn } 3931ae349f5Scvs2svn } 3941ae349f5Scvs2svn } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 3951ae349f5Scvs2svn nb = ntohs(((struct ip *) tun.data)->ip_len); 3961ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 3971ae349f5Scvs2svn frag = (struct tun_data *)malloc(nb); 3981ae349f5Scvs2svn if (frag == NULL) 3991ae349f5Scvs2svn LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n"); 4001ae349f5Scvs2svn else { 4011ae349f5Scvs2svn tun_fill_header(*frag, AF_INET); 4021ae349f5Scvs2svn memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 4031ae349f5Scvs2svn VarPacketAliasSaveFragment(frag->data); 4041ae349f5Scvs2svn } 4051ae349f5Scvs2svn } 4061ae349f5Scvs2svn } else 4071ae349f5Scvs2svn #endif /* #ifndef NOALIAS */ 4081ae349f5Scvs2svn { /* no aliasing */ 4095ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 4101ae349f5Scvs2svn pfree(bp); 4111ae349f5Scvs2svn return; 4121ae349f5Scvs2svn } 4135828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4141ae349f5Scvs2svn nb += sizeof tun - sizeof tun.data; 4157a6f8720SBrian Somers nw = write(bundle->tun_fd, &tun, nb); 4161ae349f5Scvs2svn if (nw != nb) 4171ae349f5Scvs2svn if (nw == -1) 4181ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, strerror(errno)); 4191ae349f5Scvs2svn else 4201ae349f5Scvs2svn LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 4211ae349f5Scvs2svn } 4221ae349f5Scvs2svn pfree(bp); 4231ae349f5Scvs2svn 424ab886ad0SBrian Somers if (ipKeepAlive) 425ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 4261ae349f5Scvs2svn } 4271ae349f5Scvs2svn 4281ae349f5Scvs2svn static struct mqueue IpOutputQueues[PRI_FAST + 1]; 4291ae349f5Scvs2svn 4301ae349f5Scvs2svn void 4311ae349f5Scvs2svn IpEnqueue(int pri, char *ptr, int count) 4321ae349f5Scvs2svn { 4331ae349f5Scvs2svn struct mbuf *bp; 4341ae349f5Scvs2svn 4351ae349f5Scvs2svn bp = mballoc(count, MB_IPQ); 4361ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), ptr, count); 4371ae349f5Scvs2svn Enqueue(&IpOutputQueues[pri], bp); 4381ae349f5Scvs2svn } 4391ae349f5Scvs2svn 4401ae349f5Scvs2svn int 441f4768038SBrian Somers ip_QueueLen() 4421ae349f5Scvs2svn { 4431ae349f5Scvs2svn struct mqueue *queue; 444f4768038SBrian Somers int result = 0; 4451ae349f5Scvs2svn 446f4768038SBrian Somers for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--) 447f4768038SBrian Somers result += queue->qlen; 448f4768038SBrian Somers 449f4768038SBrian Somers return result; 4501ae349f5Scvs2svn } 4511ae349f5Scvs2svn 4521ae349f5Scvs2svn void 453f4768038SBrian Somers IpStartOutput(struct link *l, struct bundle *bundle) 4541ae349f5Scvs2svn { 4551ae349f5Scvs2svn struct mqueue *queue; 4561ae349f5Scvs2svn struct mbuf *bp; 4571ae349f5Scvs2svn int cnt; 4581ae349f5Scvs2svn 4595828db6dSBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) 4601ae349f5Scvs2svn return; 4611ae349f5Scvs2svn for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) { 4621ae349f5Scvs2svn if (queue->top) { 4631ae349f5Scvs2svn bp = Dequeue(queue); 4641ae349f5Scvs2svn if (bp) { 4651ae349f5Scvs2svn cnt = plength(bp); 466f4768038SBrian Somers SendPppFrame(l, bp, bundle); 467ab886ad0SBrian Somers if (ipKeepAlive) 468ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 4695828db6dSBrian Somers ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt); 4701ae349f5Scvs2svn break; 4711ae349f5Scvs2svn } 4721ae349f5Scvs2svn } 4731ae349f5Scvs2svn } 4741ae349f5Scvs2svn } 475