ip.c revision 129175
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 *                           Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/usr.sbin/ppp/ip.c 129175 2004-05-13 09:03:00Z dds $
29 */
30
31#include <sys/param.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34#include <netinet/in_systm.h>
35#include <netinet/ip.h>
36#ifndef NOINET6
37#include <netinet/icmp6.h>
38#include <netinet/ip6.h>
39#endif
40#include <netinet/ip_icmp.h>
41#include <netinet/udp.h>
42#include <netinet/tcp.h>
43#include <sys/un.h>
44
45#include <errno.h>
46#include <netdb.h>
47#include <stdio.h>
48#include <string.h>
49#include <termios.h>
50#include <unistd.h>
51
52#include "layer.h"
53#include "proto.h"
54#include "mbuf.h"
55#include "log.h"
56#include "defs.h"
57#include "timer.h"
58#include "fsm.h"
59#include "lqr.h"
60#include "hdlc.h"
61#include "throughput.h"
62#include "iplist.h"
63#include "slcompress.h"
64#include "ncpaddr.h"
65#include "ip.h"
66#include "ipcp.h"
67#include "filter.h"
68#include "descriptor.h"
69#include "lcp.h"
70#include "ccp.h"
71#include "link.h"
72#include "mp.h"
73#ifndef NORADIUS
74#include "radius.h"
75#endif
76#include "ipv6cp.h"
77#include "ncp.h"
78#include "bundle.h"
79#include "tun.h"
80
81
82#define OPCODE_QUERY	0
83#define OPCODE_IQUERY	1
84#define OPCODE_STATUS	2
85
86struct dns_header {
87  u_short id;
88  unsigned qr : 1;
89  unsigned opcode : 4;
90  unsigned aa : 1;
91  unsigned tc : 1;
92  unsigned rd : 1;
93  unsigned ra : 1;
94  unsigned z : 3;
95  unsigned rcode : 4;
96  u_short qdcount;
97  u_short ancount;
98  u_short nscount;
99  u_short arcount;
100};
101
102static const char *
103dns_Qclass2Txt(u_short qclass)
104{
105  static char failure[6];
106  struct {
107    u_short id;
108    const char *txt;
109  } qtxt[] = {
110    /* rfc1035 */
111    { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" }
112  };
113  int f;
114
115  for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++)
116    if (qtxt[f].id == qclass)
117      return qtxt[f].txt;
118
119  return HexStr(qclass, failure, sizeof failure);
120}
121
122static const char *
123dns_Qtype2Txt(u_short qtype)
124{
125  static char failure[6];
126  struct {
127    u_short id;
128    const char *txt;
129  } qtxt[] = {
130    /* rfc1035/rfc1700 */
131    { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" },
132    { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" },
133    { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" },
134    { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" },
135    { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" },
136    { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" },
137    { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" },
138    { 254, "MAILA" }, { 255, "*" }
139  };
140  int f;
141
142  for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++)
143    if (qtxt[f].id == qtype)
144      return qtxt[f].txt;
145
146  return HexStr(qtype, failure, sizeof failure);
147}
148
149static __inline int
150PortMatch(int op, u_short pport, u_short rport)
151{
152  switch (op) {
153  case OP_EQ:
154    return pport == rport;
155  case OP_GT:
156    return pport > rport;
157  case OP_LT:
158    return pport < rport;
159  default:
160    return 0;
161  }
162}
163
164/*
165 * Return a text string representing the cproto protocol number.
166 *
167 * The purpose of this routine is calculate this result, for
168 * the many times it is needed in FilterCheck, only on demand
169 * (i.e. when the corresponding logging functions are invoked).
170 *
171 * This optimization saves, over the previous implementation, which
172 * calculated prototxt at the beginning of FilterCheck, an
173 * open/read/close system call sequence per packet, approximately
174 * halving the ppp system overhead and reducing the overall (u + s)
175 * time by 38%.
176 *
177 * The caching performed here is just a side effect.
178 */
179static const char *
180prototxt(int cproto)
181{
182  static int oproto = -1;
183  static char protobuff[16] = "-1";
184  struct protoent *pe;
185
186  if (cproto == oproto)
187	return protobuff;
188  if ((pe = getprotobynumber(cproto)) == NULL)
189    snprintf(protobuff, sizeof protobuff, "%d", cproto);
190  else
191    snprintf(protobuff, sizeof protobuff, "%s", pe->p_name);
192  oproto = cproto;
193  return (protobuff);
194}
195
196/*
197 * Check a packet against the given filter
198 * Returns 0 to accept the packet, non-zero to drop the packet.
199 * If psecs is not NULL, populate it with the timeout associated
200 * with the filter rule matched.
201 *
202 * If filtering is enabled, the initial fragment of a datagram must
203 * contain the complete protocol header, and subsequent fragments
204 * must not attempt to over-write it.
205 *
206 * One (and only one) of pip or pip6 must be set.
207 */
208int
209FilterCheck(const unsigned char *packet, u_int32_t family,
210            const struct filter *filter, unsigned *psecs)
211{
212  int gotinfo;			/* true if IP payload decoded */
213  int cproto;			/* IPPROTO_* protocol number if (gotinfo) */
214  int estab, syn, finrst;	/* TCP state flags if (gotinfo) */
215  u_short sport, dport;		/* src, dest port from packet if (gotinfo) */
216  int n;			/* filter rule to process */
217  int len;			/* bytes used in dbuff */
218  int didname;			/* true if filter header printed */
219  int match;			/* true if condition matched */
220  int mindata;			/* minimum data size or zero */
221  const struct filterent *fp = filter->rule;
222  char dbuff[100], dstip[16];
223  struct ncpaddr srcaddr, dstaddr;
224  const char *payload;		/* IP payload */
225  int datalen;			/* IP datagram length */
226
227  if (fp->f_action == A_NONE)
228    return 0;		/* No rule is given. Permit this packet */
229
230#ifndef NOINET6
231  if (family == AF_INET6) {
232    const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
233
234    ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
235    ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
236    datalen = ntohs(pip6->ip6_plen);
237    payload = packet + sizeof *pip6;
238    cproto = pip6->ip6_nxt;
239  } else
240#endif
241  {
242    /*
243     * Deny any packet fragment that tries to over-write the header.
244     * Since we no longer have the real header available, punt on the
245     * largest normal header - 20 bytes for TCP without options, rounded
246     * up to the next possible fragment boundary.  Since the smallest
247     * `legal' MTU is 576, and the smallest recommended MTU is 296, any
248     * fragmentation within this range is dubious at best
249     */
250    const struct ip *pip = (const struct ip *)packet;
251
252    len = ntohs(pip->ip_off) & IP_OFFMASK;	/* fragment offset */
253    if (len > 0) {		/* Not first fragment within datagram */
254      if (len < (24 >> 3)) {	/* don't allow fragment to over-write header */
255        log_Printf(LogFILTER, " error: illegal header\n");
256        return 1;
257      }
258      /* permit fragments on in and out filter */
259      if (!filter->fragok) {
260        log_Printf(LogFILTER, " error: illegal fragmentation\n");
261        return 1;
262      } else
263        return 0;
264    }
265
266    ncpaddr_setip4(&srcaddr, pip->ip_src);
267    ncpaddr_setip4(&dstaddr, pip->ip_dst);
268    datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
269    payload = packet + (pip->ip_hl << 2);
270    cproto = pip->ip_p;
271  }
272
273
274  gotinfo = estab = syn = finrst = didname = 0;
275  sport = dport = 0;
276
277  for (n = 0; n < MAXFILTERS; ) {
278    if (fp->f_action == A_NONE) {
279      n++;
280      fp++;
281      continue;
282    }
283
284    if (!didname) {
285      log_Printf(LogDEBUG, "%s filter:\n", filter->name);
286      didname = 1;
287    }
288
289    match = 0;
290
291    if ((ncprange_family(&fp->f_src) == AF_UNSPEC ||
292         ncprange_contains(&fp->f_src, &srcaddr)) &&
293        (ncprange_family(&fp->f_dst) == AF_UNSPEC ||
294         ncprange_contains(&fp->f_dst, &dstaddr))) {
295      if (fp->f_proto != 0) {
296        if (!gotinfo) {
297          const struct tcphdr *th;
298          const struct udphdr *uh;
299          const struct icmp *ih;
300#ifndef NOINET6
301          const struct icmp6_hdr *ih6;
302#endif
303          mindata = 0;
304          sport = dport = 0;
305          estab = syn = finrst = -1;
306
307          switch (cproto) {
308          case IPPROTO_ICMP:
309            mindata = 8;	/* ICMP must be at least 8 octets */
310            ih = (const struct icmp *)payload;
311            sport = ih->icmp_type;
312            if (log_IsKept(LogDEBUG))
313              snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
314            break;
315
316#ifndef NOINET6
317          case IPPROTO_ICMPV6:
318            mindata = 8;	/* ICMP must be at least 8 octets */
319            ih6 = (const struct icmp6_hdr *)payload;
320            sport = ih6->icmp6_type;
321            if (log_IsKept(LogDEBUG))
322              snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
323            break;
324#endif
325
326          case IPPROTO_IGMP:
327            mindata = 8;	/* IGMP uses 8-octet messages */
328            break;
329
330#ifdef IPPROTO_GRE
331          case IPPROTO_GRE:
332            mindata = 2;	/* GRE uses 2-octet+ messages */
333            break;
334#endif
335#ifdef IPPROTO_OSPFIGP
336          case IPPROTO_OSPFIGP:
337            mindata = 8;	/* IGMP uses 8-octet messages */
338            break;
339#endif
340#ifndef NOINET6
341          case IPPROTO_IPV6:
342            mindata = 20;	/* RFC2893 Section 3.5: 5 * 32bit words */
343            break;
344#endif
345
346          case IPPROTO_UDP:
347            mindata = 8;	/* UDP header is 8 octets */
348            uh = (const struct udphdr *)payload;
349            sport = ntohs(uh->uh_sport);
350            dport = ntohs(uh->uh_dport);
351            if (log_IsKept(LogDEBUG))
352              snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
353                       sport, dport);
354            break;
355
356          case IPPROTO_TCP:
357            th = (const struct tcphdr *)payload;
358            /*
359             * TCP headers are variable length.  The following code
360             * ensures that the TCP header length isn't de-referenced if
361             * the datagram is too short
362             */
363            if (datalen < 20 || datalen < (th->th_off << 2)) {
364              log_Printf(LogFILTER, " error: TCP header incorrect\n");
365              return 1;
366            }
367            sport = ntohs(th->th_sport);
368            dport = ntohs(th->th_dport);
369            estab = (th->th_flags & TH_ACK);
370            syn = (th->th_flags & TH_SYN);
371            finrst = (th->th_flags & (TH_FIN|TH_RST));
372            if (log_IsKept(LogDEBUG)) {
373              if (!estab)
374                snprintf(dbuff, sizeof dbuff,
375                         "flags = %02x, sport = %d, dport = %d",
376                         th->th_flags, sport, dport);
377              else
378                *dbuff = '\0';
379            }
380            break;
381          default:
382            break;
383          }
384
385          if (datalen < mindata) {
386            log_Printf(LogFILTER, " error: proto %s must be at least"
387                       " %d octets\n", prototxt(cproto), mindata);
388            return 1;
389          }
390
391          if (log_IsKept(LogDEBUG)) {
392            if (estab != -1) {
393              len = strlen(dbuff);
394              snprintf(dbuff + len, sizeof dbuff - len,
395                       ", estab = %d, syn = %d, finrst = %d",
396                       estab, syn, finrst);
397            }
398            log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
399                       prototxt(cproto), dbuff);
400          }
401          gotinfo = 1;
402        }
403
404        if (log_IsKept(LogDEBUG)) {
405          if (fp->f_srcop != OP_NONE) {
406            snprintf(dbuff, sizeof dbuff, ", src %s %d",
407                     filter_Op2Nam(fp->f_srcop), fp->f_srcport);
408            len = strlen(dbuff);
409          } else
410            len = 0;
411          if (fp->f_dstop != OP_NONE) {
412            snprintf(dbuff + len, sizeof dbuff - len,
413                     ", dst %s %d", filter_Op2Nam(fp->f_dstop),
414                     fp->f_dstport);
415          } else if (!len)
416            *dbuff = '\0';
417
418          log_Printf(LogDEBUG, "  rule = %d: Address match, "
419                     "check against proto %d%s, action = %s\n",
420                     n, fp->f_proto, dbuff, filter_Action2Nam(fp->f_action));
421        }
422
423        if (cproto == fp->f_proto) {
424          if ((fp->f_srcop == OP_NONE ||
425               PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
426              (fp->f_dstop == OP_NONE ||
427               PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
428              (fp->f_estab == 0 || estab) &&
429              (fp->f_syn == 0 || syn) &&
430              (fp->f_finrst == 0 || finrst)) {
431            match = 1;
432          }
433        }
434      } else {
435        /* Address is matched and no protocol specified. Make a decision. */
436        log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
437                   filter_Action2Nam(fp->f_action));
438        match = 1;
439      }
440    } else
441      log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
442
443    if (match != fp->f_invert) {
444      /* Take specified action */
445      if (fp->f_action < A_NONE)
446        fp = &filter->rule[n = fp->f_action];
447      else {
448        if (fp->f_action == A_PERMIT) {
449          if (psecs != NULL)
450            *psecs = fp->timeout;
451          if (strcmp(filter->name, "DIAL") == 0) {
452            /* If dial filter then even print out accept packets */
453            if (log_IsKept(LogFILTER)) {
454              snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
455              log_Printf(LogFILTER, "%sbound rule = %d accept %s "
456                         "src = %s:%d dst = %s:%d\n", filter->name, n,
457                         prototxt(cproto), ncpaddr_ntoa(&srcaddr), sport,
458                         dstip, dport);
459            }
460          }
461          return 0;
462        } else {
463          if (log_IsKept(LogFILTER)) {
464            snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
465            log_Printf(LogFILTER,
466                       "%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n",
467                       filter->name, n, prototxt(cproto),
468                       ncpaddr_ntoa(&srcaddr), sport, dstip, dport);
469          }
470          return 1;
471        }		/* Explict match.  Deny this packet */
472      }
473    } else {
474      n++;
475      fp++;
476    }
477  }
478
479  if (log_IsKept(LogFILTER)) {
480    snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
481    log_Printf(LogFILTER,
482               "%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n",
483               filter->name, prototxt(cproto), ncpaddr_ntoa(&srcaddr),
484               sport, dstip, dport);
485  }
486
487  return 1;		/* No rule matched, deny this packet */
488}
489
490static void
491ip_LogDNS(const struct udphdr *uh, const char *direction)
492{
493  struct dns_header header;
494  const u_short *pktptr;
495  const u_char *ptr;
496  u_short *hptr, tmp;
497  int len;
498
499  ptr = (const char *)uh + sizeof *uh;
500  len = ntohs(uh->uh_ulen) - sizeof *uh;
501  if (len < sizeof header + 5)		/* rfc1024 */
502    return;
503
504  pktptr = (const u_short *)ptr;
505  hptr = (u_short *)&header;
506  ptr += sizeof header;
507  len -= sizeof header;
508
509  while (pktptr < (const u_short *)ptr) {
510    *hptr++ = ntohs(*pktptr);		/* Careful of macro side-effects ! */
511    pktptr++;
512  }
513
514  if (header.opcode == OPCODE_QUERY && header.qr == 0) {
515    /* rfc1035 */
516    char namewithdot[MAXHOSTNAMELEN + 1], *n;
517    const char *qtype, *qclass;
518    const u_char *end;
519
520    n = namewithdot;
521    end = ptr + len - 4;
522    if (end - ptr >= sizeof namewithdot)
523      end = ptr + sizeof namewithdot - 1;
524    while (ptr < end) {
525      len = *ptr++;
526      if (len > end - ptr)
527        len = end - ptr;
528      if (n != namewithdot)
529        *n++ = '.';
530      memcpy(n, ptr, len);
531      ptr += len;
532      n += len;
533    }
534    *n = '\0';
535
536    if (log_IsKept(LogDNS)) {
537      memcpy(&tmp, end, sizeof tmp);
538      qtype = dns_Qtype2Txt(ntohs(tmp));
539      memcpy(&tmp, end + 2, sizeof tmp);
540      qclass = dns_Qclass2Txt(ntohs(tmp));
541
542      log_Printf(LogDNS, "%sbound query %s %s %s\n",
543                 direction, qclass, qtype, namewithdot);
544    }
545  }
546}
547
548/*
549 * Check if the given packet matches the given filter.
550 * One of pip or pip6 must be set.
551 */
552int
553PacketCheck(struct bundle *bundle, u_int32_t family,
554            const unsigned char *packet, int nb, struct filter *filter,
555            const char *prefix, unsigned *psecs)
556{
557  static const char *const TcpFlags[] = {
558    "FIN", "SYN", "RST", "PSH", "ACK", "URG"
559  };
560  const struct tcphdr *th;
561  const struct udphdr *uh;
562  const struct icmp *icmph;
563#ifndef NOINET6
564  const struct icmp6_hdr *icmp6h;
565#endif
566  const unsigned char *payload;
567  struct ncpaddr srcaddr, dstaddr;
568  int cproto, mask, len, n, pri, logit, loglen, result;
569  char logbuf[200];
570  int datalen, frag;
571  u_char tos;
572
573  logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) &&
574          (!filter || filter->logok);
575  loglen = 0;
576  pri = 0;
577
578#ifndef NOINET6
579  if (family == AF_INET6) {
580    const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
581
582    ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
583    ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
584    datalen = ntohs(pip6->ip6_plen);
585    payload = packet + sizeof *pip6;
586    cproto = pip6->ip6_nxt;
587    tos = 0;					/* XXX: pip6->ip6_vfc >> 4 ? */
588    frag = 0;					/* XXX: ??? */
589  } else
590#endif
591  {
592    const struct ip *pip = (const struct ip *)packet;
593
594    ncpaddr_setip4(&srcaddr, pip->ip_src);
595    ncpaddr_setip4(&dstaddr, pip->ip_dst);
596    datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
597    payload = packet + (pip->ip_hl << 2);
598    cproto = pip->ip_p;
599    tos = pip->ip_tos;
600    frag = ntohs(pip->ip_off) & IP_OFFMASK;
601  }
602
603  uh = NULL;
604
605  if (logit && loglen < sizeof logbuf) {
606    if (prefix)
607      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix);
608    else if (filter)
609      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
610    else
611      snprintf(logbuf + loglen, sizeof logbuf - loglen, "  ");
612    loglen += strlen(logbuf + loglen);
613  }
614
615  switch (cproto) {
616  case IPPROTO_ICMP:
617    if (logit && loglen < sizeof logbuf) {
618      len = datalen - sizeof *icmph;
619      icmph = (const struct icmp *)payload;
620      snprintf(logbuf + loglen, sizeof logbuf - loglen,
621               "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmph->icmp_type);
622      loglen += strlen(logbuf + loglen);
623      snprintf(logbuf + loglen, sizeof logbuf - loglen,
624               "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
625      loglen += strlen(logbuf + loglen);
626    }
627    break;
628
629#ifndef NOINET6
630  case IPPROTO_ICMPV6:
631    if (logit && loglen < sizeof logbuf) {
632      len = datalen - sizeof *icmp6h;
633      icmp6h = (const struct icmp6_hdr *)payload;
634      snprintf(logbuf + loglen, sizeof logbuf - loglen,
635               "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmp6h->icmp6_type);
636      loglen += strlen(logbuf + loglen);
637      snprintf(logbuf + loglen, sizeof logbuf - loglen,
638               "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
639      loglen += strlen(logbuf + loglen);
640    }
641    break;
642#endif
643
644  case IPPROTO_UDP:
645    uh = (const struct udphdr *)payload;
646    if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
647      pri++;
648
649    if (!frag && ncp_IsUrgentUdpPort(&bundle->ncp, ntohs(uh->uh_sport),
650                                     ntohs(uh->uh_dport)))
651      pri++;
652
653    if (logit && loglen < sizeof logbuf) {
654      len = datalen - sizeof *uh;
655      snprintf(logbuf + loglen, sizeof logbuf - loglen,
656               "UDP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(uh->uh_sport));
657      loglen += strlen(logbuf + loglen);
658      snprintf(logbuf + loglen, sizeof logbuf - loglen,
659               "%s:%d (%d/%d)", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport),
660               len, nb);
661      loglen += strlen(logbuf + loglen);
662    }
663
664    if (Enabled(bundle, OPT_FILTERDECAP) &&
665        payload[sizeof *uh] == HDLC_ADDR &&
666        payload[sizeof *uh + 1] == HDLC_UI) {
667      u_short proto;
668      const char *type;
669
670      memcpy(&proto, payload + sizeof *uh + 2, sizeof proto);
671      type = NULL;
672
673      switch (ntohs(proto)) {
674        case PROTO_IP:
675          snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
676          result = PacketCheck(bundle, AF_INET, payload + sizeof *uh + 4,
677                               nb - (payload - packet) - sizeof *uh - 4, filter,
678                               logbuf, psecs);
679          if (result != -2)
680              return result;
681          type = "IP";
682          break;
683
684        case PROTO_VJUNCOMP: type = "compressed VJ";   break;
685        case PROTO_VJCOMP:   type = "uncompressed VJ"; break;
686        case PROTO_MP:       type = "Multi-link"; break;
687        case PROTO_ICOMPD:   type = "Individual link CCP"; break;
688        case PROTO_COMPD:    type = "CCP"; break;
689        case PROTO_IPCP:     type = "IPCP"; break;
690        case PROTO_LCP:      type = "LCP"; break;
691        case PROTO_PAP:      type = "PAP"; break;
692        case PROTO_CBCP:     type = "CBCP"; break;
693        case PROTO_LQR:      type = "LQR"; break;
694        case PROTO_CHAP:     type = "CHAP"; break;
695      }
696      if (type) {
697        snprintf(logbuf + loglen, sizeof logbuf - loglen,
698                 " - %s data", type);
699        loglen += strlen(logbuf + loglen);
700      }
701    }
702
703    break;
704
705#ifdef IPPROTO_GRE
706  case IPPROTO_GRE:
707    if (logit && loglen < sizeof logbuf) {
708      snprintf(logbuf + loglen, sizeof logbuf - loglen,
709          "GRE: %s ---> ", ncpaddr_ntoa(&srcaddr));
710      loglen += strlen(logbuf + loglen);
711      snprintf(logbuf + loglen, sizeof logbuf - loglen,
712              "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
713      loglen += strlen(logbuf + loglen);
714    }
715    break;
716#endif
717
718#ifdef IPPROTO_OSPFIGP
719  case IPPROTO_OSPFIGP:
720    if (logit && loglen < sizeof logbuf) {
721      snprintf(logbuf + loglen, sizeof logbuf - loglen,
722               "OSPF: %s ---> ", ncpaddr_ntoa(&srcaddr));
723      loglen += strlen(logbuf + loglen);
724      snprintf(logbuf + loglen, sizeof logbuf - loglen,
725               "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
726      loglen += strlen(logbuf + loglen);
727    }
728    break;
729#endif
730
731#ifndef NOINET6
732  case IPPROTO_IPV6:
733    if (logit && loglen < sizeof logbuf) {
734      snprintf(logbuf + loglen, sizeof logbuf - loglen,
735               "IPv6: %s ---> ", ncpaddr_ntoa(&srcaddr));
736      loglen += strlen(logbuf + loglen);
737      snprintf(logbuf + loglen, sizeof logbuf - loglen,
738               "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
739      loglen += strlen(logbuf + loglen);
740    }
741
742    if (Enabled(bundle, OPT_FILTERDECAP)) {
743      snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
744      result = PacketCheck(bundle, AF_INET6, payload, nb - (payload - packet),
745                           filter, logbuf, psecs);
746      if (result != -2)
747        return result;
748    }
749    break;
750#endif
751
752  case IPPROTO_IPIP:
753    if (logit && loglen < sizeof logbuf) {
754      snprintf(logbuf + loglen, sizeof logbuf - loglen,
755               "IPIP: %s ---> ", ncpaddr_ntoa(&srcaddr));
756      loglen += strlen(logbuf + loglen);
757      snprintf(logbuf + loglen, sizeof logbuf - loglen,
758               "%s", ncpaddr_ntoa(&dstaddr));
759      loglen += strlen(logbuf + loglen);
760    }
761
762    if (Enabled(bundle, OPT_FILTERDECAP) &&
763        ((const struct ip *)payload)->ip_v == 4) {
764      snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
765      result = PacketCheck(bundle, AF_INET, payload, nb - (payload - packet),
766                           filter, logbuf, psecs);
767      if (result != -2)
768        return result;
769    }
770    break;
771
772  case IPPROTO_ESP:
773    if (logit && loglen < sizeof logbuf) {
774      snprintf(logbuf + loglen, sizeof logbuf - loglen,
775               "ESP: %s ---> ", ncpaddr_ntoa(&srcaddr));
776      loglen += strlen(logbuf + loglen);
777      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
778               ncpaddr_ntoa(&dstaddr), payload);
779      loglen += strlen(logbuf + loglen);
780    }
781    break;
782
783  case IPPROTO_AH:
784    if (logit && loglen < sizeof logbuf) {
785      snprintf(logbuf + loglen, sizeof logbuf - loglen,
786               "AH: %s ---> ", ncpaddr_ntoa(&srcaddr));
787      loglen += strlen(logbuf + loglen);
788      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
789               ncpaddr_ntoa(&dstaddr), payload + sizeof(u_int32_t));
790      loglen += strlen(logbuf + loglen);
791    }
792    break;
793
794  case IPPROTO_IGMP:
795    if (logit && loglen < sizeof logbuf) {
796      uh = (const struct udphdr *)payload;
797      snprintf(logbuf + loglen, sizeof logbuf - loglen,
798               "IGMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr),
799               ntohs(uh->uh_sport));
800      loglen += strlen(logbuf + loglen);
801      snprintf(logbuf + loglen, sizeof logbuf - loglen,
802               "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport));
803      loglen += strlen(logbuf + loglen);
804    }
805    break;
806
807  case IPPROTO_TCP:
808    th = (const struct tcphdr *)payload;
809    if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
810      pri++;
811
812    if (!frag && ncp_IsUrgentTcpPort(&bundle->ncp, ntohs(th->th_sport),
813                                     ntohs(th->th_dport)))
814      pri++;
815
816    if (logit && loglen < sizeof logbuf) {
817      len = datalen - (th->th_off << 2);
818      snprintf(logbuf + loglen, sizeof logbuf - loglen,
819           "TCP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(th->th_sport));
820      loglen += strlen(logbuf + loglen);
821      snprintf(logbuf + loglen, sizeof logbuf - loglen,
822               "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(th->th_dport));
823      loglen += strlen(logbuf + loglen);
824      n = 0;
825      for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
826        if (th->th_flags & mask) {
827          snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
828          loglen += strlen(logbuf + loglen);
829        }
830        n++;
831      }
832      snprintf(logbuf + loglen, sizeof logbuf - loglen,
833               "  seq:%lx  ack:%lx (%d/%d)",
834               (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
835      loglen += strlen(logbuf + loglen);
836      if ((th->th_flags & TH_SYN) && nb > 40) {
837        const u_short *sp;
838
839        sp = (const u_short *)(payload + 20);
840        if (ntohs(sp[0]) == 0x0204) {
841          snprintf(logbuf + loglen, sizeof logbuf - loglen,
842                   " MSS = %d", ntohs(sp[1]));
843          loglen += strlen(logbuf + loglen);
844        }
845      }
846    }
847    break;
848
849  default:
850    if (prefix)
851      return -2;
852
853    if (logit && loglen < sizeof logbuf) {
854      snprintf(logbuf + loglen, sizeof logbuf - loglen,
855               "<%d>: %s ---> ", cproto, ncpaddr_ntoa(&srcaddr));
856      loglen += strlen(logbuf + loglen);
857      snprintf(logbuf + loglen, sizeof logbuf - loglen,
858               "%s (%d)", ncpaddr_ntoa(&dstaddr), nb);
859      loglen += strlen(logbuf + loglen);
860    }
861    break;
862  }
863
864  if (filter && FilterCheck(packet, family, filter, psecs)) {
865    if (logit)
866      log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
867    result = -1;
868  } else {
869    /* Check Keep Alive filter */
870    if (logit && log_IsKept(LogTCPIP)) {
871      unsigned alivesecs;
872
873      alivesecs = 0;
874      if (filter &&
875          FilterCheck(packet, family, &bundle->filter.alive, &alivesecs))
876        log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
877      else if (psecs != NULL) {
878        if(*psecs == 0)
879          *psecs = alivesecs;
880        if (*psecs) {
881          if (*psecs != alivesecs)
882            log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n",
883                       logbuf, *psecs, alivesecs);
884          else
885            log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs);
886        } else
887          log_Printf(LogTCPIP, "%s\n", logbuf);
888      }
889    }
890    result = pri;
891  }
892
893  if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS))
894    ip_LogDNS(uh, filter->name);
895
896  return result;
897}
898
899static int
900ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp, u_int32_t af)
901{
902  int nb, nw;
903  struct tun_data tun;
904  char *data;
905  unsigned secs, alivesecs;
906
907  nb = m_length(bp);
908  if (nb > sizeof tun.data) {
909    log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
910               l->name, nb, (int)(sizeof tun.data));
911    m_freem(bp);
912    return 0;
913  }
914  mbuf_Read(bp, tun.data, nb);
915
916  secs = 0;
917  if (PacketCheck(bundle, af, tun.data, nb, &bundle->filter.in,
918                  NULL, &secs) < 0)
919    return 0;
920
921  alivesecs = 0;
922  if (!FilterCheck(tun.data, af, &bundle->filter.alive, &alivesecs)) {
923    if (secs == 0)
924      secs = alivesecs;
925    bundle_StartIdleTimer(bundle, secs);
926  }
927
928  if (bundle->dev.header) {
929    tun.header.family = htonl(af);
930    nb += sizeof tun - sizeof tun.data;
931    data = (char *)&tun;
932  } else
933    data = tun.data;
934
935  nw = write(bundle->dev.fd, data, nb);
936  if (nw != nb) {
937    if (nw == -1)
938      log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
939                 l->name, nb, strerror(errno));
940    else
941      log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
942  }
943
944  return nb;
945}
946
947struct mbuf *
948ipv4_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
949{
950  int nb;
951
952  if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
953    log_Printf(LogWARN, "ipv4_Input: IPCP not open - packet dropped\n");
954    m_freem(bp);
955    return NULL;
956  }
957
958  m_settype(bp, MB_IPIN);
959
960  nb = ip_Input(bundle, l, bp, AF_INET);
961  ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
962
963  return NULL;
964}
965
966#ifndef NOINET6
967struct mbuf *
968ipv6_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
969{
970  int nb;
971
972  if (bundle->ncp.ipv6cp.fsm.state != ST_OPENED) {
973    log_Printf(LogWARN, "ipv6_Input: IPV6CP not open - packet dropped\n");
974    m_freem(bp);
975    return NULL;
976  }
977
978  m_settype(bp, MB_IPV6IN);
979
980  nb = ip_Input(bundle, l, bp, AF_INET6);
981  ipv6cp_AddInOctets(&bundle->ncp.ipv6cp, nb);
982
983  return NULL;
984}
985#endif
986