1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP IP Protocol Interface 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 202faae814SBrian Somers * $Id: ip.c,v 1.65 1999/07/27 23:43:59 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai * o Return ICMP message for filterd packet 24af57ed9fSAtsushi Murai * and optionaly record it into log. 25af57ed9fSAtsushi Murai */ 26972a1bcfSBrian Somers #include <sys/param.h> 277884358fSBrian Somers #if defined(__OpenBSD__) || defined(__NetBSD__) 286a6b4bbbSBrian Somers #include <sys/socket.h> 2992b09558SBrian Somers #endif 3075240ed1SBrian Somers #include <netinet/in.h> 31af57ed9fSAtsushi Murai #include <netinet/in_systm.h> 32af57ed9fSAtsushi Murai #include <netinet/ip.h> 33af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h> 34af57ed9fSAtsushi Murai #include <netinet/udp.h> 35af57ed9fSAtsushi Murai #include <netinet/tcp.h> 36ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 371fa665f5SBrian Somers #include <sys/un.h> 3875240ed1SBrian Somers 3957fd05c4SBrian Somers #include <errno.h> 4075240ed1SBrian Somers #include <stdio.h> 4175240ed1SBrian Somers #include <stdlib.h> 4275240ed1SBrian Somers #include <string.h> 435d9e6103SBrian Somers #include <termios.h> 4475240ed1SBrian Somers #include <unistd.h> 4575240ed1SBrian Somers 465d9e6103SBrian Somers #include "layer.h" 475d9e6103SBrian Somers #include "proto.h" 48927145beSBrian Somers #include "mbuf.h" 49927145beSBrian Somers #include "log.h" 5075240ed1SBrian Somers #include "defs.h" 5175240ed1SBrian Somers #include "timer.h" 5275240ed1SBrian Somers #include "fsm.h" 53879ed6faSBrian Somers #include "lqr.h" 5475240ed1SBrian Somers #include "hdlc.h" 555828db6dSBrian Somers #include "throughput.h" 565828db6dSBrian Somers #include "iplist.h" 57eaa4df37SBrian Somers #include "slcompress.h" 5875240ed1SBrian Somers #include "ipcp.h" 591ae349f5Scvs2svn #include "filter.h" 602f786681SBrian Somers #include "descriptor.h" 6175240ed1SBrian Somers #include "lcp.h" 623b0f8d2eSBrian Somers #include "ccp.h" 633b0f8d2eSBrian Somers #include "link.h" 643b0f8d2eSBrian Somers #include "mp.h" 65972a1bcfSBrian Somers #ifndef NORADIUS 66972a1bcfSBrian Somers #include "radius.h" 67972a1bcfSBrian Somers #endif 687a6f8720SBrian Somers #include "bundle.h" 691ae349f5Scvs2svn #include "vjcomp.h" 706a6b4bbbSBrian Somers #include "tun.h" 7175240ed1SBrian Somers #include "ip.h" 72af57ed9fSAtsushi Murai 73b6e82f33SBrian Somers static const u_short interactive_ports[32] = { 7476bd0c0aSDoug Rabson 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7522d1222bSBrian Somers 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 76af57ed9fSAtsushi Murai }; 77af57ed9fSAtsushi Murai 7876bd0c0aSDoug Rabson #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 79af57ed9fSAtsushi Murai 80b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 81af57ed9fSAtsushi Murai 82cad7e742SBrian Somers static __inline int 83944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 84af57ed9fSAtsushi Murai { 85af57ed9fSAtsushi Murai switch (op) { 86af57ed9fSAtsushi Murai case OP_EQ: 87af57ed9fSAtsushi Murai return (pport == rport); 88af57ed9fSAtsushi Murai case OP_GT: 89af57ed9fSAtsushi Murai return (pport > rport); 90af57ed9fSAtsushi Murai case OP_LT: 91af57ed9fSAtsushi Murai return (pport < rport); 92af57ed9fSAtsushi Murai default: 93af57ed9fSAtsushi Murai return (0); 94af57ed9fSAtsushi Murai } 95af57ed9fSAtsushi Murai } 96af57ed9fSAtsushi Murai 97af57ed9fSAtsushi Murai /* 985d9e6103SBrian Somers * Check a packet against a defined filter 99cad7e742SBrian Somers * Returns 0 to accept the packet, non-zero to drop the packet 100cad7e742SBrian Somers * 101cad7e742SBrian Somers * If filtering is enabled, the initial fragment of a datagram must 102cad7e742SBrian Somers * contain the complete protocol header, and subsequent fragments 103cad7e742SBrian Somers * must not attempt to over-write it. 104af57ed9fSAtsushi Murai */ 105af57ed9fSAtsushi Murai static int 106cad7e742SBrian Somers FilterCheck(const struct ip *pip, const struct filter *filter) 107af57ed9fSAtsushi Murai { 108cad7e742SBrian Somers int gotinfo; /* true if IP payload decoded */ 109cad7e742SBrian Somers int cproto; /* P_* protocol type if (gotinfo) */ 110cad7e742SBrian Somers int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 111cad7e742SBrian Somers u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 112cad7e742SBrian Somers int n; /* filter rule to process */ 113cad7e742SBrian Somers int len; /* bytes used in dbuff */ 114cad7e742SBrian Somers int didname; /* true if filter header printed */ 115cad7e742SBrian Somers int match; /* true if condition matched */ 116cad7e742SBrian Somers const struct filterent *fp = filter->rule; 1178390b576SBrian Somers char dbuff[100]; 118af57ed9fSAtsushi Murai 119cad7e742SBrian Somers if (fp->f_action == A_NONE) 120cad7e742SBrian Somers return (0); /* No rule is given. Permit this packet */ 121cad7e742SBrian Somers 122cad7e742SBrian Somers /* Deny any packet fragment that tries to over-write the header. 123cad7e742SBrian Somers * Since we no longer have the real header available, punt on the 124cad7e742SBrian Somers * largest normal header - 20 bytes for TCP without options, rounded 125cad7e742SBrian Somers * up to the next possible fragment boundary. Since the smallest 126cad7e742SBrian Somers * `legal' MTU is 576, and the smallest recommended MTU is 296, any 127cad7e742SBrian Somers * fragmentation within this range is dubious at best */ 128cad7e742SBrian Somers len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 129cad7e742SBrian Somers if (len > 0) { /* Not first fragment within datagram */ 130cad7e742SBrian Somers if (len < (24 >> 3)) /* don't allow fragment to over-write header */ 131cad7e742SBrian Somers return (1); 132cad7e742SBrian Somers /* permit fragments on in and out filter */ 133cad7e742SBrian Somers return (filter->fragok); 134cad7e742SBrian Somers } 135cad7e742SBrian Somers 13663f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 137af57ed9fSAtsushi Murai sport = dport = 0; 138cad7e742SBrian Somers for (n = 0; n < MAXFILTERS; ) { 139cad7e742SBrian Somers if (fp->f_action == A_NONE) { 140cad7e742SBrian Somers n++; 141cad7e742SBrian Somers fp++; 142cad7e742SBrian Somers continue; 143cad7e742SBrian Somers } 1445ca5389aSBrian Somers 145cad7e742SBrian Somers if (!didname) { 146dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1478390b576SBrian Somers didname = 1; 148cad7e742SBrian Somers } 1498390b576SBrian Somers 150cad7e742SBrian Somers match = 0; 151cad7e742SBrian Somers if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 152cad7e742SBrian Somers fp->f_src.mask.s_addr) && 153cad7e742SBrian Somers !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 154cad7e742SBrian Somers fp->f_dst.mask.s_addr)) { 155cad7e742SBrian Somers if (fp->f_proto != P_NONE) { 156af57ed9fSAtsushi Murai if (!gotinfo) { 157cad7e742SBrian Somers const char *ptop = (const char *) pip + (pip->ip_hl << 2); 158cad7e742SBrian Somers const struct tcphdr *th; 159cad7e742SBrian Somers const struct udphdr *uh; 160cad7e742SBrian Somers const struct icmp *ih; 161cad7e742SBrian Somers int datalen; /* IP datagram length */ 162af57ed9fSAtsushi Murai 163cad7e742SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 164af57ed9fSAtsushi Murai switch (pip->ip_p) { 165af57ed9fSAtsushi Murai case IPPROTO_ICMP: 166944f7098SBrian Somers cproto = P_ICMP; 167cad7e742SBrian Somers if (datalen < 8) /* ICMP must be at least 8 octets */ 168cad7e742SBrian Somers return (1); 169cad7e742SBrian Somers ih = (const struct icmp *) ptop; 170944f7098SBrian Somers sport = ih->icmp_type; 17163f98b41SBrian Somers estab = syn = finrst = -1; 172dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1738390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 174af57ed9fSAtsushi Murai break; 175eee772ecSBrian Somers case IPPROTO_IGMP: 1761f9e5fe5SBrian Somers cproto = P_IGMP; 177cad7e742SBrian Somers if (datalen < 8) /* IGMP uses 8-octet messages */ 178cad7e742SBrian Somers return (1); 1791f9e5fe5SBrian Somers estab = syn = finrst = -1; 1801f9e5fe5SBrian Somers sport = ntohs(0); 1811f9e5fe5SBrian Somers break; 1822faae814SBrian Somers case IPPROTO_OSPFIGP: 1832faae814SBrian Somers cproto = P_OSPF; 1842faae814SBrian Somers if (datalen < 8) /* IGMP uses 8-octet messages */ 1852faae814SBrian Somers return (1); 1862faae814SBrian Somers estab = syn = finrst = -1; 1872faae814SBrian Somers sport = ntohs(0); 1882faae814SBrian Somers break; 1891f9e5fe5SBrian Somers case IPPROTO_UDP: 190eee772ecSBrian Somers case IPPROTO_IPIP: 191944f7098SBrian Somers cproto = P_UDP; 192cad7e742SBrian Somers if (datalen < 8) /* UDP header is 8 octets */ 193cad7e742SBrian Somers return (1); 194cad7e742SBrian Somers uh = (const struct udphdr *) ptop; 195944f7098SBrian Somers sport = ntohs(uh->uh_sport); 196944f7098SBrian Somers dport = ntohs(uh->uh_dport); 19763f98b41SBrian Somers estab = syn = finrst = -1; 198dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1998390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 2008390b576SBrian Somers sport, dport); 201af57ed9fSAtsushi Murai break; 202af57ed9fSAtsushi Murai case IPPROTO_TCP: 203944f7098SBrian Somers cproto = P_TCP; 204cad7e742SBrian Somers th = (const struct tcphdr *) ptop; 205cad7e742SBrian Somers /* TCP headers are variable length. The following code 206cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 207cad7e742SBrian Somers * the datagram is too short 208cad7e742SBrian Somers */ 209cad7e742SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) 210cad7e742SBrian Somers return (1); 211944f7098SBrian Somers sport = ntohs(th->th_sport); 212944f7098SBrian Somers dport = ntohs(th->th_dport); 213af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 21463f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 21563f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 2162b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 2172b81c773SBrian Somers if (!estab) 2188390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 2198390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 220927145beSBrian Somers th->th_flags, sport, dport); 2212b81c773SBrian Somers else 2222b81c773SBrian Somers *dbuff = '\0'; 2232b81c773SBrian Somers } 224af57ed9fSAtsushi Murai break; 225af57ed9fSAtsushi Murai default: 226cad7e742SBrian Somers return (1); /* We'll block unknown type of packet */ 227af57ed9fSAtsushi Murai } 228cad7e742SBrian Somers 229dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 2308390b576SBrian Somers if (estab != -1) { 2318390b576SBrian Somers len = strlen(dbuff); 23263f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 23363f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 23463f98b41SBrian Somers estab, syn, finrst); 235af57ed9fSAtsushi Murai } 236dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 2378390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 2388390b576SBrian Somers } 2398390b576SBrian Somers gotinfo = 1; 2408390b576SBrian Somers } 241dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 242cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 2438390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 244cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 2458390b576SBrian Somers len = strlen(dbuff); 2468390b576SBrian Somers } else 2478390b576SBrian Somers len = 0; 248cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 2498390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 250cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 251cad7e742SBrian Somers fp->f_dstport); 2528390b576SBrian Somers } else if (!len) 2538390b576SBrian Somers *dbuff = '\0'; 2548390b576SBrian Somers 255dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 2568390b576SBrian Somers "check against proto %s%s, action = %s\n", 257cad7e742SBrian Somers n, filter_Proto2Nam(fp->f_proto), 258cad7e742SBrian Somers dbuff, filter_Action2Nam(fp->f_action)); 2598390b576SBrian Somers } 260927145beSBrian Somers 261cad7e742SBrian Somers if (cproto == fp->f_proto) { 262cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 263cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 264cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 265cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 266cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 267cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 268cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 269cad7e742SBrian Somers match = 1; 270af57ed9fSAtsushi Murai } 271af57ed9fSAtsushi Murai } 272af57ed9fSAtsushi Murai } else { 273cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 274dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 275cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 276cad7e742SBrian Somers match = 1; 277af57ed9fSAtsushi Murai } 2788390b576SBrian Somers } else 279dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 280cad7e742SBrian Somers 281cad7e742SBrian Somers if (match != fp->f_invert) { 282cad7e742SBrian Somers /* Take specified action */ 283cad7e742SBrian Somers if (fp->f_action < A_NONE) 284cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 285cad7e742SBrian Somers else 286cad7e742SBrian Somers return (fp->f_action != A_PERMIT); 287cad7e742SBrian Somers } else { 288cad7e742SBrian Somers n++; 289af57ed9fSAtsushi Murai fp++; 290af57ed9fSAtsushi Murai } 291af57ed9fSAtsushi Murai } 292cad7e742SBrian Somers return (1); /* No rule is mached. Deny this packet */ 293af57ed9fSAtsushi Murai } 294af57ed9fSAtsushi Murai 2955ca5389aSBrian Somers #ifdef notdef 296af57ed9fSAtsushi Murai static void 297944f7098SBrian Somers IcmpError(struct ip *pip, int code) 298af57ed9fSAtsushi Murai { 299af57ed9fSAtsushi Murai struct mbuf *bp; 300af57ed9fSAtsushi Murai 301af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 302dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 30375240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 304dd7e2610SBrian Somers vj_SendFrame(bp); 3055828db6dSBrian Somers ipcp_AddOutOctets(cnt); 3061ae349f5Scvs2svn } 307af57ed9fSAtsushi Murai } 308af57ed9fSAtsushi Murai #endif 309af57ed9fSAtsushi Murai 310af57ed9fSAtsushi Murai /* 311af57ed9fSAtsushi Murai * For debugging aid. 312af57ed9fSAtsushi Murai */ 313af57ed9fSAtsushi Murai int 3145ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 315af57ed9fSAtsushi Murai { 316af57ed9fSAtsushi Murai struct ip *pip; 317af57ed9fSAtsushi Murai struct tcphdr *th; 318af57ed9fSAtsushi Murai struct udphdr *uh; 319af57ed9fSAtsushi Murai struct icmp *icmph; 320af57ed9fSAtsushi Murai char *ptop; 321af57ed9fSAtsushi Murai int mask, len, n; 322af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 32355a8cdeaSBrian Somers int logit, loglen; 324d93d3a9cSBrian Somers char logbuf[200]; 325af57ed9fSAtsushi Murai 326dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 32755a8cdeaSBrian Somers loglen = 0; 328af57ed9fSAtsushi Murai 329af57ed9fSAtsushi Murai pip = (struct ip *) cp; 330af57ed9fSAtsushi Murai 33155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 3325ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 33355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33455a8cdeaSBrian Somers } 335af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 336af57ed9fSAtsushi Murai 337af57ed9fSAtsushi Murai switch (pip->ip_p) { 338af57ed9fSAtsushi Murai case IPPROTO_ICMP: 33955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 340af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 34155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34255a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 34355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 34455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34555a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 34655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 347af57ed9fSAtsushi Murai } 348af57ed9fSAtsushi Murai break; 349af57ed9fSAtsushi Murai case IPPROTO_UDP: 35055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 351af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 35255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35355a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 35455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 35555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35655a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 35755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 358af57ed9fSAtsushi Murai } 359af57ed9fSAtsushi Murai break; 3602faae814SBrian Somers case IPPROTO_OSPFIGP: 3612faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 3622faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3632faae814SBrian Somers "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 3642faae814SBrian Somers loglen += strlen(logbuf + loglen); 3652faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3662faae814SBrian Somers "%s", inet_ntoa(pip->ip_dst)); 3672faae814SBrian Somers loglen += strlen(logbuf + loglen); 3682faae814SBrian Somers } 3692faae814SBrian Somers break; 370eee772ecSBrian Somers case IPPROTO_IPIP: 371eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 372eee772ecSBrian Somers uh = (struct udphdr *) ptop; 373eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 374eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 375eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 376eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 377eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 378eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 379eee772ecSBrian Somers } 380eee772ecSBrian Somers break; 381eee772ecSBrian Somers case IPPROTO_IGMP: 382eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 383eee772ecSBrian Somers uh = (struct udphdr *) ptop; 384eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 385eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 386eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 387eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 388eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 389eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 390eee772ecSBrian Somers } 391eee772ecSBrian Somers break; 392af57ed9fSAtsushi Murai case IPPROTO_TCP: 393af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 394af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 395af57ed9fSAtsushi Murai pri = PRI_FAST; 39676bd0c0aSDoug Rabson else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 397af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 398af57ed9fSAtsushi Murai pri = PRI_FAST; 399af57ed9fSAtsushi Murai } 40055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 401af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 40255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 40355a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 40455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 40555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 40655a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 40755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 408af57ed9fSAtsushi Murai n = 0; 409af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 41055a8cdeaSBrian Somers if (th->th_flags & mask) { 41155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 41255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 41355a8cdeaSBrian Somers } 414af57ed9fSAtsushi Murai n++; 415af57ed9fSAtsushi Murai } 41655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 4173a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 4183a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 41955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 420af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 421af57ed9fSAtsushi Murai u_short *sp; 422af57ed9fSAtsushi Murai 423af57ed9fSAtsushi Murai ptop += 20; 424af57ed9fSAtsushi Murai sp = (u_short *) ptop; 42555a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 42655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 42755a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 42855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 42955a8cdeaSBrian Somers } 430af57ed9fSAtsushi Murai } 431af57ed9fSAtsushi Murai } 432af57ed9fSAtsushi Murai break; 433af57ed9fSAtsushi Murai } 43476bd0c0aSDoug Rabson 435cad7e742SBrian Somers if (FilterCheck(pip, filter)) { 436710e9c29SBrian Somers if (logit) 437dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 4385ca5389aSBrian Somers #ifdef notdef 439944f7098SBrian Somers if (direction == 0) 440944f7098SBrian Somers IcmpError(pip, pri); 4415ca5389aSBrian Somers #endif 442af57ed9fSAtsushi Murai return (-1); 443af57ed9fSAtsushi Murai } else { 4445ca5389aSBrian Somers /* Check Keep Alive filter */ 445e43ebac1SBrian Somers if (logit) { 446cad7e742SBrian Somers if (FilterCheck(pip, &bundle->filter.alive)) 447dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 4481e991daaSBrian Somers else 449dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 45053c9f6c0SAtsushi Murai } 451af57ed9fSAtsushi Murai return (pri); 452af57ed9fSAtsushi Murai } 453af57ed9fSAtsushi Murai } 454af57ed9fSAtsushi Murai 4555d9e6103SBrian Somers struct mbuf * 4565d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 4577a6f8720SBrian Somers { 458af57ed9fSAtsushi Murai int nb, nw; 459b6e82f33SBrian Somers struct tun_data tun; 4605d9e6103SBrian Somers struct ip *pip; 4615d9e6103SBrian Somers 4625d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 4635d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 4645d9e6103SBrian Somers mbuf_Free(bp); 4655d9e6103SBrian Somers return NULL; 4665d9e6103SBrian Somers } 467af57ed9fSAtsushi Murai 468411675baSBrian Somers mbuf_SetType(bp, MB_IPIN); 4696a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 4705d9e6103SBrian Somers nb = mbuf_Length(bp); 47176d98538SBrian Somers if (nb > sizeof tun.data) { 47276d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 47376d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 47476d98538SBrian Somers mbuf_Free(bp); 47576d98538SBrian Somers return NULL; 47676d98538SBrian Somers } 4775d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 478af57ed9fSAtsushi Murai 4795d9e6103SBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 4805d9e6103SBrian Somers return NULL; 4816db75539SBrian Somers 4825d9e6103SBrian Somers pip = (struct ip *)tun.data; 483cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 4841e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4851e991daaSBrian Somers 4865828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4871e991daaSBrian Somers 48870ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 489faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 490c4c4aaacSBrian Somers if (nw != nb) { 49157fd05c4SBrian Somers if (nw == -1) 49276d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 49376d98538SBrian Somers l->name, nb, strerror(errno)); 49457fd05c4SBrian Somers else 49576d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 4966db75539SBrian Somers } 4975d9e6103SBrian Somers 4985d9e6103SBrian Somers return NULL; 499af57ed9fSAtsushi Murai } 500af57ed9fSAtsushi Murai 501af57ed9fSAtsushi Murai void 5025a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 503af57ed9fSAtsushi Murai { 504af57ed9fSAtsushi Murai struct mbuf *bp; 505af57ed9fSAtsushi Murai 5065a72b6edSBrian Somers if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 5075a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 5085a72b6edSBrian Somers else { 5095d9e6103SBrian Somers /* 5105d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 5115d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 5125d9e6103SBrian Somers * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and 5135d9e6103SBrian Somers * appending in hdlc_LayerPush(). 5145d9e6103SBrian Somers */ 515411675baSBrian Somers bp = mbuf_Alloc(count + 6, MB_IPOUT); 5165d9e6103SBrian Somers bp->offset += 4; 5175d9e6103SBrian Somers bp->cnt -= 6; 51875240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 5195a72b6edSBrian Somers mbuf_Enqueue(&ipcp->Queue[pri], bp); 5205a72b6edSBrian Somers } 521af57ed9fSAtsushi Murai } 522af57ed9fSAtsushi Murai 5236f8e9f0aSBrian Somers void 5245a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 5256f8e9f0aSBrian Somers { 5266f8e9f0aSBrian Somers struct mqueue *queue; 5276f8e9f0aSBrian Somers 5285a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 5296f8e9f0aSBrian Somers while (queue->top) 5306f8e9f0aSBrian Somers mbuf_Free(mbuf_Dequeue(queue)); 5316f8e9f0aSBrian Somers } 5326f8e9f0aSBrian Somers 53384b8a6ebSAtsushi Murai int 5345a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 53584b8a6ebSAtsushi Murai { 53684b8a6ebSAtsushi Murai struct mqueue *queue; 537f4768038SBrian Somers int result = 0; 538944f7098SBrian Somers 5395a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 540f4768038SBrian Somers result += queue->qlen; 54184b8a6ebSAtsushi Murai 542f4768038SBrian Somers return result; 5431ae349f5Scvs2svn } 5441ae349f5Scvs2svn 5453b0f8d2eSBrian Somers int 5465d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 547af57ed9fSAtsushi Murai { 5485a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 549af57ed9fSAtsushi Murai struct mqueue *queue; 550af57ed9fSAtsushi Murai struct mbuf *bp; 5515d9e6103SBrian Somers struct ip *pip; 552274e766cSBrian Somers int cnt; 553af57ed9fSAtsushi Murai 5545a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 5553b0f8d2eSBrian Somers return 0; 5561e991daaSBrian Somers 5575a72b6edSBrian Somers for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 558af57ed9fSAtsushi Murai if (queue->top) { 559aad80d9fSBrian Somers bp = mbuf_Contiguous(mbuf_Dequeue(queue)); 560dd7e2610SBrian Somers cnt = mbuf_Length(bp); 5615d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 562cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 563ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 5645d9e6103SBrian Somers link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP); 5655a72b6edSBrian Somers ipcp_AddOutOctets(ipcp, cnt); 5663b0f8d2eSBrian Somers return 1; 567af57ed9fSAtsushi Murai } 5681e991daaSBrian Somers 5693b0f8d2eSBrian Somers return 0; 570af57ed9fSAtsushi Murai } 571