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 */ 1244d9d17feSBrian 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; 17328149effSBrian Somers #ifdef IPPROTO_GRE 17428149effSBrian Somers case IPPROTO_GRE: 17528149effSBrian Somers cproto = P_GRE; 17628149effSBrian Somers if (datalen < 2) /* GRE uses 2-octet+ messages */ 17728149effSBrian Somers return (1); 17828149effSBrian Somers estab = syn = finrst = -1; 17928149effSBrian Somers sport = ntohs(0); 18028149effSBrian Somers break; 18128149effSBrian Somers #endif 18262e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 1832faae814SBrian Somers case IPPROTO_OSPFIGP: 1842faae814SBrian Somers cproto = P_OSPF; 1852faae814SBrian Somers if (datalen < 8) /* IGMP uses 8-octet messages */ 1862faae814SBrian Somers return (1); 1872faae814SBrian Somers estab = syn = finrst = -1; 1882faae814SBrian Somers sport = ntohs(0); 1892faae814SBrian Somers break; 19062e85934SBrian Somers #endif 1911f9e5fe5SBrian Somers case IPPROTO_UDP: 192eee772ecSBrian Somers case IPPROTO_IPIP: 193944f7098SBrian Somers cproto = P_UDP; 194cad7e742SBrian Somers if (datalen < 8) /* UDP header is 8 octets */ 195cad7e742SBrian Somers return (1); 196cad7e742SBrian Somers uh = (const struct udphdr *) ptop; 197944f7098SBrian Somers sport = ntohs(uh->uh_sport); 198944f7098SBrian Somers dport = ntohs(uh->uh_dport); 19963f98b41SBrian Somers estab = syn = finrst = -1; 200dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 2018390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 2028390b576SBrian Somers sport, dport); 203af57ed9fSAtsushi Murai break; 204af57ed9fSAtsushi Murai case IPPROTO_TCP: 205944f7098SBrian Somers cproto = P_TCP; 206cad7e742SBrian Somers th = (const struct tcphdr *) ptop; 207cad7e742SBrian Somers /* TCP headers are variable length. The following code 208cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 209cad7e742SBrian Somers * the datagram is too short 210cad7e742SBrian Somers */ 211cad7e742SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) 212cad7e742SBrian Somers return (1); 213944f7098SBrian Somers sport = ntohs(th->th_sport); 214944f7098SBrian Somers dport = ntohs(th->th_dport); 215af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 21663f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 21763f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 2182b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 2192b81c773SBrian Somers if (!estab) 2208390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 2218390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 222927145beSBrian Somers th->th_flags, sport, dport); 2232b81c773SBrian Somers else 2242b81c773SBrian Somers *dbuff = '\0'; 2252b81c773SBrian Somers } 226af57ed9fSAtsushi Murai break; 227af57ed9fSAtsushi Murai default: 228cad7e742SBrian Somers return (1); /* We'll block unknown type of packet */ 229af57ed9fSAtsushi Murai } 230cad7e742SBrian Somers 231dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 2328390b576SBrian Somers if (estab != -1) { 2338390b576SBrian Somers len = strlen(dbuff); 23463f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 23563f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 23663f98b41SBrian Somers estab, syn, finrst); 237af57ed9fSAtsushi Murai } 238dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 2398390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 2408390b576SBrian Somers } 2418390b576SBrian Somers gotinfo = 1; 2428390b576SBrian Somers } 243dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 244cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 2458390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 246cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 2478390b576SBrian Somers len = strlen(dbuff); 2488390b576SBrian Somers } else 2498390b576SBrian Somers len = 0; 250cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 2518390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 252cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 253cad7e742SBrian Somers fp->f_dstport); 2548390b576SBrian Somers } else if (!len) 2558390b576SBrian Somers *dbuff = '\0'; 2568390b576SBrian Somers 257dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 2588390b576SBrian Somers "check against proto %s%s, action = %s\n", 259cad7e742SBrian Somers n, filter_Proto2Nam(fp->f_proto), 260cad7e742SBrian Somers dbuff, filter_Action2Nam(fp->f_action)); 2618390b576SBrian Somers } 262927145beSBrian Somers 263cad7e742SBrian Somers if (cproto == fp->f_proto) { 264cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 265cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 266cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 267cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 268cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 269cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 270cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 271cad7e742SBrian Somers match = 1; 272af57ed9fSAtsushi Murai } 273af57ed9fSAtsushi Murai } 274af57ed9fSAtsushi Murai } else { 275cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 276dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 277cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 278cad7e742SBrian Somers match = 1; 279af57ed9fSAtsushi Murai } 2808390b576SBrian Somers } else 281dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 282cad7e742SBrian Somers 283cad7e742SBrian Somers if (match != fp->f_invert) { 284cad7e742SBrian Somers /* Take specified action */ 285cad7e742SBrian Somers if (fp->f_action < A_NONE) 286cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 287cad7e742SBrian Somers else 288cad7e742SBrian Somers return (fp->f_action != A_PERMIT); 289cad7e742SBrian Somers } else { 290cad7e742SBrian Somers n++; 291af57ed9fSAtsushi Murai fp++; 292af57ed9fSAtsushi Murai } 293af57ed9fSAtsushi Murai } 294cad7e742SBrian Somers return (1); /* No rule is mached. Deny this packet */ 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai 2975ca5389aSBrian Somers #ifdef notdef 298af57ed9fSAtsushi Murai static void 299944f7098SBrian Somers IcmpError(struct ip *pip, int code) 300af57ed9fSAtsushi Murai { 301af57ed9fSAtsushi Murai struct mbuf *bp; 302af57ed9fSAtsushi Murai 303af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 30426af0ae9SBrian Somers bp = m_get(m_len, MB_IPIN); 30526af0ae9SBrian Somers memcpy(MBUF_CTOP(bp), ptr, m_len); 306dd7e2610SBrian Somers vj_SendFrame(bp); 30726af0ae9SBrian Somers ipcp_AddOutOctets(m_len); 3081ae349f5Scvs2svn } 309af57ed9fSAtsushi Murai } 310af57ed9fSAtsushi Murai #endif 311af57ed9fSAtsushi Murai 312af57ed9fSAtsushi Murai /* 313af57ed9fSAtsushi Murai * For debugging aid. 314af57ed9fSAtsushi Murai */ 315af57ed9fSAtsushi Murai int 3165ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 317af57ed9fSAtsushi Murai { 318af57ed9fSAtsushi Murai struct ip *pip; 319af57ed9fSAtsushi Murai struct tcphdr *th; 320af57ed9fSAtsushi Murai struct udphdr *uh; 321af57ed9fSAtsushi Murai struct icmp *icmph; 322af57ed9fSAtsushi Murai char *ptop; 323af57ed9fSAtsushi Murai int mask, len, n; 324442f8495SBrian Somers int pri = 0; 32555a8cdeaSBrian Somers int logit, loglen; 326d93d3a9cSBrian Somers char logbuf[200]; 327af57ed9fSAtsushi Murai 328dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 32955a8cdeaSBrian Somers loglen = 0; 330af57ed9fSAtsushi Murai 331af57ed9fSAtsushi Murai pip = (struct ip *) cp; 332af57ed9fSAtsushi Murai 33355a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 3345ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 33555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33655a8cdeaSBrian Somers } 337af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 338af57ed9fSAtsushi Murai 339af57ed9fSAtsushi Murai switch (pip->ip_p) { 340af57ed9fSAtsushi Murai case IPPROTO_ICMP: 34155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 342af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 34355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34455a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 34555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 34655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34755a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 34855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 349af57ed9fSAtsushi Murai } 350af57ed9fSAtsushi Murai break; 351da477886SBrian Somers 352af57ed9fSAtsushi Murai case IPPROTO_UDP: 353af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 354da477886SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY) 355da477886SBrian Somers pri++; 356da477886SBrian Somers 357da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 358da477886SBrian Somers ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 359da477886SBrian Somers ntohs(uh->uh_dport))) 360da477886SBrian Somers pri++; 361da477886SBrian Somers 362da477886SBrian Somers if (logit && loglen < sizeof logbuf) { 36355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 36455a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 36555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 36655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 36755a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 36855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 369af57ed9fSAtsushi Murai } 370af57ed9fSAtsushi Murai break; 371da477886SBrian Somers 37228149effSBrian Somers #ifdef IPPROTO_GRE 37328149effSBrian Somers case IPPROTO_GRE: 37428149effSBrian Somers if (logit && loglen < sizeof logbuf) { 37528149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 37628149effSBrian Somers "GRE: %s ---> ", inet_ntoa(pip->ip_src)); 37728149effSBrian Somers loglen += strlen(logbuf + loglen); 37828149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 37928149effSBrian Somers "%s", inet_ntoa(pip->ip_dst)); 38028149effSBrian Somers loglen += strlen(logbuf + loglen); 38128149effSBrian Somers } 38228149effSBrian Somers break; 38328149effSBrian Somers #endif 38428149effSBrian Somers 38562e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 3862faae814SBrian Somers case IPPROTO_OSPFIGP: 3872faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 3882faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3892faae814SBrian Somers "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 3902faae814SBrian Somers loglen += strlen(logbuf + loglen); 3912faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3922faae814SBrian Somers "%s", inet_ntoa(pip->ip_dst)); 3932faae814SBrian Somers loglen += strlen(logbuf + loglen); 3942faae814SBrian Somers } 3952faae814SBrian Somers break; 39662e85934SBrian Somers #endif 397da477886SBrian Somers 398eee772ecSBrian Somers case IPPROTO_IPIP: 399eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 400eee772ecSBrian Somers uh = (struct udphdr *) ptop; 401eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 402eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 403eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 404eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 405eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 406eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 407eee772ecSBrian Somers } 408eee772ecSBrian Somers break; 409da477886SBrian Somers 410eee772ecSBrian Somers case IPPROTO_IGMP: 411eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 412eee772ecSBrian Somers uh = (struct udphdr *) ptop; 413eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 414eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 415eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 416eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 417eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 418eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 419eee772ecSBrian Somers } 420eee772ecSBrian Somers break; 421da477886SBrian Somers 422af57ed9fSAtsushi Murai case IPPROTO_TCP: 423af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 424af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 425442f8495SBrian Somers pri++; 426da477886SBrian Somers 427da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 428da477886SBrian Somers ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 429442f8495SBrian Somers ntohs(th->th_dport))) 430442f8495SBrian Somers pri++; 431442f8495SBrian Somers 43255a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 433af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 43455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 43555a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 43655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 43755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 43855a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 43955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 440af57ed9fSAtsushi Murai n = 0; 441af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 44255a8cdeaSBrian Somers if (th->th_flags & mask) { 44355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 44455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 44555a8cdeaSBrian Somers } 446af57ed9fSAtsushi Murai n++; 447af57ed9fSAtsushi Murai } 44855a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 4493a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 4503a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 45155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 452af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 453af57ed9fSAtsushi Murai u_short *sp; 454af57ed9fSAtsushi Murai 455af57ed9fSAtsushi Murai ptop += 20; 456af57ed9fSAtsushi Murai sp = (u_short *) ptop; 45755a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 45855a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 45955a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 46055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 46155a8cdeaSBrian Somers } 462af57ed9fSAtsushi Murai } 463af57ed9fSAtsushi Murai } 464af57ed9fSAtsushi Murai break; 465af57ed9fSAtsushi Murai } 46676bd0c0aSDoug Rabson 467cad7e742SBrian Somers if (FilterCheck(pip, filter)) { 468710e9c29SBrian Somers if (logit) 469dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 4705ca5389aSBrian Somers #ifdef notdef 471944f7098SBrian Somers if (direction == 0) 472944f7098SBrian Somers IcmpError(pip, pri); 4735ca5389aSBrian Somers #endif 474af57ed9fSAtsushi Murai return (-1); 475af57ed9fSAtsushi Murai } else { 4765ca5389aSBrian Somers /* Check Keep Alive filter */ 477e43ebac1SBrian Somers if (logit) { 478cad7e742SBrian Somers if (FilterCheck(pip, &bundle->filter.alive)) 479dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 4801e991daaSBrian Somers else 481dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 48253c9f6c0SAtsushi Murai } 483af57ed9fSAtsushi Murai return (pri); 484af57ed9fSAtsushi Murai } 485af57ed9fSAtsushi Murai } 486af57ed9fSAtsushi Murai 4875d9e6103SBrian Somers struct mbuf * 4885d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 4897a6f8720SBrian Somers { 490af57ed9fSAtsushi Murai int nb, nw; 491b6e82f33SBrian Somers struct tun_data tun; 4925d9e6103SBrian Somers struct ip *pip; 4935d9e6103SBrian Somers 4945d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 4955d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 49626af0ae9SBrian Somers m_freem(bp); 4975d9e6103SBrian Somers return NULL; 4985d9e6103SBrian Somers } 499af57ed9fSAtsushi Murai 50026af0ae9SBrian Somers m_settype(bp, MB_IPIN); 5016a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 50226af0ae9SBrian Somers nb = m_length(bp); 50376d98538SBrian Somers if (nb > sizeof tun.data) { 50476d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 50576d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 50626af0ae9SBrian Somers m_freem(bp); 50776d98538SBrian Somers return NULL; 50876d98538SBrian Somers } 5095d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 510af57ed9fSAtsushi Murai 5115d9e6103SBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 5125d9e6103SBrian Somers return NULL; 5136db75539SBrian Somers 5145d9e6103SBrian Somers pip = (struct ip *)tun.data; 515cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 5161e991daaSBrian Somers bundle_StartIdleTimer(bundle); 5171e991daaSBrian Somers 5185828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 5191e991daaSBrian Somers 52070ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 521faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 522c4c4aaacSBrian Somers if (nw != nb) { 52357fd05c4SBrian Somers if (nw == -1) 52476d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 52576d98538SBrian Somers l->name, nb, strerror(errno)); 52657fd05c4SBrian Somers else 52776d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 5286db75539SBrian Somers } 5295d9e6103SBrian Somers 5305d9e6103SBrian Somers return NULL; 531af57ed9fSAtsushi Murai } 532af57ed9fSAtsushi Murai 533af57ed9fSAtsushi Murai void 5345a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 535af57ed9fSAtsushi Murai { 536af57ed9fSAtsushi Murai struct mbuf *bp; 537af57ed9fSAtsushi Murai 538442f8495SBrian Somers if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 5395a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 5405a72b6edSBrian Somers else { 5415d9e6103SBrian Somers /* 5425d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 5435d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 54426af0ae9SBrian Somers * m_prepend() in acf_LayerPush() and proto_LayerPush() and 5455d9e6103SBrian Somers * appending in hdlc_LayerPush(). 5465d9e6103SBrian Somers */ 54726af0ae9SBrian Somers bp = m_get(count + 6, MB_IPOUT); 54826af0ae9SBrian Somers bp->m_offset += 4; 54926af0ae9SBrian Somers bp->m_len -= 6; 55075240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 55126af0ae9SBrian Somers m_enqueue(ipcp->Queue + pri, bp); 5525a72b6edSBrian Somers } 553af57ed9fSAtsushi Murai } 554af57ed9fSAtsushi Murai 5556f8e9f0aSBrian Somers void 5565a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 5576f8e9f0aSBrian Somers { 5586f8e9f0aSBrian Somers struct mqueue *queue; 5596f8e9f0aSBrian Somers 560442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 5616f8e9f0aSBrian Somers while (queue->top) 56226af0ae9SBrian Somers m_freem(m_dequeue(queue)); 5636f8e9f0aSBrian Somers } 5646f8e9f0aSBrian Somers 56526af0ae9SBrian Somers size_t 5665a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 56784b8a6ebSAtsushi Murai { 56884b8a6ebSAtsushi Murai struct mqueue *queue; 56926af0ae9SBrian Somers size_t result; 570944f7098SBrian Somers 57126af0ae9SBrian Somers result = 0; 572442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 57326af0ae9SBrian Somers result += queue->len; 57484b8a6ebSAtsushi Murai 575f4768038SBrian Somers return result; 5761ae349f5Scvs2svn } 5771ae349f5Scvs2svn 5783b0f8d2eSBrian Somers int 5795d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 580af57ed9fSAtsushi Murai { 5815a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 582af57ed9fSAtsushi Murai struct mqueue *queue; 583af57ed9fSAtsushi Murai struct mbuf *bp; 5845d9e6103SBrian Somers struct ip *pip; 58526af0ae9SBrian Somers int m_len; 586af57ed9fSAtsushi Murai 5875a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 5883b0f8d2eSBrian Somers return 0; 5891e991daaSBrian Somers 590442f8495SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 591442f8495SBrian Somers do { 592af57ed9fSAtsushi Murai if (queue->top) { 59326af0ae9SBrian Somers bp = m_pullup(m_dequeue(queue)); 59426af0ae9SBrian Somers m_len = m_length(bp); 5955d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 596cad7e742SBrian Somers if (!FilterCheck(pip, &bundle->filter.alive)) 597ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 598442f8495SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 59926af0ae9SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 6003b0f8d2eSBrian Somers return 1; 601af57ed9fSAtsushi Murai } 602442f8495SBrian Somers } while (queue-- != ipcp->Queue); 6031e991daaSBrian Somers 6043b0f8d2eSBrian Somers return 0; 605af57ed9fSAtsushi Murai } 606