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> 276a6b4bbbSBrian Somers #include <sys/socket.h> 2875240ed1SBrian Somers #include <netinet/in.h> 29af57ed9fSAtsushi Murai #include <netinet/in_systm.h> 30af57ed9fSAtsushi Murai #include <netinet/ip.h> 31af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h> 32af57ed9fSAtsushi Murai #include <netinet/udp.h> 33af57ed9fSAtsushi Murai #include <netinet/tcp.h> 34ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 351fa665f5SBrian Somers #include <sys/un.h> 3675240ed1SBrian Somers 3757fd05c4SBrian Somers #include <errno.h> 3875240ed1SBrian Somers #include <stdio.h> 3975240ed1SBrian Somers #include <string.h> 405d9e6103SBrian Somers #include <termios.h> 4175240ed1SBrian Somers #include <unistd.h> 4275240ed1SBrian Somers 435d9e6103SBrian Somers #include "layer.h" 445d9e6103SBrian Somers #include "proto.h" 45927145beSBrian Somers #include "mbuf.h" 46927145beSBrian Somers #include "log.h" 4775240ed1SBrian Somers #include "defs.h" 4875240ed1SBrian Somers #include "timer.h" 4975240ed1SBrian Somers #include "fsm.h" 50879ed6faSBrian Somers #include "lqr.h" 5175240ed1SBrian Somers #include "hdlc.h" 525828db6dSBrian Somers #include "throughput.h" 535828db6dSBrian Somers #include "iplist.h" 54eaa4df37SBrian Somers #include "slcompress.h" 5575240ed1SBrian Somers #include "ipcp.h" 561ae349f5Scvs2svn #include "filter.h" 572f786681SBrian Somers #include "descriptor.h" 5875240ed1SBrian Somers #include "lcp.h" 593b0f8d2eSBrian Somers #include "ccp.h" 603b0f8d2eSBrian Somers #include "link.h" 613b0f8d2eSBrian Somers #include "mp.h" 62972a1bcfSBrian Somers #ifndef NORADIUS 63972a1bcfSBrian Somers #include "radius.h" 64972a1bcfSBrian Somers #endif 657a6f8720SBrian Somers #include "bundle.h" 666a6b4bbbSBrian Somers #include "tun.h" 6775240ed1SBrian Somers #include "ip.h" 68af57ed9fSAtsushi Murai 6952c9ca19SBrian Somers 7052c9ca19SBrian Somers #define OPCODE_QUERY 0 7152c9ca19SBrian Somers #define OPCODE_IQUERY 1 7252c9ca19SBrian Somers #define OPCODE_STATUS 2 7352c9ca19SBrian Somers 7452c9ca19SBrian Somers struct dns_header { 7552c9ca19SBrian Somers u_short id; 7652c9ca19SBrian Somers unsigned qr : 1; 7752c9ca19SBrian Somers unsigned opcode : 4; 7852c9ca19SBrian Somers unsigned aa : 1; 7952c9ca19SBrian Somers unsigned tc : 1; 8052c9ca19SBrian Somers unsigned rd : 1; 8152c9ca19SBrian Somers unsigned ra : 1; 8252c9ca19SBrian Somers unsigned z : 3; 8352c9ca19SBrian Somers unsigned rcode : 4; 8452c9ca19SBrian Somers u_short qdcount; 8552c9ca19SBrian Somers u_short ancount; 8652c9ca19SBrian Somers u_short nscount; 8752c9ca19SBrian Somers u_short arcount; 88182c898aSBrian Somers }; 89af57ed9fSAtsushi Murai 9052c9ca19SBrian Somers static const char * 9152c9ca19SBrian Somers dns_Qclass2Txt(u_short qclass) 9252c9ca19SBrian Somers { 9352c9ca19SBrian Somers static char failure[6]; 9452c9ca19SBrian Somers struct { 9552c9ca19SBrian Somers u_short id; 9652c9ca19SBrian Somers const char *txt; 9752c9ca19SBrian Somers } qtxt[] = { 9852c9ca19SBrian Somers /* rfc1035 */ 9952c9ca19SBrian Somers { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" } 10052c9ca19SBrian Somers }; 10152c9ca19SBrian Somers int f; 10252c9ca19SBrian Somers 10352c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 10452c9ca19SBrian Somers if (qtxt[f].id == qclass) 10552c9ca19SBrian Somers return qtxt[f].txt; 10652c9ca19SBrian Somers 107d6d3eeabSBrian Somers return HexStr(qclass, failure, sizeof failure); 10852c9ca19SBrian Somers } 10952c9ca19SBrian Somers 11052c9ca19SBrian Somers static const char * 11152c9ca19SBrian Somers dns_Qtype2Txt(u_short qtype) 11252c9ca19SBrian Somers { 11352c9ca19SBrian Somers static char failure[6]; 11452c9ca19SBrian Somers struct { 11552c9ca19SBrian Somers u_short id; 11652c9ca19SBrian Somers const char *txt; 11752c9ca19SBrian Somers } qtxt[] = { 11852c9ca19SBrian Somers /* rfc1035/rfc1700 */ 11952c9ca19SBrian Somers { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" }, 12052c9ca19SBrian Somers { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" }, 12152c9ca19SBrian Somers { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" }, 12252c9ca19SBrian Somers { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" }, 12352c9ca19SBrian Somers { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" }, 12452c9ca19SBrian Somers { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" }, 12552c9ca19SBrian Somers { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" }, 12652c9ca19SBrian Somers { 254, "MAILA" }, { 255, "*" } 12752c9ca19SBrian Somers }; 12852c9ca19SBrian Somers int f; 12952c9ca19SBrian Somers 13052c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 13152c9ca19SBrian Somers if (qtxt[f].id == qtype) 13252c9ca19SBrian Somers return qtxt[f].txt; 13352c9ca19SBrian Somers 134d6d3eeabSBrian Somers return HexStr(qtype, failure, sizeof failure); 13552c9ca19SBrian Somers } 13652c9ca19SBrian Somers 137cad7e742SBrian Somers static __inline int 138944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 139af57ed9fSAtsushi Murai { 140af57ed9fSAtsushi Murai switch (op) { 141af57ed9fSAtsushi Murai case OP_EQ: 1420a4b6c5cSBrian Somers return pport == rport; 143af57ed9fSAtsushi Murai case OP_GT: 1440a4b6c5cSBrian Somers return pport > rport; 145af57ed9fSAtsushi Murai case OP_LT: 1460a4b6c5cSBrian Somers return pport < rport; 147af57ed9fSAtsushi Murai default: 1480a4b6c5cSBrian Somers return 0; 149af57ed9fSAtsushi Murai } 150af57ed9fSAtsushi Murai } 151af57ed9fSAtsushi Murai 152af57ed9fSAtsushi Murai /* 1535d9e6103SBrian Somers * Check a packet against a defined filter 154cad7e742SBrian Somers * Returns 0 to accept the packet, non-zero to drop the packet 155cad7e742SBrian Somers * 156cad7e742SBrian Somers * If filtering is enabled, the initial fragment of a datagram must 157cad7e742SBrian Somers * contain the complete protocol header, and subsequent fragments 158cad7e742SBrian Somers * must not attempt to over-write it. 159af57ed9fSAtsushi Murai */ 160af57ed9fSAtsushi Murai static int 1610a4b6c5cSBrian Somers FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs) 162af57ed9fSAtsushi Murai { 163cad7e742SBrian Somers int gotinfo; /* true if IP payload decoded */ 164cad7e742SBrian Somers int cproto; /* P_* protocol type if (gotinfo) */ 165cad7e742SBrian Somers int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 166cad7e742SBrian Somers u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 167cad7e742SBrian Somers int n; /* filter rule to process */ 168cad7e742SBrian Somers int len; /* bytes used in dbuff */ 169cad7e742SBrian Somers int didname; /* true if filter header printed */ 170cad7e742SBrian Somers int match; /* true if condition matched */ 171cad7e742SBrian Somers const struct filterent *fp = filter->rule; 17206a43ce0SBrian Somers char dbuff[100], dstip[16]; 173af57ed9fSAtsushi Murai 174cad7e742SBrian Somers if (fp->f_action == A_NONE) 1750a4b6c5cSBrian Somers return 0; /* No rule is given. Permit this packet */ 176cad7e742SBrian Somers 1770a4b6c5cSBrian Somers /* 1780a4b6c5cSBrian Somers * Deny any packet fragment that tries to over-write the header. 179cad7e742SBrian Somers * Since we no longer have the real header available, punt on the 180cad7e742SBrian Somers * largest normal header - 20 bytes for TCP without options, rounded 181cad7e742SBrian Somers * up to the next possible fragment boundary. Since the smallest 182cad7e742SBrian Somers * `legal' MTU is 576, and the smallest recommended MTU is 296, any 1830a4b6c5cSBrian Somers * fragmentation within this range is dubious at best 1840a4b6c5cSBrian Somers */ 185cad7e742SBrian Somers len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 186cad7e742SBrian Somers if (len > 0) { /* Not first fragment within datagram */ 18706a43ce0SBrian Somers if (len < (24 >> 3)) { /* don't allow fragment to over-write header */ 18806a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal header\n"); 1890a4b6c5cSBrian Somers return 1; 19006a43ce0SBrian Somers } 191cad7e742SBrian Somers /* permit fragments on in and out filter */ 19206a43ce0SBrian Somers if (!filter->fragok) { 19306a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal fragmentation\n"); 19406a43ce0SBrian Somers return 1; 19506a43ce0SBrian Somers } else 19606a43ce0SBrian Somers return 0; 197cad7e742SBrian Somers } 198cad7e742SBrian Somers 19963f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 200af57ed9fSAtsushi Murai sport = dport = 0; 201cad7e742SBrian Somers for (n = 0; n < MAXFILTERS; ) { 202cad7e742SBrian Somers if (fp->f_action == A_NONE) { 203cad7e742SBrian Somers n++; 204cad7e742SBrian Somers fp++; 205cad7e742SBrian Somers continue; 206cad7e742SBrian Somers } 2075ca5389aSBrian Somers 208cad7e742SBrian Somers if (!didname) { 209dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 2108390b576SBrian Somers didname = 1; 211cad7e742SBrian Somers } 2128390b576SBrian Somers 213cad7e742SBrian Somers match = 0; 214cad7e742SBrian Somers if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 215cad7e742SBrian Somers fp->f_src.mask.s_addr) && 216cad7e742SBrian Somers !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 217cad7e742SBrian Somers fp->f_dst.mask.s_addr)) { 218cad7e742SBrian Somers if (fp->f_proto != P_NONE) { 219af57ed9fSAtsushi Murai if (!gotinfo) { 220cad7e742SBrian Somers const char *ptop = (const char *) pip + (pip->ip_hl << 2); 221cad7e742SBrian Somers const struct tcphdr *th; 222cad7e742SBrian Somers const struct udphdr *uh; 223cad7e742SBrian Somers const struct icmp *ih; 224cad7e742SBrian Somers int datalen; /* IP datagram length */ 225af57ed9fSAtsushi Murai 226cad7e742SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 227af57ed9fSAtsushi Murai switch (pip->ip_p) { 228af57ed9fSAtsushi Murai case IPPROTO_ICMP: 229944f7098SBrian Somers cproto = P_ICMP; 23006a43ce0SBrian Somers if (datalen < 8) { /* ICMP must be at least 8 octets */ 23106a43ce0SBrian Somers log_Printf(LogFILTER, " error: ICMP must be at least 8 octets\n"); 2320a4b6c5cSBrian Somers return 1; 23306a43ce0SBrian Somers } 23406a43ce0SBrian Somers 235cad7e742SBrian Somers ih = (const struct icmp *) ptop; 236944f7098SBrian Somers sport = ih->icmp_type; 23763f98b41SBrian Somers estab = syn = finrst = -1; 238dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 2398390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 240af57ed9fSAtsushi Murai break; 241eee772ecSBrian Somers case IPPROTO_IGMP: 2421f9e5fe5SBrian Somers cproto = P_IGMP; 24306a43ce0SBrian Somers if (datalen < 8) { /* IGMP uses 8-octet messages */ 24406a43ce0SBrian Somers log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n"); 2450a4b6c5cSBrian Somers return 1; 24606a43ce0SBrian Somers } 2471f9e5fe5SBrian Somers estab = syn = finrst = -1; 2481f9e5fe5SBrian Somers sport = ntohs(0); 2491f9e5fe5SBrian Somers break; 25028149effSBrian Somers #ifdef IPPROTO_GRE 25128149effSBrian Somers case IPPROTO_GRE: 25228149effSBrian Somers cproto = P_GRE; 25306a43ce0SBrian Somers if (datalen < 2) { /* GRE uses 2-octet+ messages */ 25406a43ce0SBrian Somers log_Printf(LogFILTER, " error: GRE must be at least 2 octets\n"); 2550a4b6c5cSBrian Somers return 1; 25606a43ce0SBrian Somers } 25728149effSBrian Somers estab = syn = finrst = -1; 25828149effSBrian Somers sport = ntohs(0); 25928149effSBrian Somers break; 26028149effSBrian Somers #endif 26162e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 2622faae814SBrian Somers case IPPROTO_OSPFIGP: 2632faae814SBrian Somers cproto = P_OSPF; 26406a43ce0SBrian Somers if (datalen < 8) { /* IGMP uses 8-octet messages */ 26506a43ce0SBrian Somers log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n"); 2660a4b6c5cSBrian Somers return 1; 26706a43ce0SBrian Somers } 2682faae814SBrian Somers estab = syn = finrst = -1; 2692faae814SBrian Somers sport = ntohs(0); 2702faae814SBrian Somers break; 27162e85934SBrian Somers #endif 2722231246bSBrian Somers case IPPROTO_ESP: 2732231246bSBrian Somers cproto = P_ESP; 2742231246bSBrian Somers estab = syn = finrst = -1; 2752231246bSBrian Somers sport = ntohs(0); 2762231246bSBrian Somers break; 2772231246bSBrian Somers case IPPROTO_AH: 2782231246bSBrian Somers cproto = P_AH; 2792231246bSBrian Somers estab = syn = finrst = -1; 2802231246bSBrian Somers sport = ntohs(0); 2812231246bSBrian Somers break; 282eee772ecSBrian Somers case IPPROTO_IPIP: 283da70ad60SBrian Somers cproto = P_IPIP; 284da70ad60SBrian Somers sport = dport = 0; 285da70ad60SBrian Somers estab = syn = finrst = -1; 286da70ad60SBrian Somers break; 287da70ad60SBrian Somers case IPPROTO_UDP: 288944f7098SBrian Somers cproto = P_UDP; 28906a43ce0SBrian Somers if (datalen < 8) { /* UDP header is 8 octets */ 290da70ad60SBrian Somers log_Printf(LogFILTER, " error: UDP/IPIP" 291da70ad60SBrian Somers " must be at least 8 octets\n"); 2920a4b6c5cSBrian Somers return 1; 29306a43ce0SBrian Somers } 29406a43ce0SBrian Somers 295cad7e742SBrian Somers uh = (const struct udphdr *) ptop; 296944f7098SBrian Somers sport = ntohs(uh->uh_sport); 297944f7098SBrian Somers dport = ntohs(uh->uh_dport); 29863f98b41SBrian Somers estab = syn = finrst = -1; 299dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 3008390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 3018390b576SBrian Somers sport, dport); 302af57ed9fSAtsushi Murai break; 303af57ed9fSAtsushi Murai case IPPROTO_TCP: 304944f7098SBrian Somers cproto = P_TCP; 305cad7e742SBrian Somers th = (const struct tcphdr *) ptop; 306cad7e742SBrian Somers /* TCP headers are variable length. The following code 307cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 308cad7e742SBrian Somers * the datagram is too short 309cad7e742SBrian Somers */ 31006a43ce0SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) { 31106a43ce0SBrian Somers log_Printf(LogFILTER, " error: TCP header incorrect\n"); 3120a4b6c5cSBrian Somers return 1; 31306a43ce0SBrian Somers } 314944f7098SBrian Somers sport = ntohs(th->th_sport); 315944f7098SBrian Somers dport = ntohs(th->th_dport); 316af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 31763f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 31863f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 3192b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 3202b81c773SBrian Somers if (!estab) 3218390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 3228390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 323927145beSBrian Somers th->th_flags, sport, dport); 3242b81c773SBrian Somers else 3252b81c773SBrian Somers *dbuff = '\0'; 3262b81c773SBrian Somers } 327af57ed9fSAtsushi Murai break; 328af57ed9fSAtsushi Murai default: 32906a43ce0SBrian Somers log_Printf(LogFILTER, " error: unknown protocol\n"); 3300a4b6c5cSBrian Somers return 1; /* We'll block unknown type of packet */ 331af57ed9fSAtsushi Murai } 332cad7e742SBrian Somers 333dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 3348390b576SBrian Somers if (estab != -1) { 3358390b576SBrian Somers len = strlen(dbuff); 33663f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 33763f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 33863f98b41SBrian Somers estab, syn, finrst); 339af57ed9fSAtsushi Murai } 340dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 3418390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 3428390b576SBrian Somers } 3438390b576SBrian Somers gotinfo = 1; 3448390b576SBrian Somers } 345dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 346cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 3478390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 348cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 3498390b576SBrian Somers len = strlen(dbuff); 3508390b576SBrian Somers } else 3518390b576SBrian Somers len = 0; 352cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 3538390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 354cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 355cad7e742SBrian Somers fp->f_dstport); 3568390b576SBrian Somers } else if (!len) 3578390b576SBrian Somers *dbuff = '\0'; 3588390b576SBrian Somers 359dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 3608390b576SBrian Somers "check against proto %s%s, action = %s\n", 361cad7e742SBrian Somers n, filter_Proto2Nam(fp->f_proto), 362cad7e742SBrian Somers dbuff, filter_Action2Nam(fp->f_action)); 3638390b576SBrian Somers } 364927145beSBrian Somers 365cad7e742SBrian Somers if (cproto == fp->f_proto) { 366cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 367cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 368cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 369cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 370cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 371cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 372cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 373cad7e742SBrian Somers match = 1; 374af57ed9fSAtsushi Murai } 375af57ed9fSAtsushi Murai } 376af57ed9fSAtsushi Murai } else { 377cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 378dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 379cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 380cad7e742SBrian Somers match = 1; 381af57ed9fSAtsushi Murai } 3828390b576SBrian Somers } else 383dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 384cad7e742SBrian Somers 385cad7e742SBrian Somers if (match != fp->f_invert) { 386cad7e742SBrian Somers /* Take specified action */ 387cad7e742SBrian Somers if (fp->f_action < A_NONE) 388cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 38906a43ce0SBrian Somers else { 3900a4b6c5cSBrian Somers if (fp->f_action == A_PERMIT) { 3910a4b6c5cSBrian Somers if (psecs != NULL) 3920a4b6c5cSBrian Somers *psecs = fp->timeout; 39306a43ce0SBrian Somers if (strcmp(filter->name, "DIAL") == 0) { 39406a43ce0SBrian Somers /* If dial filter then even print out accept packets */ 39506a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 39606a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 39706a43ce0SBrian Somers log_Printf(LogFILTER, "%sbound rule = %d accept %s " 39806a43ce0SBrian Somers "src = %s/%d dst = %s/%d\n", 39906a43ce0SBrian Somers filter->name, n, filter_Proto2Nam(cproto), 40006a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 40106a43ce0SBrian Somers } 40206a43ce0SBrian Somers } 4030a4b6c5cSBrian Somers return 0; 40406a43ce0SBrian Somers } else { 40506a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 40606a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 40706a43ce0SBrian Somers log_Printf(LogFILTER, 40806a43ce0SBrian Somers "%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n", 40906a43ce0SBrian Somers filter->name, n, filter_Proto2Nam(cproto), 41006a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 41106a43ce0SBrian Somers } 4120a4b6c5cSBrian Somers return 1; 41306a43ce0SBrian Somers } /* Explict math. Deny this packet */ 41406a43ce0SBrian Somers } 415cad7e742SBrian Somers } else { 416cad7e742SBrian Somers n++; 417af57ed9fSAtsushi Murai fp++; 418af57ed9fSAtsushi Murai } 419af57ed9fSAtsushi Murai } 42006a43ce0SBrian Somers 42106a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 42206a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 42306a43ce0SBrian Somers log_Printf(LogFILTER, 42406a43ce0SBrian Somers "%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n", 42506a43ce0SBrian Somers filter->name, filter_Proto2Nam(cproto), 42606a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 42706a43ce0SBrian Somers } 42806a43ce0SBrian Somers 4290a4b6c5cSBrian Somers return 1; /* No rule is mached. Deny this packet */ 430af57ed9fSAtsushi Murai } 431af57ed9fSAtsushi Murai 4325ca5389aSBrian Somers #ifdef notdef 433af57ed9fSAtsushi Murai static void 434944f7098SBrian Somers IcmpError(struct ip *pip, int code) 435af57ed9fSAtsushi Murai { 436af57ed9fSAtsushi Murai struct mbuf *bp; 437af57ed9fSAtsushi Murai 438af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 43926af0ae9SBrian Somers bp = m_get(m_len, MB_IPIN); 44026af0ae9SBrian Somers memcpy(MBUF_CTOP(bp), ptr, m_len); 441dd7e2610SBrian Somers vj_SendFrame(bp); 44226af0ae9SBrian Somers ipcp_AddOutOctets(m_len); 4431ae349f5Scvs2svn } 444af57ed9fSAtsushi Murai } 445af57ed9fSAtsushi Murai #endif 446af57ed9fSAtsushi Murai 44752c9ca19SBrian Somers static void 44852c9ca19SBrian Somers ip_LogDNS(const struct udphdr *uh, const char *direction) 44952c9ca19SBrian Somers { 45052c9ca19SBrian Somers struct dns_header header; 45152c9ca19SBrian Somers const u_short *pktptr; 45252c9ca19SBrian Somers const u_char *ptr; 45347fe010cSBrian Somers u_short *hptr, tmp; 45452c9ca19SBrian Somers int len; 45552c9ca19SBrian Somers 45652c9ca19SBrian Somers ptr = (const char *)uh + sizeof *uh; 45752c9ca19SBrian Somers len = ntohs(uh->uh_ulen) - sizeof *uh; 45852c9ca19SBrian Somers if (len < sizeof header + 5) /* rfc1024 */ 45952c9ca19SBrian Somers return; 46052c9ca19SBrian Somers 46152c9ca19SBrian Somers pktptr = (const u_short *)ptr; 46252c9ca19SBrian Somers hptr = (u_short *)&header; 46352c9ca19SBrian Somers ptr += sizeof header; 46452c9ca19SBrian Somers len -= sizeof header; 46552c9ca19SBrian Somers 46652c9ca19SBrian Somers while (pktptr < (const u_short *)ptr) { 46752c9ca19SBrian Somers *hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */ 46852c9ca19SBrian Somers pktptr++; 46952c9ca19SBrian Somers } 47052c9ca19SBrian Somers 47152c9ca19SBrian Somers if (header.opcode == OPCODE_QUERY && header.qr == 0) { 47252c9ca19SBrian Somers /* rfc1035 */ 47326e6a622SBrian Somers char namewithdot[MAXHOSTNAMELEN + 1], *n; 47452c9ca19SBrian Somers const char *qtype, *qclass; 47552c9ca19SBrian Somers const u_char *end; 47652c9ca19SBrian Somers 47726e6a622SBrian Somers n = namewithdot; 47852c9ca19SBrian Somers end = ptr + len - 4; 47926e6a622SBrian Somers if (end - ptr >= sizeof namewithdot) 48026e6a622SBrian Somers end = ptr + sizeof namewithdot - 1; 48152c9ca19SBrian Somers while (ptr < end) { 48252c9ca19SBrian Somers len = *ptr++; 48352c9ca19SBrian Somers if (len > end - ptr) 48452c9ca19SBrian Somers len = end - ptr; 48526e6a622SBrian Somers if (n != namewithdot) 48652c9ca19SBrian Somers *n++ = '.'; 48752c9ca19SBrian Somers memcpy(n, ptr, len); 48852c9ca19SBrian Somers ptr += len; 48952c9ca19SBrian Somers n += len; 49052c9ca19SBrian Somers } 49152c9ca19SBrian Somers *n = '\0'; 49247fe010cSBrian Somers 49347fe010cSBrian Somers if (log_IsKept(LogDNS)) { 49447fe010cSBrian Somers memcpy(&tmp, end, sizeof tmp); 49547fe010cSBrian Somers qtype = dns_Qtype2Txt(ntohs(tmp)); 49647fe010cSBrian Somers memcpy(&tmp, end + 2, sizeof tmp); 49747fe010cSBrian Somers qclass = dns_Qclass2Txt(ntohs(tmp)); 49852c9ca19SBrian Somers 49952c9ca19SBrian Somers log_Printf(LogDNS, "%sbound query %s %s %s\n", 50026e6a622SBrian Somers direction, qclass, qtype, namewithdot); 50152c9ca19SBrian Somers } 50252c9ca19SBrian Somers } 50347fe010cSBrian Somers } 50452c9ca19SBrian Somers 505af57ed9fSAtsushi Murai /* 506af57ed9fSAtsushi Murai * For debugging aid. 507af57ed9fSAtsushi Murai */ 508af57ed9fSAtsushi Murai int 50998251667SBrian Somers PacketCheck(struct bundle *bundle, unsigned char *cp, int nb, 5100a4b6c5cSBrian Somers struct filter *filter, const char *prefix, unsigned *psecs) 511af57ed9fSAtsushi Murai { 51252c9ca19SBrian Somers static const char *const TcpFlags[] = { 51352c9ca19SBrian Somers "FIN", "SYN", "RST", "PSH", "ACK", "URG" 51452c9ca19SBrian Somers }; 515af57ed9fSAtsushi Murai struct ip *pip; 516af57ed9fSAtsushi Murai struct tcphdr *th; 517af57ed9fSAtsushi Murai struct udphdr *uh; 518af57ed9fSAtsushi Murai struct icmp *icmph; 51998251667SBrian Somers unsigned char *ptop; 52052c9ca19SBrian Somers int mask, len, n, pri, logit, loglen, result; 521d93d3a9cSBrian Somers char logbuf[200]; 522af57ed9fSAtsushi Murai 523b565321aSBrian Somers logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) && 524b565321aSBrian Somers (!filter || filter->logok); 52555a8cdeaSBrian Somers loglen = 0; 52652c9ca19SBrian Somers pri = 0; 527af57ed9fSAtsushi Murai 528af57ed9fSAtsushi Murai pip = (struct ip *)cp; 52952c9ca19SBrian Somers uh = NULL; 530af57ed9fSAtsushi Murai 53155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 53298251667SBrian Somers if (prefix) 53398251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix); 53498251667SBrian Somers else if (filter) 5355ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 536b565321aSBrian Somers else 537b565321aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " "); 53855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 53955a8cdeaSBrian Somers } 540af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 541af57ed9fSAtsushi Murai 542af57ed9fSAtsushi Murai switch (pip->ip_p) { 543af57ed9fSAtsushi Murai case IPPROTO_ICMP: 54455a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 54598251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *icmph; 546af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 54755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 54855a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 54955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 55055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 55198251667SBrian Somers "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), icmph->icmp_type, 55298251667SBrian Somers len, nb); 55355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 554af57ed9fSAtsushi Murai } 555af57ed9fSAtsushi Murai break; 556da477886SBrian Somers 557af57ed9fSAtsushi Murai case IPPROTO_UDP: 558af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 5594c240437SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos) 560da477886SBrian Somers pri++; 561da477886SBrian Somers 562da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 563da477886SBrian Somers ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 564da477886SBrian Somers ntohs(uh->uh_dport))) 565da477886SBrian Somers pri++; 566da477886SBrian Somers 567da477886SBrian Somers if (logit && loglen < sizeof logbuf) { 56898251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *uh; 56955a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 57055a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 57155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 57255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 57398251667SBrian Somers "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport), 57498251667SBrian Somers len, nb); 57555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 576af57ed9fSAtsushi Murai } 57798251667SBrian Somers 57898251667SBrian Somers if (Enabled(bundle, OPT_FILTERDECAP) && 57998251667SBrian Somers ptop[sizeof *uh] == HDLC_ADDR && ptop[sizeof *uh + 1] == HDLC_UI) { 58098251667SBrian Somers u_short proto; 58198251667SBrian Somers const char *type; 58298251667SBrian Somers 58398251667SBrian Somers memcpy(&proto, ptop + sizeof *uh + 2, sizeof proto); 58498251667SBrian Somers type = NULL; 58598251667SBrian Somers 58698251667SBrian Somers switch (ntohs(proto)) { 58798251667SBrian Somers case PROTO_IP: 58898251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 58998251667SBrian Somers result = PacketCheck(bundle, ptop + sizeof *uh + 4, 59098251667SBrian Somers nb - (ptop - cp) - sizeof *uh - 4, filter, 5910a4b6c5cSBrian Somers logbuf, psecs); 59298251667SBrian Somers if (result != -2) 59398251667SBrian Somers return result; 59498251667SBrian Somers type = "IP"; 59598251667SBrian Somers break; 59698251667SBrian Somers 59798251667SBrian Somers case PROTO_VJUNCOMP: type = "compressed VJ"; break; 59898251667SBrian Somers case PROTO_VJCOMP: type = "uncompressed VJ"; break; 59998251667SBrian Somers case PROTO_MP: type = "Multi-link"; break; 60098251667SBrian Somers case PROTO_ICOMPD: type = "Individual link CCP"; break; 60198251667SBrian Somers case PROTO_COMPD: type = "CCP"; break; 60298251667SBrian Somers case PROTO_IPCP: type = "IPCP"; break; 60398251667SBrian Somers case PROTO_LCP: type = "LCP"; break; 60498251667SBrian Somers case PROTO_PAP: type = "PAP"; break; 60598251667SBrian Somers case PROTO_CBCP: type = "CBCP"; break; 60698251667SBrian Somers case PROTO_LQR: type = "LQR"; break; 60798251667SBrian Somers case PROTO_CHAP: type = "CHAP"; break; 60898251667SBrian Somers } 60998251667SBrian Somers if (type) { 61098251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 61198251667SBrian Somers " - %s data", type); 61298251667SBrian Somers loglen += strlen(logbuf + loglen); 61398251667SBrian Somers } 61498251667SBrian Somers } 61598251667SBrian Somers 616af57ed9fSAtsushi Murai break; 617da477886SBrian Somers 61828149effSBrian Somers #ifdef IPPROTO_GRE 61928149effSBrian Somers case IPPROTO_GRE: 62028149effSBrian Somers if (logit && loglen < sizeof logbuf) { 62198251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2); 62228149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 62328149effSBrian Somers "GRE: %s ---> ", inet_ntoa(pip->ip_src)); 62428149effSBrian Somers loglen += strlen(logbuf + loglen); 62528149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 62698251667SBrian Somers "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb); 62728149effSBrian Somers loglen += strlen(logbuf + loglen); 62828149effSBrian Somers } 62928149effSBrian Somers break; 63028149effSBrian Somers #endif 63128149effSBrian Somers 63262e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 6332faae814SBrian Somers case IPPROTO_OSPFIGP: 6342faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 63598251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2); 6362faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6372faae814SBrian Somers "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 6382faae814SBrian Somers loglen += strlen(logbuf + loglen); 6392faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 64098251667SBrian Somers "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb); 6412faae814SBrian Somers loglen += strlen(logbuf + loglen); 6422faae814SBrian Somers } 6432faae814SBrian Somers break; 64462e85934SBrian Somers #endif 645da477886SBrian Somers 646eee772ecSBrian Somers case IPPROTO_IPIP: 647eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 648eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 649da70ad60SBrian Somers "IPIP: %s ---> ", inet_ntoa(pip->ip_src)); 650eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 651eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 652da70ad60SBrian Somers "%s", inet_ntoa(pip->ip_dst)); 653eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 654da70ad60SBrian Somers 655da70ad60SBrian Somers if (((struct ip *)ptop)->ip_v == 4) { 656da70ad60SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 657da70ad60SBrian Somers result = PacketCheck(bundle, ptop, nb - (ptop - cp), filter, 658da70ad60SBrian Somers logbuf, psecs); 659da70ad60SBrian Somers if (result != -2) 660da70ad60SBrian Somers return result; 661da70ad60SBrian Somers } 662eee772ecSBrian Somers } 663eee772ecSBrian Somers break; 664da477886SBrian Somers 6652231246bSBrian Somers case IPPROTO_ESP: 6662231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 6672231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6682231246bSBrian Somers "ESP: %s ---> ", inet_ntoa(pip->ip_src)); 6692231246bSBrian Somers loglen += strlen(logbuf + loglen); 67025254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 67125254215SBrian Somers inet_ntoa(pip->ip_dst), ptop); 6722231246bSBrian Somers loglen += strlen(logbuf + loglen); 6732231246bSBrian Somers } 6742231246bSBrian Somers break; 6752231246bSBrian Somers 6762231246bSBrian Somers case IPPROTO_AH: 6772231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 6782231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6792231246bSBrian Somers "AH: %s ---> ", inet_ntoa(pip->ip_src)); 6802231246bSBrian Somers loglen += strlen(logbuf + loglen); 68125254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 68225254215SBrian Somers inet_ntoa(pip->ip_dst), ptop + sizeof(u_int32_t)); 6832231246bSBrian Somers loglen += strlen(logbuf + loglen); 6842231246bSBrian Somers } 6852231246bSBrian Somers break; 6862231246bSBrian Somers 687eee772ecSBrian Somers case IPPROTO_IGMP: 688eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 689eee772ecSBrian Somers uh = (struct udphdr *) ptop; 690eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6910a4b6c5cSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), 6920a4b6c5cSBrian Somers ntohs(uh->uh_sport)); 693eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 694eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 695eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 696eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 697eee772ecSBrian Somers } 698eee772ecSBrian Somers break; 699da477886SBrian Somers 700af57ed9fSAtsushi Murai case IPPROTO_TCP: 701af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 7024c240437SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos) 703442f8495SBrian Somers pri++; 704da477886SBrian Somers 705da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 706da477886SBrian Somers ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 707442f8495SBrian Somers ntohs(th->th_dport))) 708442f8495SBrian Somers pri++; 709442f8495SBrian Somers 71055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 711af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 71255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 71355a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 71455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 71555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 71655a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 71755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 718af57ed9fSAtsushi Murai n = 0; 719af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 72055a8cdeaSBrian Somers if (th->th_flags & mask) { 72155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 72255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 72355a8cdeaSBrian Somers } 724af57ed9fSAtsushi Murai n++; 725af57ed9fSAtsushi Murai } 72655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 7273a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 7283a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 72955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 730af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 731af57ed9fSAtsushi Murai u_short *sp; 732af57ed9fSAtsushi Murai 733af57ed9fSAtsushi Murai ptop += 20; 734af57ed9fSAtsushi Murai sp = (u_short *) ptop; 73555a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 73655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 73755a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 73855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 73955a8cdeaSBrian Somers } 740af57ed9fSAtsushi Murai } 741af57ed9fSAtsushi Murai } 742af57ed9fSAtsushi Murai break; 74398251667SBrian Somers 74498251667SBrian Somers default: 74598251667SBrian Somers if (prefix) 74698251667SBrian Somers return -2; 747af57ed9fSAtsushi Murai } 74876bd0c0aSDoug Rabson 7490a4b6c5cSBrian Somers if (filter && FilterCheck(pip, filter, psecs)) { 750710e9c29SBrian Somers if (logit) 751dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 7525ca5389aSBrian Somers #ifdef notdef 753944f7098SBrian Somers if (direction == 0) 754944f7098SBrian Somers IcmpError(pip, pri); 7555ca5389aSBrian Somers #endif 75652c9ca19SBrian Somers result = -1; 757af57ed9fSAtsushi Murai } else { 7585ca5389aSBrian Somers /* Check Keep Alive filter */ 75952c9ca19SBrian Somers if (logit && log_IsKept(LogTCPIP)) { 7600a4b6c5cSBrian Somers unsigned alivesecs; 7610a4b6c5cSBrian Somers 7620a4b6c5cSBrian Somers alivesecs = 0; 7630a4b6c5cSBrian Somers if (filter && FilterCheck(pip, &bundle->filter.alive, &alivesecs)) 764dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 7650a4b6c5cSBrian Somers else if (psecs != NULL) { 7660a4b6c5cSBrian Somers if(*psecs == 0) 7670a4b6c5cSBrian Somers *psecs = alivesecs; 7680a4b6c5cSBrian Somers if (*psecs) { 7690a4b6c5cSBrian Somers if (*psecs != alivesecs) 7700a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n", 7710a4b6c5cSBrian Somers logbuf, *psecs, alivesecs); 7721e991daaSBrian Somers else 7730a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs); 7740a4b6c5cSBrian Somers } else 775dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 77653c9f6c0SAtsushi Murai } 7770a4b6c5cSBrian Somers } 77852c9ca19SBrian Somers result = pri; 779af57ed9fSAtsushi Murai } 78052c9ca19SBrian Somers 781b565321aSBrian Somers if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS)) 78252c9ca19SBrian Somers ip_LogDNS(uh, filter->name); 78352c9ca19SBrian Somers 78452c9ca19SBrian Somers return result; 785af57ed9fSAtsushi Murai } 786af57ed9fSAtsushi Murai 7875d9e6103SBrian Somers struct mbuf * 7885d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 7897a6f8720SBrian Somers { 790af57ed9fSAtsushi Murai int nb, nw; 791b6e82f33SBrian Somers struct tun_data tun; 7925d9e6103SBrian Somers struct ip *pip; 7933a7b6d76SBrian Somers char *data; 7940a4b6c5cSBrian Somers unsigned secs, alivesecs; 7955d9e6103SBrian Somers 7965d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 7975d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 79826af0ae9SBrian Somers m_freem(bp); 7995d9e6103SBrian Somers return NULL; 8005d9e6103SBrian Somers } 801af57ed9fSAtsushi Murai 80226af0ae9SBrian Somers m_settype(bp, MB_IPIN); 80326af0ae9SBrian Somers nb = m_length(bp); 80476d98538SBrian Somers if (nb > sizeof tun.data) { 80576d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 80676d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 80726af0ae9SBrian Somers m_freem(bp); 80876d98538SBrian Somers return NULL; 80976d98538SBrian Somers } 8105d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 811af57ed9fSAtsushi Murai 8120a4b6c5cSBrian Somers secs = 0; 8130a4b6c5cSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL, &secs) < 0) 8145d9e6103SBrian Somers return NULL; 8156db75539SBrian Somers 8165d9e6103SBrian Somers pip = (struct ip *)tun.data; 8170a4b6c5cSBrian Somers alivesecs = 0; 8180a4b6c5cSBrian Somers if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) { 8190a4b6c5cSBrian Somers if (secs == 0) 8200a4b6c5cSBrian Somers secs = alivesecs; 8210a4b6c5cSBrian Somers bundle_StartIdleTimer(bundle, secs); 8220a4b6c5cSBrian Somers } 8231e991daaSBrian Somers 8245828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 8251e991daaSBrian Somers 8263a7b6d76SBrian Somers if (bundle->dev.header) { 8270a4b6c5cSBrian Somers tun.header.family = htonl(AF_INET); 82870ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 8293a7b6d76SBrian Somers data = (char *)&tun; 8303a7b6d76SBrian Somers } else 8313a7b6d76SBrian Somers data = tun.data; 8323a7b6d76SBrian Somers 8333a7b6d76SBrian Somers nw = write(bundle->dev.fd, data, nb); 834c4c4aaacSBrian Somers if (nw != nb) { 83557fd05c4SBrian Somers if (nw == -1) 83676d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 83776d98538SBrian Somers l->name, nb, strerror(errno)); 83857fd05c4SBrian Somers else 83976d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 8406db75539SBrian Somers } 8415d9e6103SBrian Somers 8425d9e6103SBrian Somers return NULL; 843af57ed9fSAtsushi Murai } 844af57ed9fSAtsushi Murai 845af57ed9fSAtsushi Murai void 8465a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 847af57ed9fSAtsushi Murai { 848af57ed9fSAtsushi Murai struct mbuf *bp; 849af57ed9fSAtsushi Murai 850442f8495SBrian Somers if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 8515a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 8525a72b6edSBrian Somers else { 8535d9e6103SBrian Somers /* 8545d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 8555d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 85626af0ae9SBrian Somers * m_prepend() in acf_LayerPush() and proto_LayerPush() and 8575d9e6103SBrian Somers * appending in hdlc_LayerPush(). 8585d9e6103SBrian Somers */ 85926af0ae9SBrian Somers bp = m_get(count + 6, MB_IPOUT); 86026af0ae9SBrian Somers bp->m_offset += 4; 86126af0ae9SBrian Somers bp->m_len -= 6; 86275240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 86326af0ae9SBrian Somers m_enqueue(ipcp->Queue + pri, bp); 8645a72b6edSBrian Somers } 865af57ed9fSAtsushi Murai } 866af57ed9fSAtsushi Murai 8676f8e9f0aSBrian Somers void 8685a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 8696f8e9f0aSBrian Somers { 8706f8e9f0aSBrian Somers struct mqueue *queue; 8716f8e9f0aSBrian Somers 872442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 8736f8e9f0aSBrian Somers while (queue->top) 87426af0ae9SBrian Somers m_freem(m_dequeue(queue)); 8756f8e9f0aSBrian Somers } 8766f8e9f0aSBrian Somers 87726af0ae9SBrian Somers size_t 8785a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 87984b8a6ebSAtsushi Murai { 88084b8a6ebSAtsushi Murai struct mqueue *queue; 88126af0ae9SBrian Somers size_t result; 882944f7098SBrian Somers 88326af0ae9SBrian Somers result = 0; 884442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 88526af0ae9SBrian Somers result += queue->len; 88684b8a6ebSAtsushi Murai 887f4768038SBrian Somers return result; 8881ae349f5Scvs2svn } 8891ae349f5Scvs2svn 8903b0f8d2eSBrian Somers int 8915d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 892af57ed9fSAtsushi Murai { 8935a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 894af57ed9fSAtsushi Murai struct mqueue *queue; 895af57ed9fSAtsushi Murai struct mbuf *bp; 8965d9e6103SBrian Somers struct ip *pip; 89726af0ae9SBrian Somers int m_len; 8980a4b6c5cSBrian Somers u_int32_t secs = 0; 8990a4b6c5cSBrian Somers unsigned alivesecs = 0; 900af57ed9fSAtsushi Murai 9015a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 9023b0f8d2eSBrian Somers return 0; 9031e991daaSBrian Somers 904442f8495SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 905442f8495SBrian Somers do { 906af57ed9fSAtsushi Murai if (queue->top) { 9070a4b6c5cSBrian Somers bp = m_dequeue(queue); 9080a4b6c5cSBrian Somers bp = mbuf_Read(bp, &secs, sizeof secs); 9090a4b6c5cSBrian Somers bp = m_pullup(bp); 91026af0ae9SBrian Somers m_len = m_length(bp); 9115d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 9120a4b6c5cSBrian Somers if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) { 9130a4b6c5cSBrian Somers if (secs == 0) 9140a4b6c5cSBrian Somers secs = alivesecs; 9150a4b6c5cSBrian Somers bundle_StartIdleTimer(bundle, secs); 9160a4b6c5cSBrian Somers } 917442f8495SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 91826af0ae9SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 9193b0f8d2eSBrian Somers return 1; 920af57ed9fSAtsushi Murai } 921442f8495SBrian Somers } while (queue-- != ipcp->Queue); 9221e991daaSBrian Somers 9233b0f8d2eSBrian Somers return 0; 924af57ed9fSAtsushi Murai } 925