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 * 2097d92980SPeter Wemm * $FreeBSD$ 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 <string.h> 425d9e6103SBrian Somers #include <termios.h> 4375240ed1SBrian Somers #include <unistd.h> 4475240ed1SBrian Somers 455d9e6103SBrian Somers #include "layer.h" 465d9e6103SBrian Somers #include "proto.h" 47927145beSBrian Somers #include "mbuf.h" 48927145beSBrian Somers #include "log.h" 4975240ed1SBrian Somers #include "defs.h" 5075240ed1SBrian Somers #include "timer.h" 5175240ed1SBrian Somers #include "fsm.h" 52879ed6faSBrian Somers #include "lqr.h" 5375240ed1SBrian Somers #include "hdlc.h" 545828db6dSBrian Somers #include "throughput.h" 555828db6dSBrian Somers #include "iplist.h" 56eaa4df37SBrian Somers #include "slcompress.h" 5775240ed1SBrian Somers #include "ipcp.h" 581ae349f5Scvs2svn #include "filter.h" 592f786681SBrian Somers #include "descriptor.h" 6075240ed1SBrian Somers #include "lcp.h" 613b0f8d2eSBrian Somers #include "ccp.h" 623b0f8d2eSBrian Somers #include "link.h" 633b0f8d2eSBrian Somers #include "mp.h" 64972a1bcfSBrian Somers #ifndef NORADIUS 65972a1bcfSBrian Somers #include "radius.h" 66972a1bcfSBrian Somers #endif 677a6f8720SBrian Somers #include "bundle.h" 686a6b4bbbSBrian Somers #include "tun.h" 6975240ed1SBrian Somers #include "ip.h" 70af57ed9fSAtsushi Murai 71b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 72af57ed9fSAtsushi Murai 73cad7e742SBrian Somers static __inline int 74944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 75af57ed9fSAtsushi Murai { 76af57ed9fSAtsushi Murai switch (op) { 77af57ed9fSAtsushi Murai case OP_EQ: 78af57ed9fSAtsushi Murai return (pport == rport); 79af57ed9fSAtsushi Murai case OP_GT: 80af57ed9fSAtsushi Murai return (pport > rport); 81af57ed9fSAtsushi Murai case OP_LT: 82af57ed9fSAtsushi Murai return (pport < rport); 83af57ed9fSAtsushi Murai default: 84af57ed9fSAtsushi Murai return (0); 85af57ed9fSAtsushi Murai } 86af57ed9fSAtsushi Murai } 87af57ed9fSAtsushi Murai 88af57ed9fSAtsushi Murai /* 895d9e6103SBrian Somers * Check a packet against a defined filter 90cad7e742SBrian Somers * Returns 0 to accept the packet, non-zero to drop the packet 91cad7e742SBrian Somers * 92cad7e742SBrian Somers * If filtering is enabled, the initial fragment of a datagram must 93cad7e742SBrian Somers * contain the complete protocol header, and subsequent fragments 94cad7e742SBrian Somers * must not attempt to over-write it. 95af57ed9fSAtsushi Murai */ 96af57ed9fSAtsushi Murai static int 97cad7e742SBrian Somers FilterCheck(const struct ip *pip, const struct filter *filter) 98af57ed9fSAtsushi Murai { 99cad7e742SBrian Somers int gotinfo; /* true if IP payload decoded */ 100cad7e742SBrian Somers int cproto; /* P_* protocol type if (gotinfo) */ 101cad7e742SBrian Somers int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 102cad7e742SBrian Somers u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 103cad7e742SBrian Somers int n; /* filter rule to process */ 104cad7e742SBrian Somers int len; /* bytes used in dbuff */ 105cad7e742SBrian Somers int didname; /* true if filter header printed */ 106cad7e742SBrian Somers int match; /* true if condition matched */ 107cad7e742SBrian Somers const struct filterent *fp = filter->rule; 1088390b576SBrian Somers char dbuff[100]; 109af57ed9fSAtsushi Murai 110cad7e742SBrian Somers if (fp->f_action == A_NONE) 111cad7e742SBrian Somers return (0); /* No rule is given. Permit this packet */ 112cad7e742SBrian Somers 113cad7e742SBrian Somers /* Deny any packet fragment that tries to over-write the header. 114cad7e742SBrian Somers * Since we no longer have the real header available, punt on the 115cad7e742SBrian Somers * largest normal header - 20 bytes for TCP without options, rounded 116cad7e742SBrian Somers * up to the next possible fragment boundary. Since the smallest 117cad7e742SBrian Somers * `legal' MTU is 576, and the smallest recommended MTU is 296, any 118cad7e742SBrian Somers * fragmentation within this range is dubious at best */ 119cad7e742SBrian Somers len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 120cad7e742SBrian Somers if (len > 0) { /* Not first fragment within datagram */ 121cad7e742SBrian Somers if (len < (24 >> 3)) /* don't allow fragment to over-write header */ 122cad7e742SBrian Somers return (1); 123cad7e742SBrian Somers /* permit fragments on in and out filter */ 124cad7e742SBrian Somers return (filter->fragok); 125cad7e742SBrian Somers } 126cad7e742SBrian Somers 12763f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 128af57ed9fSAtsushi Murai sport = dport = 0; 129cad7e742SBrian Somers for (n = 0; n < MAXFILTERS; ) { 130cad7e742SBrian Somers if (fp->f_action == A_NONE) { 131cad7e742SBrian Somers n++; 132cad7e742SBrian Somers fp++; 133cad7e742SBrian Somers continue; 134cad7e742SBrian Somers } 1355ca5389aSBrian Somers 136cad7e742SBrian Somers if (!didname) { 137dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1388390b576SBrian Somers didname = 1; 139cad7e742SBrian Somers } 1408390b576SBrian Somers 141cad7e742SBrian Somers match = 0; 142cad7e742SBrian Somers if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 143cad7e742SBrian Somers fp->f_src.mask.s_addr) && 144cad7e742SBrian Somers !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 145cad7e742SBrian Somers fp->f_dst.mask.s_addr)) { 146cad7e742SBrian Somers if (fp->f_proto != P_NONE) { 147af57ed9fSAtsushi Murai if (!gotinfo) { 148cad7e742SBrian Somers const char *ptop = (const char *) pip + (pip->ip_hl << 2); 149cad7e742SBrian Somers const struct tcphdr *th; 150cad7e742SBrian Somers const struct udphdr *uh; 151cad7e742SBrian Somers const struct icmp *ih; 152cad7e742SBrian Somers int datalen; /* IP datagram length */ 153af57ed9fSAtsushi Murai 154cad7e742SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 155af57ed9fSAtsushi Murai switch (pip->ip_p) { 156af57ed9fSAtsushi Murai case IPPROTO_ICMP: 157944f7098SBrian Somers cproto = P_ICMP; 158cad7e742SBrian Somers if (datalen < 8) /* ICMP must be at least 8 octets */ 159cad7e742SBrian Somers return (1); 160cad7e742SBrian Somers ih = (const struct icmp *) ptop; 161944f7098SBrian Somers sport = ih->icmp_type; 16263f98b41SBrian Somers estab = syn = finrst = -1; 163dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1648390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 165af57ed9fSAtsushi Murai break; 166eee772ecSBrian Somers case IPPROTO_IGMP: 1671f9e5fe5SBrian Somers cproto = P_IGMP; 168cad7e742SBrian Somers if (datalen < 8) /* IGMP uses 8-octet messages */ 169cad7e742SBrian Somers return (1); 1701f9e5fe5SBrian Somers estab = syn = finrst = -1; 1711f9e5fe5SBrian Somers sport = ntohs(0); 1721f9e5fe5SBrian Somers break; 17362e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 1742faae814SBrian Somers case IPPROTO_OSPFIGP: 1752faae814SBrian Somers cproto = P_OSPF; 1762faae814SBrian Somers if (datalen < 8) /* IGMP uses 8-octet messages */ 1772faae814SBrian Somers return (1); 1782faae814SBrian Somers estab = syn = finrst = -1; 1792faae814SBrian Somers sport = ntohs(0); 1802faae814SBrian Somers break; 18162e85934SBrian Somers #endif 1821f9e5fe5SBrian Somers case IPPROTO_UDP: 183eee772ecSBrian Somers case IPPROTO_IPIP: 184944f7098SBrian Somers cproto = P_UDP; 185cad7e742SBrian Somers if (datalen < 8) /* UDP header is 8 octets */ 186cad7e742SBrian Somers return (1); 187cad7e742SBrian Somers uh = (const struct udphdr *) ptop; 188944f7098SBrian Somers sport = ntohs(uh->uh_sport); 189944f7098SBrian Somers dport = ntohs(uh->uh_dport); 19063f98b41SBrian Somers estab = syn = finrst = -1; 191dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1928390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1938390b576SBrian Somers sport, dport); 194af57ed9fSAtsushi Murai break; 195af57ed9fSAtsushi Murai case IPPROTO_TCP: 196944f7098SBrian Somers cproto = P_TCP; 197cad7e742SBrian Somers th = (const struct tcphdr *) ptop; 198cad7e742SBrian Somers /* TCP headers are variable length. The following code 199cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 200cad7e742SBrian Somers * the datagram is too short 201cad7e742SBrian Somers */ 202cad7e742SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) 203cad7e742SBrian Somers return (1); 204944f7098SBrian Somers sport = ntohs(th->th_sport); 205944f7098SBrian Somers dport = ntohs(th->th_dport); 206af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 20763f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 20863f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 2092b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 2102b81c773SBrian Somers if (!estab) 2118390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 2128390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 213927145beSBrian Somers th->th_flags, sport, dport); 2142b81c773SBrian Somers else 2152b81c773SBrian Somers *dbuff = '\0'; 2162b81c773SBrian Somers } 217af57ed9fSAtsushi Murai break; 218af57ed9fSAtsushi Murai default: 219cad7e742SBrian Somers return (1); /* We'll block unknown type of packet */ 220af57ed9fSAtsushi Murai } 221cad7e742SBrian Somers 222dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 2238390b576SBrian Somers if (estab != -1) { 2248390b576SBrian Somers len = strlen(dbuff); 22563f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 22663f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 22763f98b41SBrian Somers estab, syn, finrst); 228af57ed9fSAtsushi Murai } 229dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 2308390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 2318390b576SBrian Somers } 2328390b576SBrian Somers gotinfo = 1; 2338390b576SBrian Somers } 234dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 235cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 2368390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 237cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 2388390b576SBrian Somers len = strlen(dbuff); 2398390b576SBrian Somers } else 2408390b576SBrian Somers len = 0; 241cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 2428390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 243cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 244cad7e742SBrian Somers fp->f_dstport); 2458390b576SBrian Somers } else if (!len) 2468390b576SBrian Somers *dbuff = '\0'; 2478390b576SBrian Somers 248dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 2498390b576SBrian Somers "check against proto %s%s, action = %s\n", 250cad7e742SBrian Somers n, filter_Proto2Nam(fp->f_proto), 251cad7e742SBrian Somers dbuff, filter_Action2Nam(fp->f_action)); 2528390b576SBrian Somers } 253927145beSBrian Somers 254cad7e742SBrian Somers if (cproto == fp->f_proto) { 255cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 256cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 257cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 258cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 259cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 260cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 261cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 262cad7e742SBrian Somers match = 1; 263af57ed9fSAtsushi Murai } 264af57ed9fSAtsushi Murai } 265af57ed9fSAtsushi Murai } else { 266cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 267dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 268cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 269cad7e742SBrian Somers match = 1; 270af57ed9fSAtsushi Murai } 2718390b576SBrian Somers } else 272dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 273cad7e742SBrian Somers 274cad7e742SBrian Somers if (match != fp->f_invert) { 275cad7e742SBrian Somers /* Take specified action */ 276cad7e742SBrian Somers if (fp->f_action < A_NONE) 277cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 278cad7e742SBrian Somers else 279cad7e742SBrian Somers return (fp->f_action != A_PERMIT); 280cad7e742SBrian Somers } else { 281cad7e742SBrian Somers n++; 282af57ed9fSAtsushi Murai fp++; 283af57ed9fSAtsushi Murai } 284af57ed9fSAtsushi Murai } 285cad7e742SBrian Somers return (1); /* No rule is mached. Deny this packet */ 286af57ed9fSAtsushi Murai } 287af57ed9fSAtsushi Murai 2885ca5389aSBrian Somers #ifdef notdef 289af57ed9fSAtsushi Murai static void 290944f7098SBrian Somers IcmpError(struct ip *pip, int code) 291af57ed9fSAtsushi Murai { 292af57ed9fSAtsushi Murai struct mbuf *bp; 293af57ed9fSAtsushi Murai 294af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 295dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 29675240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 297dd7e2610SBrian Somers vj_SendFrame(bp); 2985828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2991ae349f5Scvs2svn } 300af57ed9fSAtsushi Murai } 301af57ed9fSAtsushi Murai #endif 302af57ed9fSAtsushi Murai 303af57ed9fSAtsushi Murai /* 304af57ed9fSAtsushi Murai * For debugging aid. 305af57ed9fSAtsushi Murai */ 306af57ed9fSAtsushi Murai int 3075ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 308af57ed9fSAtsushi Murai { 309af57ed9fSAtsushi Murai struct ip *pip; 310af57ed9fSAtsushi Murai struct tcphdr *th; 311af57ed9fSAtsushi Murai struct udphdr *uh; 312af57ed9fSAtsushi Murai struct icmp *icmph; 313af57ed9fSAtsushi Murai char *ptop; 314af57ed9fSAtsushi Murai int mask, len, n; 315442f8495SBrian Somers int pri = 0; 31655a8cdeaSBrian Somers int logit, loglen; 317d93d3a9cSBrian Somers char logbuf[200]; 318af57ed9fSAtsushi Murai 319dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 32055a8cdeaSBrian Somers loglen = 0; 321af57ed9fSAtsushi Murai 322af57ed9fSAtsushi Murai pip = (struct ip *) cp; 323af57ed9fSAtsushi Murai 32455a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 3255ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 32655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 32755a8cdeaSBrian Somers } 328af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 329af57ed9fSAtsushi Murai 330af57ed9fSAtsushi Murai switch (pip->ip_p) { 331af57ed9fSAtsushi Murai case IPPROTO_ICMP: 33255a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 333af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 33455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33555a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 33655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33855a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 33955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 340af57ed9fSAtsushi Murai } 341af57ed9fSAtsushi Murai break; 342da477886SBrian Somers 343af57ed9fSAtsushi Murai case IPPROTO_UDP: 344af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 345da477886SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY) 346da477886SBrian Somers pri++; 347da477886SBrian Somers 348da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 349da477886SBrian Somers ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 350da477886SBrian Somers ntohs(uh->uh_dport))) 351da477886SBrian Somers pri++; 352da477886SBrian Somers 353da477886SBrian Somers if (logit && loglen < sizeof logbuf) { 35455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35555a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 35655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 35755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35855a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 35955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 360af57ed9fSAtsushi Murai } 361af57ed9fSAtsushi Murai break; 362da477886SBrian Somers 36362e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 3642faae814SBrian Somers case IPPROTO_OSPFIGP: 3652faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 3662faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3672faae814SBrian Somers "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 3682faae814SBrian Somers loglen += strlen(logbuf + loglen); 3692faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3702faae814SBrian Somers "%s", inet_ntoa(pip->ip_dst)); 3712faae814SBrian Somers loglen += strlen(logbuf + loglen); 3722faae814SBrian Somers } 3732faae814SBrian Somers break; 37462e85934SBrian Somers #endif 375da477886SBrian Somers 376eee772ecSBrian Somers case IPPROTO_IPIP: 377eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 378eee772ecSBrian Somers uh = (struct udphdr *) ptop; 379eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 380eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 381eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 382eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 383eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 384eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 385eee772ecSBrian Somers } 386eee772ecSBrian Somers break; 387da477886SBrian Somers 388eee772ecSBrian Somers case IPPROTO_IGMP: 389eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 390eee772ecSBrian Somers uh = (struct udphdr *) ptop; 391eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 392eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 393eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 394eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 395eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 396eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 397eee772ecSBrian Somers } 398eee772ecSBrian Somers break; 399da477886SBrian Somers 400af57ed9fSAtsushi Murai case IPPROTO_TCP: 401af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 402af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 403442f8495SBrian Somers pri++; 404da477886SBrian Somers 405da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 406da477886SBrian Somers ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 407442f8495SBrian Somers ntohs(th->th_dport))) 408442f8495SBrian Somers pri++; 409442f8495SBrian Somers 41055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 411af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 41255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 41355a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 41455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 41555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 41655a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 41755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 418af57ed9fSAtsushi Murai n = 0; 419af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 42055a8cdeaSBrian Somers if (th->th_flags & mask) { 42155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 42255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 42355a8cdeaSBrian Somers } 424af57ed9fSAtsushi Murai n++; 425af57ed9fSAtsushi Murai } 42655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 4273a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 4283a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 42955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 430af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 431af57ed9fSAtsushi Murai u_short *sp; 432af57ed9fSAtsushi Murai 433af57ed9fSAtsushi Murai ptop += 20; 434af57ed9fSAtsushi Murai sp = (u_short *) ptop; 43555a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 43655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 43755a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 43855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 43955a8cdeaSBrian Somers } 440af57ed9fSAtsushi Murai } 441af57ed9fSAtsushi Murai } 442af57ed9fSAtsushi Murai break; 443af57ed9fSAtsushi Murai } 44476bd0c0aSDoug Rabson 445cad7e742SBrian Somers if (FilterCheck(pip, filter)) { 446710e9c29SBrian Somers if (logit) 447dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 4485ca5389aSBrian Somers #ifdef notdef 449944f7098SBrian Somers if (direction == 0) 450944f7098SBrian Somers IcmpError(pip, pri); 4515ca5389aSBrian Somers #endif 452af57ed9fSAtsushi Murai return (-1); 453af57ed9fSAtsushi Murai } else { 4545ca5389aSBrian Somers /* Check Keep Alive filter */ 455e43ebac1SBrian Somers if (logit) { 456cad7e742SBrian Somers if (FilterCheck(pip, &bundle->filter.alive)) 457dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 4581e991daaSBrian Somers else 459dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 46053c9f6c0SAtsushi Murai } 461af57ed9fSAtsushi Murai return (pri); 462af57ed9fSAtsushi Murai } 463af57ed9fSAtsushi Murai } 464af57ed9fSAtsushi Murai 4655d9e6103SBrian Somers struct mbuf * 4665d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 4677a6f8720SBrian Somers { 468af57ed9fSAtsushi Murai int nb, nw; 469b6e82f33SBrian Somers struct tun_data tun; 4705d9e6103SBrian Somers struct ip *pip; 4715d9e6103SBrian Somers 4725d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 4735d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 4745d9e6103SBrian Somers mbuf_Free(bp); 4755d9e6103SBrian Somers return NULL; 4765d9e6103SBrian Somers } 477af57ed9fSAtsushi Murai 478411675baSBrian Somers mbuf_SetType(bp, MB_IPIN); 4796a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 4805d9e6103SBrian Somers nb = mbuf_Length(bp); 48176d98538SBrian Somers if (nb > sizeof tun.data) { 48276d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 48376d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 48476d98538SBrian Somers mbuf_Free(bp); 48576d98538SBrian Somers return NULL; 48676d98538SBrian Somers } 4875d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 488af57ed9fSAtsushi Murai 4895d9e6103SBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 4905d9e6103SBrian Somers return NULL; 4916db75539SBrian Somers 4925d9e6103SBrian Somers pip = (struct ip *)tun.data; 493cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 4941e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4951e991daaSBrian Somers 4965828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4971e991daaSBrian Somers 49870ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 499faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 500c4c4aaacSBrian Somers if (nw != nb) { 50157fd05c4SBrian Somers if (nw == -1) 50276d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 50376d98538SBrian Somers l->name, nb, strerror(errno)); 50457fd05c4SBrian Somers else 50576d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 5066db75539SBrian Somers } 5075d9e6103SBrian Somers 5085d9e6103SBrian Somers return NULL; 509af57ed9fSAtsushi Murai } 510af57ed9fSAtsushi Murai 511af57ed9fSAtsushi Murai void 5125a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 513af57ed9fSAtsushi Murai { 514af57ed9fSAtsushi Murai struct mbuf *bp; 515af57ed9fSAtsushi Murai 516442f8495SBrian Somers if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 5175a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 5185a72b6edSBrian Somers else { 5195d9e6103SBrian Somers /* 5205d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 5215d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 5225d9e6103SBrian Somers * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and 5235d9e6103SBrian Somers * appending in hdlc_LayerPush(). 5245d9e6103SBrian Somers */ 525411675baSBrian Somers bp = mbuf_Alloc(count + 6, MB_IPOUT); 5265d9e6103SBrian Somers bp->offset += 4; 5275d9e6103SBrian Somers bp->cnt -= 6; 52875240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 529442f8495SBrian Somers mbuf_Enqueue(ipcp->Queue + pri, bp); 5305a72b6edSBrian Somers } 531af57ed9fSAtsushi Murai } 532af57ed9fSAtsushi Murai 5336f8e9f0aSBrian Somers void 5345a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 5356f8e9f0aSBrian Somers { 5366f8e9f0aSBrian Somers struct mqueue *queue; 5376f8e9f0aSBrian Somers 538442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 5396f8e9f0aSBrian Somers while (queue->top) 5406f8e9f0aSBrian Somers mbuf_Free(mbuf_Dequeue(queue)); 5416f8e9f0aSBrian Somers } 5426f8e9f0aSBrian Somers 54384b8a6ebSAtsushi Murai int 5445a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 54584b8a6ebSAtsushi Murai { 54684b8a6ebSAtsushi Murai struct mqueue *queue; 547f4768038SBrian Somers int result = 0; 548944f7098SBrian Somers 549442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 550f4768038SBrian Somers result += queue->qlen; 55184b8a6ebSAtsushi Murai 552f4768038SBrian Somers return result; 5531ae349f5Scvs2svn } 5541ae349f5Scvs2svn 5553b0f8d2eSBrian Somers int 5565d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 557af57ed9fSAtsushi Murai { 5585a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 559af57ed9fSAtsushi Murai struct mqueue *queue; 560af57ed9fSAtsushi Murai struct mbuf *bp; 5615d9e6103SBrian Somers struct ip *pip; 562274e766cSBrian Somers int cnt; 563af57ed9fSAtsushi Murai 5645a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 5653b0f8d2eSBrian Somers return 0; 5661e991daaSBrian Somers 567442f8495SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 568442f8495SBrian Somers do { 569af57ed9fSAtsushi Murai if (queue->top) { 570aad80d9fSBrian Somers bp = mbuf_Contiguous(mbuf_Dequeue(queue)); 571dd7e2610SBrian Somers cnt = mbuf_Length(bp); 5725d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 573cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 574ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 575442f8495SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 5765a72b6edSBrian Somers ipcp_AddOutOctets(ipcp, cnt); 5773b0f8d2eSBrian Somers return 1; 578af57ed9fSAtsushi Murai } 579442f8495SBrian Somers } while (queue-- != ipcp->Queue); 5801e991daaSBrian Somers 5813b0f8d2eSBrian Somers return 0; 582af57ed9fSAtsushi Murai } 583