165309e5cSBrian Somers /*- 265309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 365309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 465309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 565309e5cSBrian Somers * All rights reserved. 6af57ed9fSAtsushi Murai * 765309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 865309e5cSBrian Somers * modification, are permitted provided that the following conditions 965309e5cSBrian Somers * are met: 1065309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1165309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1265309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1465309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 15af57ed9fSAtsushi Murai * 1665309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1765309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1865309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1965309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2065309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2165309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2265309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2365309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2465309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2565309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2665309e5cSBrian Somers * SUCH DAMAGE. 27af57ed9fSAtsushi Murai * 2897d92980SPeter Wemm * $FreeBSD$ 29af57ed9fSAtsushi Murai */ 3065309e5cSBrian Somers 31972a1bcfSBrian Somers #include <sys/param.h> 326a6b4bbbSBrian Somers #include <sys/socket.h> 3375240ed1SBrian Somers #include <netinet/in.h> 34af57ed9fSAtsushi Murai #include <netinet/in_systm.h> 35af57ed9fSAtsushi Murai #include <netinet/ip.h> 36af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h> 37af57ed9fSAtsushi Murai #include <netinet/udp.h> 38af57ed9fSAtsushi Murai #include <netinet/tcp.h> 39ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 401fa665f5SBrian Somers #include <sys/un.h> 4175240ed1SBrian Somers 4257fd05c4SBrian Somers #include <errno.h> 4375240ed1SBrian Somers #include <stdio.h> 4475240ed1SBrian Somers #include <string.h> 455d9e6103SBrian Somers #include <termios.h> 4675240ed1SBrian Somers #include <unistd.h> 4775240ed1SBrian Somers 485d9e6103SBrian Somers #include "layer.h" 495d9e6103SBrian Somers #include "proto.h" 50927145beSBrian Somers #include "mbuf.h" 51927145beSBrian Somers #include "log.h" 5275240ed1SBrian Somers #include "defs.h" 5375240ed1SBrian Somers #include "timer.h" 5475240ed1SBrian Somers #include "fsm.h" 55879ed6faSBrian Somers #include "lqr.h" 5675240ed1SBrian Somers #include "hdlc.h" 575828db6dSBrian Somers #include "throughput.h" 585828db6dSBrian Somers #include "iplist.h" 59eaa4df37SBrian Somers #include "slcompress.h" 6075240ed1SBrian Somers #include "ipcp.h" 611ae349f5Scvs2svn #include "filter.h" 622f786681SBrian Somers #include "descriptor.h" 6375240ed1SBrian Somers #include "lcp.h" 643b0f8d2eSBrian Somers #include "ccp.h" 653b0f8d2eSBrian Somers #include "link.h" 663b0f8d2eSBrian Somers #include "mp.h" 67972a1bcfSBrian Somers #ifndef NORADIUS 68972a1bcfSBrian Somers #include "radius.h" 69972a1bcfSBrian Somers #endif 707a6f8720SBrian Somers #include "bundle.h" 716a6b4bbbSBrian Somers #include "tun.h" 7275240ed1SBrian Somers #include "ip.h" 73af57ed9fSAtsushi Murai 7452c9ca19SBrian Somers 7552c9ca19SBrian Somers #define OPCODE_QUERY 0 7652c9ca19SBrian Somers #define OPCODE_IQUERY 1 7752c9ca19SBrian Somers #define OPCODE_STATUS 2 7852c9ca19SBrian Somers 7952c9ca19SBrian Somers struct dns_header { 8052c9ca19SBrian Somers u_short id; 8152c9ca19SBrian Somers unsigned qr : 1; 8252c9ca19SBrian Somers unsigned opcode : 4; 8352c9ca19SBrian Somers unsigned aa : 1; 8452c9ca19SBrian Somers unsigned tc : 1; 8552c9ca19SBrian Somers unsigned rd : 1; 8652c9ca19SBrian Somers unsigned ra : 1; 8752c9ca19SBrian Somers unsigned z : 3; 8852c9ca19SBrian Somers unsigned rcode : 4; 8952c9ca19SBrian Somers u_short qdcount; 9052c9ca19SBrian Somers u_short ancount; 9152c9ca19SBrian Somers u_short nscount; 9252c9ca19SBrian Somers u_short arcount; 93182c898aSBrian Somers }; 94af57ed9fSAtsushi Murai 9552c9ca19SBrian Somers static const char * 9652c9ca19SBrian Somers dns_Qclass2Txt(u_short qclass) 9752c9ca19SBrian Somers { 9852c9ca19SBrian Somers static char failure[6]; 9952c9ca19SBrian Somers struct { 10052c9ca19SBrian Somers u_short id; 10152c9ca19SBrian Somers const char *txt; 10252c9ca19SBrian Somers } qtxt[] = { 10352c9ca19SBrian Somers /* rfc1035 */ 10452c9ca19SBrian Somers { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" } 10552c9ca19SBrian Somers }; 10652c9ca19SBrian Somers int f; 10752c9ca19SBrian Somers 10852c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 10952c9ca19SBrian Somers if (qtxt[f].id == qclass) 11052c9ca19SBrian Somers return qtxt[f].txt; 11152c9ca19SBrian Somers 112d6d3eeabSBrian Somers return HexStr(qclass, failure, sizeof failure); 11352c9ca19SBrian Somers } 11452c9ca19SBrian Somers 11552c9ca19SBrian Somers static const char * 11652c9ca19SBrian Somers dns_Qtype2Txt(u_short qtype) 11752c9ca19SBrian Somers { 11852c9ca19SBrian Somers static char failure[6]; 11952c9ca19SBrian Somers struct { 12052c9ca19SBrian Somers u_short id; 12152c9ca19SBrian Somers const char *txt; 12252c9ca19SBrian Somers } qtxt[] = { 12352c9ca19SBrian Somers /* rfc1035/rfc1700 */ 12452c9ca19SBrian Somers { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" }, 12552c9ca19SBrian Somers { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" }, 12652c9ca19SBrian Somers { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" }, 12752c9ca19SBrian Somers { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" }, 12852c9ca19SBrian Somers { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" }, 12952c9ca19SBrian Somers { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" }, 13052c9ca19SBrian Somers { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" }, 13152c9ca19SBrian Somers { 254, "MAILA" }, { 255, "*" } 13252c9ca19SBrian Somers }; 13352c9ca19SBrian Somers int f; 13452c9ca19SBrian Somers 13552c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 13652c9ca19SBrian Somers if (qtxt[f].id == qtype) 13752c9ca19SBrian Somers return qtxt[f].txt; 13852c9ca19SBrian Somers 139d6d3eeabSBrian Somers return HexStr(qtype, failure, sizeof failure); 14052c9ca19SBrian Somers } 14152c9ca19SBrian Somers 142cad7e742SBrian Somers static __inline int 143944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 144af57ed9fSAtsushi Murai { 145af57ed9fSAtsushi Murai switch (op) { 146af57ed9fSAtsushi Murai case OP_EQ: 1470a4b6c5cSBrian Somers return pport == rport; 148af57ed9fSAtsushi Murai case OP_GT: 1490a4b6c5cSBrian Somers return pport > rport; 150af57ed9fSAtsushi Murai case OP_LT: 1510a4b6c5cSBrian Somers return pport < rport; 152af57ed9fSAtsushi Murai default: 1530a4b6c5cSBrian Somers return 0; 154af57ed9fSAtsushi Murai } 155af57ed9fSAtsushi Murai } 156af57ed9fSAtsushi Murai 157af57ed9fSAtsushi Murai /* 1585d9e6103SBrian Somers * Check a packet against a defined filter 159cad7e742SBrian Somers * Returns 0 to accept the packet, non-zero to drop the packet 160cad7e742SBrian Somers * 161cad7e742SBrian Somers * If filtering is enabled, the initial fragment of a datagram must 162cad7e742SBrian Somers * contain the complete protocol header, and subsequent fragments 163cad7e742SBrian Somers * must not attempt to over-write it. 164af57ed9fSAtsushi Murai */ 165af57ed9fSAtsushi Murai static int 1660a4b6c5cSBrian Somers FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs) 167af57ed9fSAtsushi Murai { 168cad7e742SBrian Somers int gotinfo; /* true if IP payload decoded */ 169cad7e742SBrian Somers int cproto; /* P_* protocol type if (gotinfo) */ 170cad7e742SBrian Somers int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 171cad7e742SBrian Somers u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 172cad7e742SBrian Somers int n; /* filter rule to process */ 173cad7e742SBrian Somers int len; /* bytes used in dbuff */ 174cad7e742SBrian Somers int didname; /* true if filter header printed */ 175cad7e742SBrian Somers int match; /* true if condition matched */ 176cad7e742SBrian Somers const struct filterent *fp = filter->rule; 17706a43ce0SBrian Somers char dbuff[100], dstip[16]; 178af57ed9fSAtsushi Murai 179cad7e742SBrian Somers if (fp->f_action == A_NONE) 1800a4b6c5cSBrian Somers return 0; /* No rule is given. Permit this packet */ 181cad7e742SBrian Somers 1820a4b6c5cSBrian Somers /* 1830a4b6c5cSBrian Somers * Deny any packet fragment that tries to over-write the header. 184cad7e742SBrian Somers * Since we no longer have the real header available, punt on the 185cad7e742SBrian Somers * largest normal header - 20 bytes for TCP without options, rounded 186cad7e742SBrian Somers * up to the next possible fragment boundary. Since the smallest 187cad7e742SBrian Somers * `legal' MTU is 576, and the smallest recommended MTU is 296, any 1880a4b6c5cSBrian Somers * fragmentation within this range is dubious at best 1890a4b6c5cSBrian Somers */ 190cad7e742SBrian Somers len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 191cad7e742SBrian Somers if (len > 0) { /* Not first fragment within datagram */ 19206a43ce0SBrian Somers if (len < (24 >> 3)) { /* don't allow fragment to over-write header */ 19306a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal header\n"); 1940a4b6c5cSBrian Somers return 1; 19506a43ce0SBrian Somers } 196cad7e742SBrian Somers /* permit fragments on in and out filter */ 19706a43ce0SBrian Somers if (!filter->fragok) { 19806a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal fragmentation\n"); 19906a43ce0SBrian Somers return 1; 20006a43ce0SBrian Somers } else 20106a43ce0SBrian Somers return 0; 202cad7e742SBrian Somers } 203cad7e742SBrian Somers 20463f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 205af57ed9fSAtsushi Murai sport = dport = 0; 206cad7e742SBrian Somers for (n = 0; n < MAXFILTERS; ) { 207cad7e742SBrian Somers if (fp->f_action == A_NONE) { 208cad7e742SBrian Somers n++; 209cad7e742SBrian Somers fp++; 210cad7e742SBrian Somers continue; 211cad7e742SBrian Somers } 2125ca5389aSBrian Somers 213cad7e742SBrian Somers if (!didname) { 214dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 2158390b576SBrian Somers didname = 1; 216cad7e742SBrian Somers } 2178390b576SBrian Somers 218cad7e742SBrian Somers match = 0; 219cad7e742SBrian Somers if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 220cad7e742SBrian Somers fp->f_src.mask.s_addr) && 221cad7e742SBrian Somers !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 222cad7e742SBrian Somers fp->f_dst.mask.s_addr)) { 223cad7e742SBrian Somers if (fp->f_proto != P_NONE) { 224af57ed9fSAtsushi Murai if (!gotinfo) { 225cad7e742SBrian Somers const char *ptop = (const char *) pip + (pip->ip_hl << 2); 226cad7e742SBrian Somers const struct tcphdr *th; 227cad7e742SBrian Somers const struct udphdr *uh; 228cad7e742SBrian Somers const struct icmp *ih; 229cad7e742SBrian Somers int datalen; /* IP datagram length */ 230af57ed9fSAtsushi Murai 231cad7e742SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 232af57ed9fSAtsushi Murai switch (pip->ip_p) { 233af57ed9fSAtsushi Murai case IPPROTO_ICMP: 234944f7098SBrian Somers cproto = P_ICMP; 23506a43ce0SBrian Somers if (datalen < 8) { /* ICMP must be at least 8 octets */ 23606a43ce0SBrian Somers log_Printf(LogFILTER, " error: ICMP must be at least 8 octets\n"); 2370a4b6c5cSBrian Somers return 1; 23806a43ce0SBrian Somers } 23906a43ce0SBrian Somers 240cad7e742SBrian Somers ih = (const struct icmp *) ptop; 241944f7098SBrian Somers sport = ih->icmp_type; 24263f98b41SBrian Somers estab = syn = finrst = -1; 243dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 2448390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 245af57ed9fSAtsushi Murai break; 246eee772ecSBrian Somers case IPPROTO_IGMP: 2471f9e5fe5SBrian Somers cproto = P_IGMP; 24806a43ce0SBrian Somers if (datalen < 8) { /* IGMP uses 8-octet messages */ 24906a43ce0SBrian Somers log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n"); 2500a4b6c5cSBrian Somers return 1; 25106a43ce0SBrian Somers } 2521f9e5fe5SBrian Somers estab = syn = finrst = -1; 2531f9e5fe5SBrian Somers sport = ntohs(0); 2541f9e5fe5SBrian Somers break; 25528149effSBrian Somers #ifdef IPPROTO_GRE 25628149effSBrian Somers case IPPROTO_GRE: 25728149effSBrian Somers cproto = P_GRE; 25806a43ce0SBrian Somers if (datalen < 2) { /* GRE uses 2-octet+ messages */ 25906a43ce0SBrian Somers log_Printf(LogFILTER, " error: GRE must be at least 2 octets\n"); 2600a4b6c5cSBrian Somers return 1; 26106a43ce0SBrian Somers } 26228149effSBrian Somers estab = syn = finrst = -1; 26328149effSBrian Somers sport = ntohs(0); 26428149effSBrian Somers break; 26528149effSBrian Somers #endif 26662e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 2672faae814SBrian Somers case IPPROTO_OSPFIGP: 2682faae814SBrian Somers cproto = P_OSPF; 26906a43ce0SBrian Somers if (datalen < 8) { /* IGMP uses 8-octet messages */ 27006a43ce0SBrian Somers log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n"); 2710a4b6c5cSBrian Somers return 1; 27206a43ce0SBrian Somers } 2732faae814SBrian Somers estab = syn = finrst = -1; 2742faae814SBrian Somers sport = ntohs(0); 2752faae814SBrian Somers break; 27662e85934SBrian Somers #endif 2772231246bSBrian Somers case IPPROTO_ESP: 2782231246bSBrian Somers cproto = P_ESP; 2792231246bSBrian Somers estab = syn = finrst = -1; 2802231246bSBrian Somers sport = ntohs(0); 2812231246bSBrian Somers break; 2822231246bSBrian Somers case IPPROTO_AH: 2832231246bSBrian Somers cproto = P_AH; 2842231246bSBrian Somers estab = syn = finrst = -1; 2852231246bSBrian Somers sport = ntohs(0); 2862231246bSBrian Somers break; 287eee772ecSBrian Somers case IPPROTO_IPIP: 288da70ad60SBrian Somers cproto = P_IPIP; 289da70ad60SBrian Somers sport = dport = 0; 290da70ad60SBrian Somers estab = syn = finrst = -1; 291da70ad60SBrian Somers break; 292da70ad60SBrian Somers case IPPROTO_UDP: 293944f7098SBrian Somers cproto = P_UDP; 29406a43ce0SBrian Somers if (datalen < 8) { /* UDP header is 8 octets */ 295da70ad60SBrian Somers log_Printf(LogFILTER, " error: UDP/IPIP" 296da70ad60SBrian Somers " must be at least 8 octets\n"); 2970a4b6c5cSBrian Somers return 1; 29806a43ce0SBrian Somers } 29906a43ce0SBrian Somers 300cad7e742SBrian Somers uh = (const struct udphdr *) ptop; 301944f7098SBrian Somers sport = ntohs(uh->uh_sport); 302944f7098SBrian Somers dport = ntohs(uh->uh_dport); 30363f98b41SBrian Somers estab = syn = finrst = -1; 304dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 3058390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 3068390b576SBrian Somers sport, dport); 307af57ed9fSAtsushi Murai break; 308af57ed9fSAtsushi Murai case IPPROTO_TCP: 309944f7098SBrian Somers cproto = P_TCP; 310cad7e742SBrian Somers th = (const struct tcphdr *) ptop; 311cad7e742SBrian Somers /* TCP headers are variable length. The following code 312cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 313cad7e742SBrian Somers * the datagram is too short 314cad7e742SBrian Somers */ 31506a43ce0SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) { 31606a43ce0SBrian Somers log_Printf(LogFILTER, " error: TCP header incorrect\n"); 3170a4b6c5cSBrian Somers return 1; 31806a43ce0SBrian Somers } 319944f7098SBrian Somers sport = ntohs(th->th_sport); 320944f7098SBrian Somers dport = ntohs(th->th_dport); 321af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 32263f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 32363f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 3242b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 3252b81c773SBrian Somers if (!estab) 3268390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 3278390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 328927145beSBrian Somers th->th_flags, sport, dport); 3292b81c773SBrian Somers else 3302b81c773SBrian Somers *dbuff = '\0'; 3312b81c773SBrian Somers } 332af57ed9fSAtsushi Murai break; 333af57ed9fSAtsushi Murai default: 33406a43ce0SBrian Somers log_Printf(LogFILTER, " error: unknown protocol\n"); 3350a4b6c5cSBrian Somers return 1; /* We'll block unknown type of packet */ 336af57ed9fSAtsushi Murai } 337cad7e742SBrian Somers 338dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 3398390b576SBrian Somers if (estab != -1) { 3408390b576SBrian Somers len = strlen(dbuff); 34163f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 34263f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 34363f98b41SBrian Somers estab, syn, finrst); 344af57ed9fSAtsushi Murai } 345dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 3468390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 3478390b576SBrian Somers } 3488390b576SBrian Somers gotinfo = 1; 3498390b576SBrian Somers } 350dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 351cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 3528390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 353cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 3548390b576SBrian Somers len = strlen(dbuff); 3558390b576SBrian Somers } else 3568390b576SBrian Somers len = 0; 357cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 3588390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 359cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 360cad7e742SBrian Somers fp->f_dstport); 3618390b576SBrian Somers } else if (!len) 3628390b576SBrian Somers *dbuff = '\0'; 3638390b576SBrian Somers 364dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 3658390b576SBrian Somers "check against proto %s%s, action = %s\n", 366cad7e742SBrian Somers n, filter_Proto2Nam(fp->f_proto), 367cad7e742SBrian Somers dbuff, filter_Action2Nam(fp->f_action)); 3688390b576SBrian Somers } 369927145beSBrian Somers 370cad7e742SBrian Somers if (cproto == fp->f_proto) { 371cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 372cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 373cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 374cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 375cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 376cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 377cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 378cad7e742SBrian Somers match = 1; 379af57ed9fSAtsushi Murai } 380af57ed9fSAtsushi Murai } 381af57ed9fSAtsushi Murai } else { 382cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 383dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 384cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 385cad7e742SBrian Somers match = 1; 386af57ed9fSAtsushi Murai } 3878390b576SBrian Somers } else 388dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 389cad7e742SBrian Somers 390cad7e742SBrian Somers if (match != fp->f_invert) { 391cad7e742SBrian Somers /* Take specified action */ 392cad7e742SBrian Somers if (fp->f_action < A_NONE) 393cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 39406a43ce0SBrian Somers else { 3950a4b6c5cSBrian Somers if (fp->f_action == A_PERMIT) { 3960a4b6c5cSBrian Somers if (psecs != NULL) 3970a4b6c5cSBrian Somers *psecs = fp->timeout; 39806a43ce0SBrian Somers if (strcmp(filter->name, "DIAL") == 0) { 39906a43ce0SBrian Somers /* If dial filter then even print out accept packets */ 40006a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 40106a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 40206a43ce0SBrian Somers log_Printf(LogFILTER, "%sbound rule = %d accept %s " 40306a43ce0SBrian Somers "src = %s/%d dst = %s/%d\n", 40406a43ce0SBrian Somers filter->name, n, filter_Proto2Nam(cproto), 40506a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 40606a43ce0SBrian Somers } 40706a43ce0SBrian Somers } 4080a4b6c5cSBrian Somers return 0; 40906a43ce0SBrian Somers } else { 41006a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 41106a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 41206a43ce0SBrian Somers log_Printf(LogFILTER, 41306a43ce0SBrian Somers "%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n", 41406a43ce0SBrian Somers filter->name, n, filter_Proto2Nam(cproto), 41506a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 41606a43ce0SBrian Somers } 4170a4b6c5cSBrian Somers return 1; 41806a43ce0SBrian Somers } /* Explict math. Deny this packet */ 41906a43ce0SBrian Somers } 420cad7e742SBrian Somers } else { 421cad7e742SBrian Somers n++; 422af57ed9fSAtsushi Murai fp++; 423af57ed9fSAtsushi Murai } 424af57ed9fSAtsushi Murai } 42506a43ce0SBrian Somers 42606a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 42706a43ce0SBrian Somers snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst)); 42806a43ce0SBrian Somers log_Printf(LogFILTER, 42906a43ce0SBrian Somers "%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n", 43006a43ce0SBrian Somers filter->name, filter_Proto2Nam(cproto), 43106a43ce0SBrian Somers inet_ntoa(pip->ip_src), sport, dstip, dport); 43206a43ce0SBrian Somers } 43306a43ce0SBrian Somers 4340a4b6c5cSBrian Somers return 1; /* No rule is mached. Deny this packet */ 435af57ed9fSAtsushi Murai } 436af57ed9fSAtsushi Murai 4375ca5389aSBrian Somers #ifdef notdef 438af57ed9fSAtsushi Murai static void 439944f7098SBrian Somers IcmpError(struct ip *pip, int code) 440af57ed9fSAtsushi Murai { 441af57ed9fSAtsushi Murai struct mbuf *bp; 442af57ed9fSAtsushi Murai 443af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 44426af0ae9SBrian Somers bp = m_get(m_len, MB_IPIN); 44526af0ae9SBrian Somers memcpy(MBUF_CTOP(bp), ptr, m_len); 446dd7e2610SBrian Somers vj_SendFrame(bp); 44726af0ae9SBrian Somers ipcp_AddOutOctets(m_len); 4481ae349f5Scvs2svn } 449af57ed9fSAtsushi Murai } 450af57ed9fSAtsushi Murai #endif 451af57ed9fSAtsushi Murai 45252c9ca19SBrian Somers static void 45352c9ca19SBrian Somers ip_LogDNS(const struct udphdr *uh, const char *direction) 45452c9ca19SBrian Somers { 45552c9ca19SBrian Somers struct dns_header header; 45652c9ca19SBrian Somers const u_short *pktptr; 45752c9ca19SBrian Somers const u_char *ptr; 45847fe010cSBrian Somers u_short *hptr, tmp; 45952c9ca19SBrian Somers int len; 46052c9ca19SBrian Somers 46152c9ca19SBrian Somers ptr = (const char *)uh + sizeof *uh; 46252c9ca19SBrian Somers len = ntohs(uh->uh_ulen) - sizeof *uh; 46352c9ca19SBrian Somers if (len < sizeof header + 5) /* rfc1024 */ 46452c9ca19SBrian Somers return; 46552c9ca19SBrian Somers 46652c9ca19SBrian Somers pktptr = (const u_short *)ptr; 46752c9ca19SBrian Somers hptr = (u_short *)&header; 46852c9ca19SBrian Somers ptr += sizeof header; 46952c9ca19SBrian Somers len -= sizeof header; 47052c9ca19SBrian Somers 47152c9ca19SBrian Somers while (pktptr < (const u_short *)ptr) { 47252c9ca19SBrian Somers *hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */ 47352c9ca19SBrian Somers pktptr++; 47452c9ca19SBrian Somers } 47552c9ca19SBrian Somers 47652c9ca19SBrian Somers if (header.opcode == OPCODE_QUERY && header.qr == 0) { 47752c9ca19SBrian Somers /* rfc1035 */ 47826e6a622SBrian Somers char namewithdot[MAXHOSTNAMELEN + 1], *n; 47952c9ca19SBrian Somers const char *qtype, *qclass; 48052c9ca19SBrian Somers const u_char *end; 48152c9ca19SBrian Somers 48226e6a622SBrian Somers n = namewithdot; 48352c9ca19SBrian Somers end = ptr + len - 4; 48426e6a622SBrian Somers if (end - ptr >= sizeof namewithdot) 48526e6a622SBrian Somers end = ptr + sizeof namewithdot - 1; 48652c9ca19SBrian Somers while (ptr < end) { 48752c9ca19SBrian Somers len = *ptr++; 48852c9ca19SBrian Somers if (len > end - ptr) 48952c9ca19SBrian Somers len = end - ptr; 49026e6a622SBrian Somers if (n != namewithdot) 49152c9ca19SBrian Somers *n++ = '.'; 49252c9ca19SBrian Somers memcpy(n, ptr, len); 49352c9ca19SBrian Somers ptr += len; 49452c9ca19SBrian Somers n += len; 49552c9ca19SBrian Somers } 49652c9ca19SBrian Somers *n = '\0'; 49747fe010cSBrian Somers 49847fe010cSBrian Somers if (log_IsKept(LogDNS)) { 49947fe010cSBrian Somers memcpy(&tmp, end, sizeof tmp); 50047fe010cSBrian Somers qtype = dns_Qtype2Txt(ntohs(tmp)); 50147fe010cSBrian Somers memcpy(&tmp, end + 2, sizeof tmp); 50247fe010cSBrian Somers qclass = dns_Qclass2Txt(ntohs(tmp)); 50352c9ca19SBrian Somers 50452c9ca19SBrian Somers log_Printf(LogDNS, "%sbound query %s %s %s\n", 50526e6a622SBrian Somers direction, qclass, qtype, namewithdot); 50652c9ca19SBrian Somers } 50752c9ca19SBrian Somers } 50847fe010cSBrian Somers } 50952c9ca19SBrian Somers 510af57ed9fSAtsushi Murai /* 511af57ed9fSAtsushi Murai * For debugging aid. 512af57ed9fSAtsushi Murai */ 513af57ed9fSAtsushi Murai int 51498251667SBrian Somers PacketCheck(struct bundle *bundle, unsigned char *cp, int nb, 5150a4b6c5cSBrian Somers struct filter *filter, const char *prefix, unsigned *psecs) 516af57ed9fSAtsushi Murai { 51752c9ca19SBrian Somers static const char *const TcpFlags[] = { 51852c9ca19SBrian Somers "FIN", "SYN", "RST", "PSH", "ACK", "URG" 51952c9ca19SBrian Somers }; 520af57ed9fSAtsushi Murai struct ip *pip; 521af57ed9fSAtsushi Murai struct tcphdr *th; 522af57ed9fSAtsushi Murai struct udphdr *uh; 523af57ed9fSAtsushi Murai struct icmp *icmph; 52498251667SBrian Somers unsigned char *ptop; 52552c9ca19SBrian Somers int mask, len, n, pri, logit, loglen, result; 526d93d3a9cSBrian Somers char logbuf[200]; 527af57ed9fSAtsushi Murai 528b565321aSBrian Somers logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) && 529b565321aSBrian Somers (!filter || filter->logok); 53055a8cdeaSBrian Somers loglen = 0; 53152c9ca19SBrian Somers pri = 0; 532af57ed9fSAtsushi Murai 533af57ed9fSAtsushi Murai pip = (struct ip *)cp; 53452c9ca19SBrian Somers uh = NULL; 535af57ed9fSAtsushi Murai 53655a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 53798251667SBrian Somers if (prefix) 53898251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix); 53998251667SBrian Somers else if (filter) 5405ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 541b565321aSBrian Somers else 542b565321aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " "); 54355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 54455a8cdeaSBrian Somers } 545af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 546af57ed9fSAtsushi Murai 547af57ed9fSAtsushi Murai switch (pip->ip_p) { 548af57ed9fSAtsushi Murai case IPPROTO_ICMP: 54955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 55098251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *icmph; 551af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 55255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 55355a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 55455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 55555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 55698251667SBrian Somers "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), icmph->icmp_type, 55798251667SBrian Somers len, nb); 55855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 559af57ed9fSAtsushi Murai } 560af57ed9fSAtsushi Murai break; 561da477886SBrian Somers 562af57ed9fSAtsushi Murai case IPPROTO_UDP: 563af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 5644c240437SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos) 565da477886SBrian Somers pri++; 566da477886SBrian Somers 567da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 568da477886SBrian Somers ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 569da477886SBrian Somers ntohs(uh->uh_dport))) 570da477886SBrian Somers pri++; 571da477886SBrian Somers 572da477886SBrian Somers if (logit && loglen < sizeof logbuf) { 57398251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *uh; 57455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 57555a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 57655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 57755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 57898251667SBrian Somers "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport), 57998251667SBrian Somers len, nb); 58055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 581af57ed9fSAtsushi Murai } 58298251667SBrian Somers 58398251667SBrian Somers if (Enabled(bundle, OPT_FILTERDECAP) && 58498251667SBrian Somers ptop[sizeof *uh] == HDLC_ADDR && ptop[sizeof *uh + 1] == HDLC_UI) { 58598251667SBrian Somers u_short proto; 58698251667SBrian Somers const char *type; 58798251667SBrian Somers 58898251667SBrian Somers memcpy(&proto, ptop + sizeof *uh + 2, sizeof proto); 58998251667SBrian Somers type = NULL; 59098251667SBrian Somers 59198251667SBrian Somers switch (ntohs(proto)) { 59298251667SBrian Somers case PROTO_IP: 59398251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 59498251667SBrian Somers result = PacketCheck(bundle, ptop + sizeof *uh + 4, 59598251667SBrian Somers nb - (ptop - cp) - sizeof *uh - 4, filter, 5960a4b6c5cSBrian Somers logbuf, psecs); 59798251667SBrian Somers if (result != -2) 59898251667SBrian Somers return result; 59998251667SBrian Somers type = "IP"; 60098251667SBrian Somers break; 60198251667SBrian Somers 60298251667SBrian Somers case PROTO_VJUNCOMP: type = "compressed VJ"; break; 60398251667SBrian Somers case PROTO_VJCOMP: type = "uncompressed VJ"; break; 60498251667SBrian Somers case PROTO_MP: type = "Multi-link"; break; 60598251667SBrian Somers case PROTO_ICOMPD: type = "Individual link CCP"; break; 60698251667SBrian Somers case PROTO_COMPD: type = "CCP"; break; 60798251667SBrian Somers case PROTO_IPCP: type = "IPCP"; break; 60898251667SBrian Somers case PROTO_LCP: type = "LCP"; break; 60998251667SBrian Somers case PROTO_PAP: type = "PAP"; break; 61098251667SBrian Somers case PROTO_CBCP: type = "CBCP"; break; 61198251667SBrian Somers case PROTO_LQR: type = "LQR"; break; 61298251667SBrian Somers case PROTO_CHAP: type = "CHAP"; break; 61398251667SBrian Somers } 61498251667SBrian Somers if (type) { 61598251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 61698251667SBrian Somers " - %s data", type); 61798251667SBrian Somers loglen += strlen(logbuf + loglen); 61898251667SBrian Somers } 61998251667SBrian Somers } 62098251667SBrian Somers 621af57ed9fSAtsushi Murai break; 622da477886SBrian Somers 62328149effSBrian Somers #ifdef IPPROTO_GRE 62428149effSBrian Somers case IPPROTO_GRE: 62528149effSBrian Somers if (logit && loglen < sizeof logbuf) { 62698251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2); 62728149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 62828149effSBrian Somers "GRE: %s ---> ", inet_ntoa(pip->ip_src)); 62928149effSBrian Somers loglen += strlen(logbuf + loglen); 63028149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 63198251667SBrian Somers "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb); 63228149effSBrian Somers loglen += strlen(logbuf + loglen); 63328149effSBrian Somers } 63428149effSBrian Somers break; 63528149effSBrian Somers #endif 63628149effSBrian Somers 63762e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 6382faae814SBrian Somers case IPPROTO_OSPFIGP: 6392faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 64098251667SBrian Somers len = ntohs(pip->ip_len) - (pip->ip_hl << 2); 6412faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6422faae814SBrian Somers "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 6432faae814SBrian Somers loglen += strlen(logbuf + loglen); 6442faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 64598251667SBrian Somers "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb); 6462faae814SBrian Somers loglen += strlen(logbuf + loglen); 6472faae814SBrian Somers } 6482faae814SBrian Somers break; 64962e85934SBrian Somers #endif 650da477886SBrian Somers 651eee772ecSBrian Somers case IPPROTO_IPIP: 652eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 653eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 654da70ad60SBrian Somers "IPIP: %s ---> ", inet_ntoa(pip->ip_src)); 655eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 656eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 657da70ad60SBrian Somers "%s", inet_ntoa(pip->ip_dst)); 658eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 659da70ad60SBrian Somers 660da70ad60SBrian Somers if (((struct ip *)ptop)->ip_v == 4) { 661da70ad60SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 662da70ad60SBrian Somers result = PacketCheck(bundle, ptop, nb - (ptop - cp), filter, 663da70ad60SBrian Somers logbuf, psecs); 664da70ad60SBrian Somers if (result != -2) 665da70ad60SBrian Somers return result; 666da70ad60SBrian Somers } 667eee772ecSBrian Somers } 668eee772ecSBrian Somers break; 669da477886SBrian Somers 6702231246bSBrian Somers case IPPROTO_ESP: 6712231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 6722231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6732231246bSBrian Somers "ESP: %s ---> ", inet_ntoa(pip->ip_src)); 6742231246bSBrian Somers loglen += strlen(logbuf + loglen); 67525254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 67625254215SBrian Somers inet_ntoa(pip->ip_dst), ptop); 6772231246bSBrian Somers loglen += strlen(logbuf + loglen); 6782231246bSBrian Somers } 6792231246bSBrian Somers break; 6802231246bSBrian Somers 6812231246bSBrian Somers case IPPROTO_AH: 6822231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 6832231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6842231246bSBrian Somers "AH: %s ---> ", inet_ntoa(pip->ip_src)); 6852231246bSBrian Somers loglen += strlen(logbuf + loglen); 68625254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 68725254215SBrian Somers inet_ntoa(pip->ip_dst), ptop + sizeof(u_int32_t)); 6882231246bSBrian Somers loglen += strlen(logbuf + loglen); 6892231246bSBrian Somers } 6902231246bSBrian Somers break; 6912231246bSBrian Somers 692eee772ecSBrian Somers case IPPROTO_IGMP: 693eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 694eee772ecSBrian Somers uh = (struct udphdr *) ptop; 695eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 6960a4b6c5cSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), 6970a4b6c5cSBrian Somers ntohs(uh->uh_sport)); 698eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 699eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 700eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 701eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 702eee772ecSBrian Somers } 703eee772ecSBrian Somers break; 704da477886SBrian Somers 705af57ed9fSAtsushi Murai case IPPROTO_TCP: 706af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 7074c240437SBrian Somers if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos) 708442f8495SBrian Somers pri++; 709da477886SBrian Somers 710da477886SBrian Somers if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 711da477886SBrian Somers ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 712442f8495SBrian Somers ntohs(th->th_dport))) 713442f8495SBrian Somers pri++; 714442f8495SBrian Somers 71555a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 716af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 71755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 71855a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 71955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 72055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 72155a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 72255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 723af57ed9fSAtsushi Murai n = 0; 724af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 72555a8cdeaSBrian Somers if (th->th_flags & mask) { 72655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 72755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 72855a8cdeaSBrian Somers } 729af57ed9fSAtsushi Murai n++; 730af57ed9fSAtsushi Murai } 73155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 7323a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 7333a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 73455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 735af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 736af57ed9fSAtsushi Murai u_short *sp; 737af57ed9fSAtsushi Murai 738af57ed9fSAtsushi Murai ptop += 20; 739af57ed9fSAtsushi Murai sp = (u_short *) ptop; 74055a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 74155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 74255a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 74355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 74455a8cdeaSBrian Somers } 745af57ed9fSAtsushi Murai } 746af57ed9fSAtsushi Murai } 747af57ed9fSAtsushi Murai break; 74898251667SBrian Somers 74998251667SBrian Somers default: 75098251667SBrian Somers if (prefix) 75198251667SBrian Somers return -2; 752af57ed9fSAtsushi Murai } 75376bd0c0aSDoug Rabson 7540a4b6c5cSBrian Somers if (filter && FilterCheck(pip, filter, psecs)) { 755710e9c29SBrian Somers if (logit) 756dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 7575ca5389aSBrian Somers #ifdef notdef 758944f7098SBrian Somers if (direction == 0) 759944f7098SBrian Somers IcmpError(pip, pri); 7605ca5389aSBrian Somers #endif 76152c9ca19SBrian Somers result = -1; 762af57ed9fSAtsushi Murai } else { 7635ca5389aSBrian Somers /* Check Keep Alive filter */ 76452c9ca19SBrian Somers if (logit && log_IsKept(LogTCPIP)) { 7650a4b6c5cSBrian Somers unsigned alivesecs; 7660a4b6c5cSBrian Somers 7670a4b6c5cSBrian Somers alivesecs = 0; 7680a4b6c5cSBrian Somers if (filter && FilterCheck(pip, &bundle->filter.alive, &alivesecs)) 769dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 7700a4b6c5cSBrian Somers else if (psecs != NULL) { 7710a4b6c5cSBrian Somers if(*psecs == 0) 7720a4b6c5cSBrian Somers *psecs = alivesecs; 7730a4b6c5cSBrian Somers if (*psecs) { 7740a4b6c5cSBrian Somers if (*psecs != alivesecs) 7750a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n", 7760a4b6c5cSBrian Somers logbuf, *psecs, alivesecs); 7771e991daaSBrian Somers else 7780a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs); 7790a4b6c5cSBrian Somers } else 780dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 78153c9f6c0SAtsushi Murai } 7820a4b6c5cSBrian Somers } 78352c9ca19SBrian Somers result = pri; 784af57ed9fSAtsushi Murai } 78552c9ca19SBrian Somers 786b565321aSBrian Somers if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS)) 78752c9ca19SBrian Somers ip_LogDNS(uh, filter->name); 78852c9ca19SBrian Somers 78952c9ca19SBrian Somers return result; 790af57ed9fSAtsushi Murai } 791af57ed9fSAtsushi Murai 7925d9e6103SBrian Somers struct mbuf * 7935d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 7947a6f8720SBrian Somers { 795af57ed9fSAtsushi Murai int nb, nw; 796b6e82f33SBrian Somers struct tun_data tun; 7975d9e6103SBrian Somers struct ip *pip; 7983a7b6d76SBrian Somers char *data; 7990a4b6c5cSBrian Somers unsigned secs, alivesecs; 8005d9e6103SBrian Somers 8015d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 8025d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 80326af0ae9SBrian Somers m_freem(bp); 8045d9e6103SBrian Somers return NULL; 8055d9e6103SBrian Somers } 806af57ed9fSAtsushi Murai 80726af0ae9SBrian Somers m_settype(bp, MB_IPIN); 80826af0ae9SBrian Somers nb = m_length(bp); 80976d98538SBrian Somers if (nb > sizeof tun.data) { 81076d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 81176d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 81226af0ae9SBrian Somers m_freem(bp); 81376d98538SBrian Somers return NULL; 81476d98538SBrian Somers } 8155d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 816af57ed9fSAtsushi Murai 8170a4b6c5cSBrian Somers secs = 0; 8180a4b6c5cSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL, &secs) < 0) 8195d9e6103SBrian Somers return NULL; 8206db75539SBrian Somers 8215d9e6103SBrian Somers pip = (struct ip *)tun.data; 8220a4b6c5cSBrian Somers alivesecs = 0; 8230a4b6c5cSBrian Somers if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) { 8240a4b6c5cSBrian Somers if (secs == 0) 8250a4b6c5cSBrian Somers secs = alivesecs; 8260a4b6c5cSBrian Somers bundle_StartIdleTimer(bundle, secs); 8270a4b6c5cSBrian Somers } 8281e991daaSBrian Somers 8295828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 8301e991daaSBrian Somers 8313a7b6d76SBrian Somers if (bundle->dev.header) { 8320a4b6c5cSBrian Somers tun.header.family = htonl(AF_INET); 83370ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 8343a7b6d76SBrian Somers data = (char *)&tun; 8353a7b6d76SBrian Somers } else 8363a7b6d76SBrian Somers data = tun.data; 8373a7b6d76SBrian Somers 8383a7b6d76SBrian Somers nw = write(bundle->dev.fd, data, nb); 839c4c4aaacSBrian Somers if (nw != nb) { 84057fd05c4SBrian Somers if (nw == -1) 84176d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 84276d98538SBrian Somers l->name, nb, strerror(errno)); 84357fd05c4SBrian Somers else 84476d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 8456db75539SBrian Somers } 8465d9e6103SBrian Somers 8475d9e6103SBrian Somers return NULL; 848af57ed9fSAtsushi Murai } 849af57ed9fSAtsushi Murai 850af57ed9fSAtsushi Murai void 8515a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 852af57ed9fSAtsushi Murai { 853af57ed9fSAtsushi Murai struct mbuf *bp; 854af57ed9fSAtsushi Murai 855442f8495SBrian Somers if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 8565a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 8575a72b6edSBrian Somers else { 8585d9e6103SBrian Somers /* 8595d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 8605d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 86126af0ae9SBrian Somers * m_prepend() in acf_LayerPush() and proto_LayerPush() and 8625d9e6103SBrian Somers * appending in hdlc_LayerPush(). 8635d9e6103SBrian Somers */ 86426af0ae9SBrian Somers bp = m_get(count + 6, MB_IPOUT); 86526af0ae9SBrian Somers bp->m_offset += 4; 86626af0ae9SBrian Somers bp->m_len -= 6; 86775240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 86826af0ae9SBrian Somers m_enqueue(ipcp->Queue + pri, bp); 8695a72b6edSBrian Somers } 870af57ed9fSAtsushi Murai } 871af57ed9fSAtsushi Murai 8726f8e9f0aSBrian Somers void 8735a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 8746f8e9f0aSBrian Somers { 8756f8e9f0aSBrian Somers struct mqueue *queue; 8766f8e9f0aSBrian Somers 877442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 8786f8e9f0aSBrian Somers while (queue->top) 87926af0ae9SBrian Somers m_freem(m_dequeue(queue)); 8806f8e9f0aSBrian Somers } 8816f8e9f0aSBrian Somers 88226af0ae9SBrian Somers size_t 8835a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 88484b8a6ebSAtsushi Murai { 88584b8a6ebSAtsushi Murai struct mqueue *queue; 88626af0ae9SBrian Somers size_t result; 887944f7098SBrian Somers 88826af0ae9SBrian Somers result = 0; 889442f8495SBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 89026af0ae9SBrian Somers result += queue->len; 89184b8a6ebSAtsushi Murai 892f4768038SBrian Somers return result; 8931ae349f5Scvs2svn } 8941ae349f5Scvs2svn 8953b0f8d2eSBrian Somers int 8965d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 897af57ed9fSAtsushi Murai { 8985a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 899af57ed9fSAtsushi Murai struct mqueue *queue; 900af57ed9fSAtsushi Murai struct mbuf *bp; 9015d9e6103SBrian Somers struct ip *pip; 90226af0ae9SBrian Somers int m_len; 9030a4b6c5cSBrian Somers u_int32_t secs = 0; 9040a4b6c5cSBrian Somers unsigned alivesecs = 0; 905af57ed9fSAtsushi Murai 9065a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 9073b0f8d2eSBrian Somers return 0; 9081e991daaSBrian Somers 909442f8495SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 910442f8495SBrian Somers do { 911af57ed9fSAtsushi Murai if (queue->top) { 9120a4b6c5cSBrian Somers bp = m_dequeue(queue); 9130a4b6c5cSBrian Somers bp = mbuf_Read(bp, &secs, sizeof secs); 9140a4b6c5cSBrian Somers bp = m_pullup(bp); 91526af0ae9SBrian Somers m_len = m_length(bp); 9165d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 9170a4b6c5cSBrian Somers if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) { 9180a4b6c5cSBrian Somers if (secs == 0) 9190a4b6c5cSBrian Somers secs = alivesecs; 9200a4b6c5cSBrian Somers bundle_StartIdleTimer(bundle, secs); 9210a4b6c5cSBrian Somers } 922442f8495SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 92326af0ae9SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 9243b0f8d2eSBrian Somers return 1; 925af57ed9fSAtsushi Murai } 926442f8495SBrian Somers } while (queue-- != ipcp->Queue); 9271e991daaSBrian Somers 9283b0f8d2eSBrian Somers return 0; 929af57ed9fSAtsushi Murai } 930