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> 3630949fd4SBrian Somers #ifndef NOINET6 3730949fd4SBrian Somers #include <netinet/icmp6.h> 3830949fd4SBrian Somers #include <netinet/ip6.h> 3930949fd4SBrian Somers #endif 40af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h> 41af57ed9fSAtsushi Murai #include <netinet/udp.h> 42af57ed9fSAtsushi Murai #include <netinet/tcp.h> 43ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 441fa665f5SBrian Somers #include <sys/un.h> 4575240ed1SBrian Somers 4657fd05c4SBrian Somers #include <errno.h> 4730949fd4SBrian Somers #include <netdb.h> 4875240ed1SBrian Somers #include <stdio.h> 4930949fd4SBrian Somers #include <stdlib.h> 5075240ed1SBrian Somers #include <string.h> 515d9e6103SBrian Somers #include <termios.h> 5275240ed1SBrian Somers #include <unistd.h> 5375240ed1SBrian Somers 545d9e6103SBrian Somers #include "layer.h" 555d9e6103SBrian Somers #include "proto.h" 56927145beSBrian Somers #include "mbuf.h" 57927145beSBrian Somers #include "log.h" 5875240ed1SBrian Somers #include "defs.h" 5975240ed1SBrian Somers #include "timer.h" 6075240ed1SBrian Somers #include "fsm.h" 61879ed6faSBrian Somers #include "lqr.h" 6275240ed1SBrian Somers #include "hdlc.h" 635828db6dSBrian Somers #include "throughput.h" 645828db6dSBrian Somers #include "iplist.h" 65eaa4df37SBrian Somers #include "slcompress.h" 6630949fd4SBrian Somers #include "ncpaddr.h" 6730949fd4SBrian Somers #include "ip.h" 6875240ed1SBrian Somers #include "ipcp.h" 691ae349f5Scvs2svn #include "filter.h" 702f786681SBrian Somers #include "descriptor.h" 7175240ed1SBrian Somers #include "lcp.h" 723b0f8d2eSBrian Somers #include "ccp.h" 733b0f8d2eSBrian Somers #include "link.h" 743b0f8d2eSBrian Somers #include "mp.h" 75972a1bcfSBrian Somers #ifndef NORADIUS 76972a1bcfSBrian Somers #include "radius.h" 77972a1bcfSBrian Somers #endif 7830949fd4SBrian Somers #include "ipv6cp.h" 7930949fd4SBrian Somers #include "ncp.h" 807a6f8720SBrian Somers #include "bundle.h" 816a6b4bbbSBrian Somers #include "tun.h" 82af57ed9fSAtsushi Murai 8352c9ca19SBrian Somers 8452c9ca19SBrian Somers #define OPCODE_QUERY 0 8552c9ca19SBrian Somers #define OPCODE_IQUERY 1 8652c9ca19SBrian Somers #define OPCODE_STATUS 2 8752c9ca19SBrian Somers 8852c9ca19SBrian Somers struct dns_header { 8952c9ca19SBrian Somers u_short id; 9052c9ca19SBrian Somers unsigned qr : 1; 9152c9ca19SBrian Somers unsigned opcode : 4; 9252c9ca19SBrian Somers unsigned aa : 1; 9352c9ca19SBrian Somers unsigned tc : 1; 9452c9ca19SBrian Somers unsigned rd : 1; 9552c9ca19SBrian Somers unsigned ra : 1; 9652c9ca19SBrian Somers unsigned z : 3; 9752c9ca19SBrian Somers unsigned rcode : 4; 9852c9ca19SBrian Somers u_short qdcount; 9952c9ca19SBrian Somers u_short ancount; 10052c9ca19SBrian Somers u_short nscount; 10152c9ca19SBrian Somers u_short arcount; 102182c898aSBrian Somers }; 103af57ed9fSAtsushi Murai 10452c9ca19SBrian Somers static const char * 10552c9ca19SBrian Somers dns_Qclass2Txt(u_short qclass) 10652c9ca19SBrian Somers { 10752c9ca19SBrian Somers static char failure[6]; 10852c9ca19SBrian Somers struct { 10952c9ca19SBrian Somers u_short id; 11052c9ca19SBrian Somers const char *txt; 11152c9ca19SBrian Somers } qtxt[] = { 11252c9ca19SBrian Somers /* rfc1035 */ 11352c9ca19SBrian Somers { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" } 11452c9ca19SBrian Somers }; 11552c9ca19SBrian Somers int f; 11652c9ca19SBrian Somers 11752c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 11852c9ca19SBrian Somers if (qtxt[f].id == qclass) 11952c9ca19SBrian Somers return qtxt[f].txt; 12052c9ca19SBrian Somers 121d6d3eeabSBrian Somers return HexStr(qclass, failure, sizeof failure); 12252c9ca19SBrian Somers } 12352c9ca19SBrian Somers 12452c9ca19SBrian Somers static const char * 12552c9ca19SBrian Somers dns_Qtype2Txt(u_short qtype) 12652c9ca19SBrian Somers { 12752c9ca19SBrian Somers static char failure[6]; 12852c9ca19SBrian Somers struct { 12952c9ca19SBrian Somers u_short id; 13052c9ca19SBrian Somers const char *txt; 13152c9ca19SBrian Somers } qtxt[] = { 13252c9ca19SBrian Somers /* rfc1035/rfc1700 */ 13352c9ca19SBrian Somers { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" }, 13452c9ca19SBrian Somers { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" }, 13552c9ca19SBrian Somers { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" }, 13652c9ca19SBrian Somers { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" }, 13752c9ca19SBrian Somers { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" }, 13852c9ca19SBrian Somers { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" }, 13952c9ca19SBrian Somers { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" }, 14052c9ca19SBrian Somers { 254, "MAILA" }, { 255, "*" } 14152c9ca19SBrian Somers }; 14252c9ca19SBrian Somers int f; 14352c9ca19SBrian Somers 14452c9ca19SBrian Somers for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 14552c9ca19SBrian Somers if (qtxt[f].id == qtype) 14652c9ca19SBrian Somers return qtxt[f].txt; 14752c9ca19SBrian Somers 148d6d3eeabSBrian Somers return HexStr(qtype, failure, sizeof failure); 14952c9ca19SBrian Somers } 15052c9ca19SBrian Somers 151cad7e742SBrian Somers static __inline int 152944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 153af57ed9fSAtsushi Murai { 154af57ed9fSAtsushi Murai switch (op) { 155af57ed9fSAtsushi Murai case OP_EQ: 1560a4b6c5cSBrian Somers return pport == rport; 157af57ed9fSAtsushi Murai case OP_GT: 1580a4b6c5cSBrian Somers return pport > rport; 159af57ed9fSAtsushi Murai case OP_LT: 1600a4b6c5cSBrian Somers return pport < rport; 161af57ed9fSAtsushi Murai default: 1620a4b6c5cSBrian Somers return 0; 163af57ed9fSAtsushi Murai } 164af57ed9fSAtsushi Murai } 165af57ed9fSAtsushi Murai 166af57ed9fSAtsushi Murai /* 16730949fd4SBrian Somers * Check a packet against the given filter 16830949fd4SBrian Somers * Returns 0 to accept the packet, non-zero to drop the packet. 16930949fd4SBrian Somers * If psecs is not NULL, populate it with the timeout associated 17030949fd4SBrian Somers * with the filter rule matched. 171cad7e742SBrian Somers * 172cad7e742SBrian Somers * If filtering is enabled, the initial fragment of a datagram must 173cad7e742SBrian Somers * contain the complete protocol header, and subsequent fragments 174cad7e742SBrian Somers * must not attempt to over-write it. 17530949fd4SBrian Somers * 17630949fd4SBrian Somers * One (and only one) of pip or pip6 must be set. 177af57ed9fSAtsushi Murai */ 17830949fd4SBrian Somers int 17930949fd4SBrian Somers FilterCheck(const unsigned char *packet, u_int32_t family, 18030949fd4SBrian Somers const struct filter *filter, unsigned *psecs) 181af57ed9fSAtsushi Murai { 182cad7e742SBrian Somers int gotinfo; /* true if IP payload decoded */ 18330949fd4SBrian Somers int cproto; /* IPPROTO_* protocol number if (gotinfo) */ 184cad7e742SBrian Somers int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 185cad7e742SBrian Somers u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 186cad7e742SBrian Somers int n; /* filter rule to process */ 187cad7e742SBrian Somers int len; /* bytes used in dbuff */ 188cad7e742SBrian Somers int didname; /* true if filter header printed */ 189cad7e742SBrian Somers int match; /* true if condition matched */ 19030949fd4SBrian Somers int mindata; /* minimum data size or zero */ 191cad7e742SBrian Somers const struct filterent *fp = filter->rule; 19230949fd4SBrian Somers char dbuff[100], dstip[16], prototxt[16]; 19330949fd4SBrian Somers struct protoent *pe; 19430949fd4SBrian Somers struct ncpaddr srcaddr, dstaddr; 19530949fd4SBrian Somers const char *payload; /* IP payload */ 19630949fd4SBrian Somers int datalen; /* IP datagram length */ 197af57ed9fSAtsushi Murai 198cad7e742SBrian Somers if (fp->f_action == A_NONE) 1990a4b6c5cSBrian Somers return 0; /* No rule is given. Permit this packet */ 200cad7e742SBrian Somers 20130949fd4SBrian Somers #ifndef NOINET6 20230949fd4SBrian Somers if (family == AF_INET6) { 20330949fd4SBrian Somers const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet; 20430949fd4SBrian Somers 20530949fd4SBrian Somers ncpaddr_setip6(&srcaddr, &pip6->ip6_src); 20630949fd4SBrian Somers ncpaddr_setip6(&dstaddr, &pip6->ip6_dst); 2076de54bbeSBrian Somers datalen = ntohs(pip6->ip6_plen); 2086de54bbeSBrian Somers payload = packet + sizeof *pip6; 20930949fd4SBrian Somers cproto = pip6->ip6_nxt; 21030949fd4SBrian Somers } else 21130949fd4SBrian Somers #endif 21230949fd4SBrian Somers { 2130a4b6c5cSBrian Somers /* 2140a4b6c5cSBrian Somers * Deny any packet fragment that tries to over-write the header. 215cad7e742SBrian Somers * Since we no longer have the real header available, punt on the 216cad7e742SBrian Somers * largest normal header - 20 bytes for TCP without options, rounded 217cad7e742SBrian Somers * up to the next possible fragment boundary. Since the smallest 218cad7e742SBrian Somers * `legal' MTU is 576, and the smallest recommended MTU is 296, any 2190a4b6c5cSBrian Somers * fragmentation within this range is dubious at best 2200a4b6c5cSBrian Somers */ 22130949fd4SBrian Somers const struct ip *pip = (const struct ip *)packet; 22230949fd4SBrian Somers 223cad7e742SBrian Somers len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 224cad7e742SBrian Somers if (len > 0) { /* Not first fragment within datagram */ 22506a43ce0SBrian Somers if (len < (24 >> 3)) { /* don't allow fragment to over-write header */ 22606a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal header\n"); 2270a4b6c5cSBrian Somers return 1; 22806a43ce0SBrian Somers } 229cad7e742SBrian Somers /* permit fragments on in and out filter */ 23006a43ce0SBrian Somers if (!filter->fragok) { 23106a43ce0SBrian Somers log_Printf(LogFILTER, " error: illegal fragmentation\n"); 23206a43ce0SBrian Somers return 1; 23306a43ce0SBrian Somers } else 23406a43ce0SBrian Somers return 0; 235cad7e742SBrian Somers } 236cad7e742SBrian Somers 23730949fd4SBrian Somers ncpaddr_setip4(&srcaddr, pip->ip_src); 23830949fd4SBrian Somers ncpaddr_setip4(&dstaddr, pip->ip_dst); 23930949fd4SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 24030949fd4SBrian Somers payload = packet + (pip->ip_hl << 2); 24130949fd4SBrian Somers cproto = pip->ip_p; 24230949fd4SBrian Somers } 24330949fd4SBrian Somers 24430949fd4SBrian Somers if ((pe = getprotobynumber(cproto)) == NULL) 24530949fd4SBrian Somers snprintf(prototxt, sizeof prototxt, "%d", cproto); 24630949fd4SBrian Somers else 24730949fd4SBrian Somers snprintf(prototxt, sizeof prototxt, "%s", pe->p_name); 24830949fd4SBrian Somers gotinfo = estab = syn = finrst = didname = 0; 249af57ed9fSAtsushi Murai sport = dport = 0; 25030949fd4SBrian Somers 251cad7e742SBrian Somers for (n = 0; n < MAXFILTERS; ) { 252cad7e742SBrian Somers if (fp->f_action == A_NONE) { 253cad7e742SBrian Somers n++; 254cad7e742SBrian Somers fp++; 255cad7e742SBrian Somers continue; 256cad7e742SBrian Somers } 2575ca5389aSBrian Somers 258cad7e742SBrian Somers if (!didname) { 259dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 2608390b576SBrian Somers didname = 1; 261cad7e742SBrian Somers } 2628390b576SBrian Somers 263cad7e742SBrian Somers match = 0; 26430949fd4SBrian Somers 26530949fd4SBrian Somers if ((ncprange_family(&fp->f_src) == AF_UNSPEC || 26630949fd4SBrian Somers ncprange_contains(&fp->f_src, &srcaddr)) && 26730949fd4SBrian Somers (ncprange_family(&fp->f_dst) == AF_UNSPEC || 26830949fd4SBrian Somers ncprange_contains(&fp->f_dst, &dstaddr))) { 26930949fd4SBrian Somers if (fp->f_proto != 0) { 270af57ed9fSAtsushi Murai if (!gotinfo) { 271cad7e742SBrian Somers const struct tcphdr *th; 272cad7e742SBrian Somers const struct udphdr *uh; 273cad7e742SBrian Somers const struct icmp *ih; 27430949fd4SBrian Somers #ifndef NOINET6 27530949fd4SBrian Somers const struct icmp6_hdr *ih6; 27630949fd4SBrian Somers #endif 27730949fd4SBrian Somers mindata = 0; 27830949fd4SBrian Somers sport = dport = 0; 27963f98b41SBrian Somers estab = syn = finrst = -1; 28030949fd4SBrian Somers 28130949fd4SBrian Somers switch (cproto) { 28230949fd4SBrian Somers case IPPROTO_ICMP: 28330949fd4SBrian Somers mindata = 8; /* ICMP must be at least 8 octets */ 28430949fd4SBrian Somers ih = (const struct icmp *)payload; 28530949fd4SBrian Somers sport = ntohs(ih->icmp_type); 286dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 2878390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 288af57ed9fSAtsushi Murai break; 28930949fd4SBrian Somers 29030949fd4SBrian Somers #ifndef NOINET6 29130949fd4SBrian Somers case IPPROTO_ICMPV6: 29230949fd4SBrian Somers mindata = 8; /* ICMP must be at least 8 octets */ 29330949fd4SBrian Somers ih6 = (const struct icmp6_hdr *)payload; 29430949fd4SBrian Somers sport = ntohs(ih6->icmp6_type); 29530949fd4SBrian Somers if (log_IsKept(LogDEBUG)) 29630949fd4SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 2971f9e5fe5SBrian Somers break; 29830949fd4SBrian Somers #endif 29930949fd4SBrian Somers 30030949fd4SBrian Somers case IPPROTO_IGMP: 30130949fd4SBrian Somers mindata = 8; /* IGMP uses 8-octet messages */ 30230949fd4SBrian Somers break; 30330949fd4SBrian Somers 30428149effSBrian Somers #ifdef IPPROTO_GRE 30528149effSBrian Somers case IPPROTO_GRE: 30630949fd4SBrian Somers mindata = 2; /* GRE uses 2-octet+ messages */ 30728149effSBrian Somers break; 30828149effSBrian Somers #endif 30962e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 3102faae814SBrian Somers case IPPROTO_OSPFIGP: 31130949fd4SBrian Somers mindata = 8; /* IGMP uses 8-octet messages */ 3122faae814SBrian Somers break; 31362e85934SBrian Somers #endif 31430949fd4SBrian Somers #ifndef NOINET6 31530949fd4SBrian Somers case IPPROTO_IPV6: 31630949fd4SBrian Somers mindata = 20; /* RFC2893 Section 3.5: 5 * 32bit words */ 3172231246bSBrian Somers break; 31830949fd4SBrian Somers #endif 31906a43ce0SBrian Somers 32030949fd4SBrian Somers case IPPROTO_UDP: 32130949fd4SBrian Somers mindata = 8; /* UDP header is 8 octets */ 32230949fd4SBrian Somers uh = (const struct udphdr *)payload; 323944f7098SBrian Somers sport = ntohs(uh->uh_sport); 324944f7098SBrian Somers dport = ntohs(uh->uh_dport); 325dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 3268390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 3278390b576SBrian Somers sport, dport); 328af57ed9fSAtsushi Murai break; 32930949fd4SBrian Somers 330af57ed9fSAtsushi Murai case IPPROTO_TCP: 33130949fd4SBrian Somers th = (const struct tcphdr *)payload; 33230949fd4SBrian Somers /* 33330949fd4SBrian Somers * TCP headers are variable length. The following code 334cad7e742SBrian Somers * ensures that the TCP header length isn't de-referenced if 335cad7e742SBrian Somers * the datagram is too short 336cad7e742SBrian Somers */ 33706a43ce0SBrian Somers if (datalen < 20 || datalen < (th->th_off << 2)) { 33806a43ce0SBrian Somers log_Printf(LogFILTER, " error: TCP header incorrect\n"); 3390a4b6c5cSBrian Somers return 1; 34006a43ce0SBrian Somers } 341944f7098SBrian Somers sport = ntohs(th->th_sport); 342944f7098SBrian Somers dport = ntohs(th->th_dport); 343af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 34463f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 34563f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 3462b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 3472b81c773SBrian Somers if (!estab) 3488390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 3498390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 350927145beSBrian Somers th->th_flags, sport, dport); 3512b81c773SBrian Somers else 3522b81c773SBrian Somers *dbuff = '\0'; 3532b81c773SBrian Somers } 354af57ed9fSAtsushi Murai break; 355af57ed9fSAtsushi Murai default: 35630949fd4SBrian Somers break; 35730949fd4SBrian Somers } 35830949fd4SBrian Somers 35930949fd4SBrian Somers if (datalen < mindata) { 36030949fd4SBrian Somers log_Printf(LogFILTER, " error: proto %s must be at least" 36130949fd4SBrian Somers " %d octets\n", prototxt, mindata); 36230949fd4SBrian Somers return 1; 363af57ed9fSAtsushi Murai } 364cad7e742SBrian Somers 365dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 3668390b576SBrian Somers if (estab != -1) { 3678390b576SBrian Somers len = strlen(dbuff); 36863f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 36963f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 37063f98b41SBrian Somers estab, syn, finrst); 371af57ed9fSAtsushi Murai } 37230949fd4SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", prototxt, dbuff); 3738390b576SBrian Somers } 3748390b576SBrian Somers gotinfo = 1; 3758390b576SBrian Somers } 37630949fd4SBrian Somers 377dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 378cad7e742SBrian Somers if (fp->f_srcop != OP_NONE) { 3798390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 380cad7e742SBrian Somers filter_Op2Nam(fp->f_srcop), fp->f_srcport); 3818390b576SBrian Somers len = strlen(dbuff); 3828390b576SBrian Somers } else 3838390b576SBrian Somers len = 0; 384cad7e742SBrian Somers if (fp->f_dstop != OP_NONE) { 3858390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 386cad7e742SBrian Somers ", dst %s %d", filter_Op2Nam(fp->f_dstop), 387cad7e742SBrian Somers fp->f_dstport); 3888390b576SBrian Somers } else if (!len) 3898390b576SBrian Somers *dbuff = '\0'; 3908390b576SBrian Somers 391dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 39230949fd4SBrian Somers "check against proto %d%s, action = %s\n", 39330949fd4SBrian Somers n, fp->f_proto, dbuff, filter_Action2Nam(fp->f_action)); 3948390b576SBrian Somers } 395927145beSBrian Somers 396cad7e742SBrian Somers if (cproto == fp->f_proto) { 397cad7e742SBrian Somers if ((fp->f_srcop == OP_NONE || 398cad7e742SBrian Somers PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 399cad7e742SBrian Somers (fp->f_dstop == OP_NONE || 400cad7e742SBrian Somers PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 401cad7e742SBrian Somers (fp->f_estab == 0 || estab) && 402cad7e742SBrian Somers (fp->f_syn == 0 || syn) && 403cad7e742SBrian Somers (fp->f_finrst == 0 || finrst)) { 404cad7e742SBrian Somers match = 1; 405af57ed9fSAtsushi Murai } 406af57ed9fSAtsushi Murai } 407af57ed9fSAtsushi Murai } else { 408cad7e742SBrian Somers /* Address is matched and no protocol specified. Make a decision. */ 409dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 410cad7e742SBrian Somers filter_Action2Nam(fp->f_action)); 411cad7e742SBrian Somers match = 1; 412af57ed9fSAtsushi Murai } 4138390b576SBrian Somers } else 414dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 415cad7e742SBrian Somers 416cad7e742SBrian Somers if (match != fp->f_invert) { 417cad7e742SBrian Somers /* Take specified action */ 418cad7e742SBrian Somers if (fp->f_action < A_NONE) 419cad7e742SBrian Somers fp = &filter->rule[n = fp->f_action]; 42006a43ce0SBrian Somers else { 4210a4b6c5cSBrian Somers if (fp->f_action == A_PERMIT) { 4220a4b6c5cSBrian Somers if (psecs != NULL) 4230a4b6c5cSBrian Somers *psecs = fp->timeout; 42406a43ce0SBrian Somers if (strcmp(filter->name, "DIAL") == 0) { 42506a43ce0SBrian Somers /* If dial filter then even print out accept packets */ 42606a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 42730949fd4SBrian Somers snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr)); 42806a43ce0SBrian Somers log_Printf(LogFILTER, "%sbound rule = %d accept %s " 42930949fd4SBrian Somers "src = %s:%d dst = %s:%d\n", filter->name, n, prototxt, 43030949fd4SBrian Somers ncpaddr_ntoa(&srcaddr), sport, dstip, dport); 43106a43ce0SBrian Somers } 43206a43ce0SBrian Somers } 4330a4b6c5cSBrian Somers return 0; 43406a43ce0SBrian Somers } else { 43506a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 43630949fd4SBrian Somers snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr)); 43706a43ce0SBrian Somers log_Printf(LogFILTER, 43806a43ce0SBrian Somers "%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n", 43930949fd4SBrian Somers filter->name, n, prototxt, 44030949fd4SBrian Somers ncpaddr_ntoa(&srcaddr), sport, dstip, dport); 44106a43ce0SBrian Somers } 4420a4b6c5cSBrian Somers return 1; 44330949fd4SBrian Somers } /* Explict match. Deny this packet */ 44406a43ce0SBrian Somers } 445cad7e742SBrian Somers } else { 446cad7e742SBrian Somers n++; 447af57ed9fSAtsushi Murai fp++; 448af57ed9fSAtsushi Murai } 449af57ed9fSAtsushi Murai } 45006a43ce0SBrian Somers 45106a43ce0SBrian Somers if (log_IsKept(LogFILTER)) { 45230949fd4SBrian Somers snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr)); 45306a43ce0SBrian Somers log_Printf(LogFILTER, 45406a43ce0SBrian Somers "%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n", 45530949fd4SBrian Somers filter->name, prototxt, ncpaddr_ntoa(&srcaddr), sport, 45630949fd4SBrian Somers dstip, dport); 45706a43ce0SBrian Somers } 45806a43ce0SBrian Somers 45930949fd4SBrian Somers return 1; /* No rule matched, deny this packet */ 460af57ed9fSAtsushi Murai } 461af57ed9fSAtsushi Murai 46252c9ca19SBrian Somers static void 46352c9ca19SBrian Somers ip_LogDNS(const struct udphdr *uh, const char *direction) 46452c9ca19SBrian Somers { 46552c9ca19SBrian Somers struct dns_header header; 46652c9ca19SBrian Somers const u_short *pktptr; 46752c9ca19SBrian Somers const u_char *ptr; 46847fe010cSBrian Somers u_short *hptr, tmp; 46952c9ca19SBrian Somers int len; 47052c9ca19SBrian Somers 47152c9ca19SBrian Somers ptr = (const char *)uh + sizeof *uh; 47252c9ca19SBrian Somers len = ntohs(uh->uh_ulen) - sizeof *uh; 47352c9ca19SBrian Somers if (len < sizeof header + 5) /* rfc1024 */ 47452c9ca19SBrian Somers return; 47552c9ca19SBrian Somers 47652c9ca19SBrian Somers pktptr = (const u_short *)ptr; 47752c9ca19SBrian Somers hptr = (u_short *)&header; 47852c9ca19SBrian Somers ptr += sizeof header; 47952c9ca19SBrian Somers len -= sizeof header; 48052c9ca19SBrian Somers 48152c9ca19SBrian Somers while (pktptr < (const u_short *)ptr) { 48252c9ca19SBrian Somers *hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */ 48352c9ca19SBrian Somers pktptr++; 48452c9ca19SBrian Somers } 48552c9ca19SBrian Somers 48652c9ca19SBrian Somers if (header.opcode == OPCODE_QUERY && header.qr == 0) { 48752c9ca19SBrian Somers /* rfc1035 */ 48826e6a622SBrian Somers char namewithdot[MAXHOSTNAMELEN + 1], *n; 48952c9ca19SBrian Somers const char *qtype, *qclass; 49052c9ca19SBrian Somers const u_char *end; 49152c9ca19SBrian Somers 49226e6a622SBrian Somers n = namewithdot; 49352c9ca19SBrian Somers end = ptr + len - 4; 49426e6a622SBrian Somers if (end - ptr >= sizeof namewithdot) 49526e6a622SBrian Somers end = ptr + sizeof namewithdot - 1; 49652c9ca19SBrian Somers while (ptr < end) { 49752c9ca19SBrian Somers len = *ptr++; 49852c9ca19SBrian Somers if (len > end - ptr) 49952c9ca19SBrian Somers len = end - ptr; 50026e6a622SBrian Somers if (n != namewithdot) 50152c9ca19SBrian Somers *n++ = '.'; 50252c9ca19SBrian Somers memcpy(n, ptr, len); 50352c9ca19SBrian Somers ptr += len; 50452c9ca19SBrian Somers n += len; 50552c9ca19SBrian Somers } 50652c9ca19SBrian Somers *n = '\0'; 50747fe010cSBrian Somers 50847fe010cSBrian Somers if (log_IsKept(LogDNS)) { 50947fe010cSBrian Somers memcpy(&tmp, end, sizeof tmp); 51047fe010cSBrian Somers qtype = dns_Qtype2Txt(ntohs(tmp)); 51147fe010cSBrian Somers memcpy(&tmp, end + 2, sizeof tmp); 51247fe010cSBrian Somers qclass = dns_Qclass2Txt(ntohs(tmp)); 51352c9ca19SBrian Somers 51452c9ca19SBrian Somers log_Printf(LogDNS, "%sbound query %s %s %s\n", 51526e6a622SBrian Somers direction, qclass, qtype, namewithdot); 51652c9ca19SBrian Somers } 51752c9ca19SBrian Somers } 51847fe010cSBrian Somers } 51952c9ca19SBrian Somers 520af57ed9fSAtsushi Murai /* 52130949fd4SBrian Somers * Check if the given packet matches the given filter. 52230949fd4SBrian Somers * One of pip or pip6 must be set. 523af57ed9fSAtsushi Murai */ 524af57ed9fSAtsushi Murai int 52530949fd4SBrian Somers PacketCheck(struct bundle *bundle, u_int32_t family, 52630949fd4SBrian Somers const unsigned char *packet, int nb, struct filter *filter, 52730949fd4SBrian Somers const char *prefix, unsigned *psecs) 528af57ed9fSAtsushi Murai { 52952c9ca19SBrian Somers static const char *const TcpFlags[] = { 53052c9ca19SBrian Somers "FIN", "SYN", "RST", "PSH", "ACK", "URG" 53152c9ca19SBrian Somers }; 53230949fd4SBrian Somers const struct tcphdr *th; 53330949fd4SBrian Somers const struct udphdr *uh; 53430949fd4SBrian Somers const struct icmp *icmph; 53530949fd4SBrian Somers #ifndef NOINET6 53630949fd4SBrian Somers const struct icmp6_hdr *icmp6h; 53730949fd4SBrian Somers #endif 53830949fd4SBrian Somers const unsigned char *payload; 53930949fd4SBrian Somers struct ncpaddr srcaddr, dstaddr; 54030949fd4SBrian Somers int cproto, mask, len, n, pri, logit, loglen, result; 541d93d3a9cSBrian Somers char logbuf[200]; 54230949fd4SBrian Somers int datalen, frag; 54330949fd4SBrian Somers u_char tos; 544af57ed9fSAtsushi Murai 545b565321aSBrian Somers logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) && 546b565321aSBrian Somers (!filter || filter->logok); 54755a8cdeaSBrian Somers loglen = 0; 54852c9ca19SBrian Somers pri = 0; 549af57ed9fSAtsushi Murai 55030949fd4SBrian Somers #ifndef NOINET6 55130949fd4SBrian Somers if (family == AF_INET6) { 55230949fd4SBrian Somers const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet; 55330949fd4SBrian Somers 55430949fd4SBrian Somers ncpaddr_setip6(&srcaddr, &pip6->ip6_src); 55530949fd4SBrian Somers ncpaddr_setip6(&dstaddr, &pip6->ip6_dst); 55630949fd4SBrian Somers datalen = ntohs(pip6->ip6_plen); 55730949fd4SBrian Somers payload = packet + sizeof *pip6; 55830949fd4SBrian Somers cproto = pip6->ip6_nxt; 5596de54bbeSBrian Somers tos = 0; /* XXX: pip6->ip6_vfc >> 4 ? */ 56030949fd4SBrian Somers frag = 0; /* XXX: ??? */ 56130949fd4SBrian Somers } else 56230949fd4SBrian Somers #endif 56330949fd4SBrian Somers { 56430949fd4SBrian Somers const struct ip *pip = (const struct ip *)packet; 56530949fd4SBrian Somers 56630949fd4SBrian Somers ncpaddr_setip4(&srcaddr, pip->ip_src); 56730949fd4SBrian Somers ncpaddr_setip4(&dstaddr, pip->ip_dst); 56830949fd4SBrian Somers datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 56930949fd4SBrian Somers payload = packet + (pip->ip_hl << 2); 57030949fd4SBrian Somers cproto = pip->ip_p; 57130949fd4SBrian Somers tos = pip->ip_tos; 57230949fd4SBrian Somers frag = ntohs(pip->ip_off) & IP_OFFMASK; 57330949fd4SBrian Somers } 57430949fd4SBrian Somers 57552c9ca19SBrian Somers uh = NULL; 576af57ed9fSAtsushi Murai 57755a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 57898251667SBrian Somers if (prefix) 57998251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix); 58098251667SBrian Somers else if (filter) 5815ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 582b565321aSBrian Somers else 583b565321aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " "); 58455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 58555a8cdeaSBrian Somers } 586af57ed9fSAtsushi Murai 58730949fd4SBrian Somers switch (cproto) { 588af57ed9fSAtsushi Murai case IPPROTO_ICMP: 58955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 59030949fd4SBrian Somers len = datalen - sizeof *icmph; 59130949fd4SBrian Somers icmph = (const struct icmp *)payload; 59255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 59330949fd4SBrian Somers "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmph->icmp_type); 59455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 59555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 59630949fd4SBrian Somers "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb); 59755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 598af57ed9fSAtsushi Murai } 599af57ed9fSAtsushi Murai break; 600da477886SBrian Somers 60130949fd4SBrian Somers #ifndef NOINET6 60230949fd4SBrian Somers case IPPROTO_ICMPV6: 60330949fd4SBrian Somers if (logit && loglen < sizeof logbuf) { 60430949fd4SBrian Somers len = datalen - sizeof *icmp6h; 60530949fd4SBrian Somers icmp6h = (const struct icmp6_hdr *)payload; 60630949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 60730949fd4SBrian Somers "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmp6h->icmp6_type); 60830949fd4SBrian Somers loglen += strlen(logbuf + loglen); 60930949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 61030949fd4SBrian Somers "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb); 61130949fd4SBrian Somers loglen += strlen(logbuf + loglen); 61230949fd4SBrian Somers } 61330949fd4SBrian Somers break; 61430949fd4SBrian Somers #endif 61530949fd4SBrian Somers 616af57ed9fSAtsushi Murai case IPPROTO_UDP: 61730949fd4SBrian Somers uh = (const struct udphdr *)payload; 61830949fd4SBrian Somers if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos) 619da477886SBrian Somers pri++; 620da477886SBrian Somers 62130949fd4SBrian Somers if (!frag && ncp_IsUrgentUdpPort(&bundle->ncp, ntohs(uh->uh_sport), 622da477886SBrian Somers ntohs(uh->uh_dport))) 623da477886SBrian Somers pri++; 624da477886SBrian Somers 625da477886SBrian Somers if (logit && loglen < sizeof logbuf) { 62630949fd4SBrian Somers len = datalen - sizeof *uh; 62755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 62830949fd4SBrian Somers "UDP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(uh->uh_sport)); 62955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 63055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 63130949fd4SBrian Somers "%s:%d (%d/%d)", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport), 63298251667SBrian Somers len, nb); 63355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 634af57ed9fSAtsushi Murai } 63598251667SBrian Somers 63698251667SBrian Somers if (Enabled(bundle, OPT_FILTERDECAP) && 63730949fd4SBrian Somers payload[sizeof *uh] == HDLC_ADDR && 63830949fd4SBrian Somers payload[sizeof *uh + 1] == HDLC_UI) { 63998251667SBrian Somers u_short proto; 64098251667SBrian Somers const char *type; 64198251667SBrian Somers 64230949fd4SBrian Somers memcpy(&proto, payload + sizeof *uh + 2, sizeof proto); 64398251667SBrian Somers type = NULL; 64498251667SBrian Somers 64598251667SBrian Somers switch (ntohs(proto)) { 64698251667SBrian Somers case PROTO_IP: 64798251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 64830949fd4SBrian Somers result = PacketCheck(bundle, AF_INET, payload + sizeof *uh + 4, 64930949fd4SBrian Somers nb - (payload - packet) - sizeof *uh - 4, filter, 6500a4b6c5cSBrian Somers logbuf, psecs); 65198251667SBrian Somers if (result != -2) 65298251667SBrian Somers return result; 65398251667SBrian Somers type = "IP"; 65498251667SBrian Somers break; 65598251667SBrian Somers 65698251667SBrian Somers case PROTO_VJUNCOMP: type = "compressed VJ"; break; 65798251667SBrian Somers case PROTO_VJCOMP: type = "uncompressed VJ"; break; 65898251667SBrian Somers case PROTO_MP: type = "Multi-link"; break; 65998251667SBrian Somers case PROTO_ICOMPD: type = "Individual link CCP"; break; 66098251667SBrian Somers case PROTO_COMPD: type = "CCP"; break; 66198251667SBrian Somers case PROTO_IPCP: type = "IPCP"; break; 66298251667SBrian Somers case PROTO_LCP: type = "LCP"; break; 66398251667SBrian Somers case PROTO_PAP: type = "PAP"; break; 66498251667SBrian Somers case PROTO_CBCP: type = "CBCP"; break; 66598251667SBrian Somers case PROTO_LQR: type = "LQR"; break; 66698251667SBrian Somers case PROTO_CHAP: type = "CHAP"; break; 66798251667SBrian Somers } 66898251667SBrian Somers if (type) { 66998251667SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 67098251667SBrian Somers " - %s data", type); 67198251667SBrian Somers loglen += strlen(logbuf + loglen); 67298251667SBrian Somers } 67398251667SBrian Somers } 67498251667SBrian Somers 675af57ed9fSAtsushi Murai break; 676da477886SBrian Somers 67728149effSBrian Somers #ifdef IPPROTO_GRE 67828149effSBrian Somers case IPPROTO_GRE: 67928149effSBrian Somers if (logit && loglen < sizeof logbuf) { 68028149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 68130949fd4SBrian Somers "GRE: %s ---> ", ncpaddr_ntoa(&srcaddr)); 68228149effSBrian Somers loglen += strlen(logbuf + loglen); 68328149effSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 68430949fd4SBrian Somers "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb); 68528149effSBrian Somers loglen += strlen(logbuf + loglen); 68628149effSBrian Somers } 68728149effSBrian Somers break; 68828149effSBrian Somers #endif 68928149effSBrian Somers 69062e85934SBrian Somers #ifdef IPPROTO_OSPFIGP 6912faae814SBrian Somers case IPPROTO_OSPFIGP: 6922faae814SBrian Somers if (logit && loglen < sizeof logbuf) { 6932faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 69430949fd4SBrian Somers "OSPF: %s ---> ", ncpaddr_ntoa(&srcaddr)); 6952faae814SBrian Somers loglen += strlen(logbuf + loglen); 6962faae814SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 69730949fd4SBrian Somers "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb); 6982faae814SBrian Somers loglen += strlen(logbuf + loglen); 6992faae814SBrian Somers } 7002faae814SBrian Somers break; 70162e85934SBrian Somers #endif 702da477886SBrian Somers 70330949fd4SBrian Somers #ifndef NOINET6 70430949fd4SBrian Somers case IPPROTO_IPV6: 70530949fd4SBrian Somers if (logit && loglen < sizeof logbuf) { 70630949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 70730949fd4SBrian Somers "IPv6: %s ---> ", ncpaddr_ntoa(&srcaddr)); 70830949fd4SBrian Somers loglen += strlen(logbuf + loglen); 70930949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 71030949fd4SBrian Somers "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb); 71130949fd4SBrian Somers loglen += strlen(logbuf + loglen); 71230949fd4SBrian Somers } 71330949fd4SBrian Somers 71430949fd4SBrian Somers if (Enabled(bundle, OPT_FILTERDECAP)) { 71530949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 71630949fd4SBrian Somers result = PacketCheck(bundle, AF_INET6, payload, nb - (payload - packet), 71730949fd4SBrian Somers filter, logbuf, psecs); 71830949fd4SBrian Somers if (result != -2) 71930949fd4SBrian Somers return result; 72030949fd4SBrian Somers } 72130949fd4SBrian Somers break; 72230949fd4SBrian Somers #endif 72330949fd4SBrian Somers 724eee772ecSBrian Somers case IPPROTO_IPIP: 725eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 726eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 72730949fd4SBrian Somers "IPIP: %s ---> ", ncpaddr_ntoa(&srcaddr)); 728eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 729eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 73030949fd4SBrian Somers "%s", ncpaddr_ntoa(&dstaddr)); 731eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 73230949fd4SBrian Somers } 733da70ad60SBrian Somers 73430949fd4SBrian Somers if (Enabled(bundle, OPT_FILTERDECAP) && 73530949fd4SBrian Somers ((const struct ip *)payload)->ip_v == 4) { 736da70ad60SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains "); 73730949fd4SBrian Somers result = PacketCheck(bundle, AF_INET, payload, nb - (payload - packet), 73830949fd4SBrian Somers filter, logbuf, psecs); 739da70ad60SBrian Somers if (result != -2) 740da70ad60SBrian Somers return result; 741da70ad60SBrian Somers } 742eee772ecSBrian Somers break; 743da477886SBrian Somers 7442231246bSBrian Somers case IPPROTO_ESP: 7452231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 7462231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 74730949fd4SBrian Somers "ESP: %s ---> ", ncpaddr_ntoa(&srcaddr)); 7482231246bSBrian Somers loglen += strlen(logbuf + loglen); 74925254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 75030949fd4SBrian Somers ncpaddr_ntoa(&dstaddr), payload); 7512231246bSBrian Somers loglen += strlen(logbuf + loglen); 7522231246bSBrian Somers } 7532231246bSBrian Somers break; 7542231246bSBrian Somers 7552231246bSBrian Somers case IPPROTO_AH: 7562231246bSBrian Somers if (logit && loglen < sizeof logbuf) { 7572231246bSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 75830949fd4SBrian Somers "AH: %s ---> ", ncpaddr_ntoa(&srcaddr)); 7592231246bSBrian Somers loglen += strlen(logbuf + loglen); 76025254215SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p", 76130949fd4SBrian Somers ncpaddr_ntoa(&dstaddr), payload + sizeof(u_int32_t)); 7622231246bSBrian Somers loglen += strlen(logbuf + loglen); 7632231246bSBrian Somers } 7642231246bSBrian Somers break; 7652231246bSBrian Somers 766eee772ecSBrian Somers case IPPROTO_IGMP: 767eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 76830949fd4SBrian Somers uh = (const struct udphdr *)payload; 769eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 77030949fd4SBrian Somers "IGMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), 7710a4b6c5cSBrian Somers ntohs(uh->uh_sport)); 772eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 773eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 77430949fd4SBrian Somers "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport)); 775eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 776eee772ecSBrian Somers } 777eee772ecSBrian Somers break; 778da477886SBrian Somers 779af57ed9fSAtsushi Murai case IPPROTO_TCP: 78030949fd4SBrian Somers th = (const struct tcphdr *)payload; 78130949fd4SBrian Somers if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos) 782442f8495SBrian Somers pri++; 783da477886SBrian Somers 78430949fd4SBrian Somers if (!frag && ncp_IsUrgentTcpPort(&bundle->ncp, ntohs(th->th_sport), 785442f8495SBrian Somers ntohs(th->th_dport))) 786442f8495SBrian Somers pri++; 787442f8495SBrian Somers 78855a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 78930949fd4SBrian Somers len = datalen - (th->th_off << 2); 79055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 79130949fd4SBrian Somers "TCP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(th->th_sport)); 79255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 79355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 79430949fd4SBrian Somers "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(th->th_dport)); 79555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 796af57ed9fSAtsushi Murai n = 0; 797af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 79855a8cdeaSBrian Somers if (th->th_flags & mask) { 79955a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 80055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 80155a8cdeaSBrian Somers } 802af57ed9fSAtsushi Murai n++; 803af57ed9fSAtsushi Murai } 80455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 8053a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 8063a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 80755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 808af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 80930949fd4SBrian Somers const u_short *sp; 810af57ed9fSAtsushi Murai 81130949fd4SBrian Somers sp = (const u_short *)(payload + 20); 81255a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 81355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 81455a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 81555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 81655a8cdeaSBrian Somers } 817af57ed9fSAtsushi Murai } 818af57ed9fSAtsushi Murai } 819af57ed9fSAtsushi Murai break; 82098251667SBrian Somers 82198251667SBrian Somers default: 82298251667SBrian Somers if (prefix) 82398251667SBrian Somers return -2; 82430949fd4SBrian Somers 82530949fd4SBrian Somers if (logit && loglen < sizeof logbuf) { 82630949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 82730949fd4SBrian Somers "<%d>: %s ---> ", cproto, ncpaddr_ntoa(&srcaddr)); 82830949fd4SBrian Somers loglen += strlen(logbuf + loglen); 82930949fd4SBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 83030949fd4SBrian Somers "%s (%d)", ncpaddr_ntoa(&dstaddr), nb); 83130949fd4SBrian Somers loglen += strlen(logbuf + loglen); 83230949fd4SBrian Somers } 83330949fd4SBrian Somers break; 834af57ed9fSAtsushi Murai } 83576bd0c0aSDoug Rabson 83630949fd4SBrian Somers if (filter && FilterCheck(packet, family, filter, psecs)) { 837710e9c29SBrian Somers if (logit) 838dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 83952c9ca19SBrian Somers result = -1; 840af57ed9fSAtsushi Murai } else { 8415ca5389aSBrian Somers /* Check Keep Alive filter */ 84252c9ca19SBrian Somers if (logit && log_IsKept(LogTCPIP)) { 8430a4b6c5cSBrian Somers unsigned alivesecs; 8440a4b6c5cSBrian Somers 8450a4b6c5cSBrian Somers alivesecs = 0; 84630949fd4SBrian Somers if (filter && 84730949fd4SBrian Somers FilterCheck(packet, family, &bundle->filter.alive, &alivesecs)) 848dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 8490a4b6c5cSBrian Somers else if (psecs != NULL) { 8500a4b6c5cSBrian Somers if(*psecs == 0) 8510a4b6c5cSBrian Somers *psecs = alivesecs; 8520a4b6c5cSBrian Somers if (*psecs) { 8530a4b6c5cSBrian Somers if (*psecs != alivesecs) 8540a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n", 8550a4b6c5cSBrian Somers logbuf, *psecs, alivesecs); 8561e991daaSBrian Somers else 8570a4b6c5cSBrian Somers log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs); 8580a4b6c5cSBrian Somers } else 859dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 86053c9f6c0SAtsushi Murai } 8610a4b6c5cSBrian Somers } 86252c9ca19SBrian Somers result = pri; 863af57ed9fSAtsushi Murai } 86452c9ca19SBrian Somers 865b565321aSBrian Somers if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS)) 86652c9ca19SBrian Somers ip_LogDNS(uh, filter->name); 86752c9ca19SBrian Somers 86852c9ca19SBrian Somers return result; 869af57ed9fSAtsushi Murai } 870af57ed9fSAtsushi Murai 87130949fd4SBrian Somers static int 87230949fd4SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp, u_int32_t af) 8737a6f8720SBrian Somers { 874af57ed9fSAtsushi Murai int nb, nw; 875b6e82f33SBrian Somers struct tun_data tun; 8763a7b6d76SBrian Somers char *data; 8770a4b6c5cSBrian Somers unsigned secs, alivesecs; 8785d9e6103SBrian Somers 87926af0ae9SBrian Somers nb = m_length(bp); 88076d98538SBrian Somers if (nb > sizeof tun.data) { 88176d98538SBrian Somers log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 88276d98538SBrian Somers l->name, nb, (int)(sizeof tun.data)); 88326af0ae9SBrian Somers m_freem(bp); 88430949fd4SBrian Somers return 0; 88576d98538SBrian Somers } 8865d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 887af57ed9fSAtsushi Murai 8880a4b6c5cSBrian Somers secs = 0; 88930949fd4SBrian Somers if (PacketCheck(bundle, af, tun.data, nb, &bundle->filter.in, 89030949fd4SBrian Somers NULL, &secs) < 0) 89130949fd4SBrian Somers return 0; 8926db75539SBrian Somers 8930a4b6c5cSBrian Somers alivesecs = 0; 89430949fd4SBrian Somers if (!FilterCheck(tun.data, af, &bundle->filter.alive, &alivesecs)) { 8950a4b6c5cSBrian Somers if (secs == 0) 8960a4b6c5cSBrian Somers secs = alivesecs; 8970a4b6c5cSBrian Somers bundle_StartIdleTimer(bundle, secs); 8980a4b6c5cSBrian Somers } 8991e991daaSBrian Somers 9003a7b6d76SBrian Somers if (bundle->dev.header) { 90130949fd4SBrian Somers tun.header.family = htonl(af); 90270ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 9033a7b6d76SBrian Somers data = (char *)&tun; 9043a7b6d76SBrian Somers } else 9053a7b6d76SBrian Somers data = tun.data; 9063a7b6d76SBrian Somers 9073a7b6d76SBrian Somers nw = write(bundle->dev.fd, data, nb); 908c4c4aaacSBrian Somers if (nw != nb) { 90957fd05c4SBrian Somers if (nw == -1) 91076d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 91176d98538SBrian Somers l->name, nb, strerror(errno)); 91257fd05c4SBrian Somers else 91376d98538SBrian Somers log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 9146db75539SBrian Somers } 9155d9e6103SBrian Somers 91630949fd4SBrian Somers return nb; 91730949fd4SBrian Somers } 91830949fd4SBrian Somers 91930949fd4SBrian Somers struct mbuf * 92030949fd4SBrian Somers ipv4_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 92130949fd4SBrian Somers { 92230949fd4SBrian Somers int nb; 92330949fd4SBrian Somers 92430949fd4SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 92530949fd4SBrian Somers log_Printf(LogWARN, "ipv4_Input: IPCP not open - packet dropped\n"); 92630949fd4SBrian Somers m_freem(bp); 9275d9e6103SBrian Somers return NULL; 928af57ed9fSAtsushi Murai } 929af57ed9fSAtsushi Murai 93030949fd4SBrian Somers m_settype(bp, MB_IPIN); 93130949fd4SBrian Somers 93230949fd4SBrian Somers nb = ip_Input(bundle, l, bp, AF_INET); 93330949fd4SBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 93430949fd4SBrian Somers 93530949fd4SBrian Somers return NULL; 93630949fd4SBrian Somers } 93730949fd4SBrian Somers 93830949fd4SBrian Somers #ifndef NOINET6 93930949fd4SBrian Somers struct mbuf * 94030949fd4SBrian Somers ipv6_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 941af57ed9fSAtsushi Murai { 94230949fd4SBrian Somers int nb; 943af57ed9fSAtsushi Murai 9441136c6acSBrian Somers if (bundle->ncp.ipv6cp.fsm.state != ST_OPENED) { 94530949fd4SBrian Somers log_Printf(LogWARN, "ipv6_Input: IPV6CP not open - packet dropped\n"); 94630949fd4SBrian Somers m_freem(bp); 94730949fd4SBrian Somers return NULL; 948af57ed9fSAtsushi Murai } 949af57ed9fSAtsushi Murai 95030949fd4SBrian Somers m_settype(bp, MB_IPV6IN); 9516f8e9f0aSBrian Somers 95230949fd4SBrian Somers nb = ip_Input(bundle, l, bp, AF_INET6); 95330949fd4SBrian Somers ipv6cp_AddInOctets(&bundle->ncp.ipv6cp, nb); 95430949fd4SBrian Somers 95530949fd4SBrian Somers return NULL; 9566f8e9f0aSBrian Somers } 95730949fd4SBrian Somers #endif 958