ip.c revision 134833
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 134833 2004-09-06 00:07:58Z marcel $
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  unsigned 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  unsigned 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  unsigned 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 >= (int)sizeof namewithdot)
523      end = ptr + sizeof namewithdot - 1;
524    while (ptr < end) {
525      len = *ptr++;
526      if ((int)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  char logbuf[200];
558  static const char *const TcpFlags[] = {
559    "FIN", "SYN", "RST", "PSH", "ACK", "URG"
560  };
561  const struct tcphdr *th;
562  const struct udphdr *uh;
563  const struct icmp *icmph;
564#ifndef NOINET6
565  const struct icmp6_hdr *icmp6h;
566#endif
567  const unsigned char *payload;
568  struct ncpaddr srcaddr, dstaddr;
569  int cproto, mask, len, n, pri, logit, result, datalen, frag;
570  unsigned loglen;
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      loglen += strlen(logbuf + loglen);
768      if (result != -2)
769        return result;
770    }
771    break;
772
773  case IPPROTO_ESP:
774    if (logit && loglen < sizeof logbuf) {
775      snprintf(logbuf + loglen, sizeof logbuf - loglen,
776               "ESP: %s ---> ", ncpaddr_ntoa(&srcaddr));
777      loglen += strlen(logbuf + loglen);
778      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
779               ncpaddr_ntoa(&dstaddr), payload);
780      loglen += strlen(logbuf + loglen);
781    }
782    break;
783
784  case IPPROTO_AH:
785    if (logit && loglen < sizeof logbuf) {
786      snprintf(logbuf + loglen, sizeof logbuf - loglen,
787               "AH: %s ---> ", ncpaddr_ntoa(&srcaddr));
788      loglen += strlen(logbuf + loglen);
789      snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
790               ncpaddr_ntoa(&dstaddr), payload + sizeof(u_int32_t));
791      loglen += strlen(logbuf + loglen);
792    }
793    break;
794
795  case IPPROTO_IGMP:
796    if (logit && loglen < sizeof logbuf) {
797      uh = (const struct udphdr *)payload;
798      snprintf(logbuf + loglen, sizeof logbuf - loglen,
799               "IGMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr),
800               ntohs(uh->uh_sport));
801      loglen += strlen(logbuf + loglen);
802      snprintf(logbuf + loglen, sizeof logbuf - loglen,
803               "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport));
804      loglen += strlen(logbuf + loglen);
805    }
806    break;
807
808  case IPPROTO_TCP:
809    th = (const struct tcphdr *)payload;
810    if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
811      pri++;
812
813    if (!frag && ncp_IsUrgentTcpPort(&bundle->ncp, ntohs(th->th_sport),
814                                     ntohs(th->th_dport)))
815      pri++;
816
817    if (logit && loglen < sizeof logbuf) {
818      len = datalen - (th->th_off << 2);
819      snprintf(logbuf + loglen, sizeof logbuf - loglen,
820           "TCP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(th->th_sport));
821      loglen += strlen(logbuf + loglen);
822      snprintf(logbuf + loglen, sizeof logbuf - loglen,
823               "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(th->th_dport));
824      loglen += strlen(logbuf + loglen);
825      n = 0;
826      for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
827        if (th->th_flags & mask) {
828          snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
829          loglen += strlen(logbuf + loglen);
830        }
831        n++;
832      }
833      snprintf(logbuf + loglen, sizeof logbuf - loglen,
834               "  seq:%lx  ack:%lx (%d/%d)",
835               (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
836      loglen += strlen(logbuf + loglen);
837      if ((th->th_flags & TH_SYN) && nb > 40) {
838        const u_short *sp;
839
840        sp = (const u_short *)(payload + 20);
841        if (ntohs(sp[0]) == 0x0204) {
842          snprintf(logbuf + loglen, sizeof logbuf - loglen,
843                   " MSS = %d", ntohs(sp[1]));
844          loglen += strlen(logbuf + loglen);
845        }
846      }
847    }
848    break;
849
850  default:
851    if (prefix)
852      return -2;
853
854    if (logit && loglen < sizeof logbuf) {
855      snprintf(logbuf + loglen, sizeof logbuf - loglen,
856               "<%d>: %s ---> ", cproto, ncpaddr_ntoa(&srcaddr));
857      loglen += strlen(logbuf + loglen);
858      snprintf(logbuf + loglen, sizeof logbuf - loglen,
859               "%s (%d)", ncpaddr_ntoa(&dstaddr), nb);
860      loglen += strlen(logbuf + loglen);
861    }
862    break;
863  }
864
865  if (filter && FilterCheck(packet, family, filter, psecs)) {
866    if (logit)
867      log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
868    result = -1;
869  } else {
870    /* Check Keep Alive filter */
871    if (logit && log_IsKept(LogTCPIP)) {
872      unsigned alivesecs;
873
874      alivesecs = 0;
875      if (filter &&
876          FilterCheck(packet, family, &bundle->filter.alive, &alivesecs))
877        log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
878      else if (psecs != NULL) {
879        if(*psecs == 0)
880          *psecs = alivesecs;
881        if (*psecs) {
882          if (*psecs != alivesecs)
883            log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n",
884                       logbuf, *psecs, alivesecs);
885          else
886            log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs);
887        } else
888          log_Printf(LogTCPIP, "%s\n", logbuf);
889      }
890    }
891    result = pri;
892  }
893
894  if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS))
895    ip_LogDNS(uh, filter->name);
896
897  return result;
898}
899
900static size_t
901ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp, u_int32_t af)
902{
903  ssize_t nw;
904  size_t nb;
905  struct tun_data tun;
906  char *data;
907  unsigned secs, alivesecs;
908
909  nb = m_length(bp);
910  if (nb > sizeof tun.data) {
911    log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %zd, max %d)\n",
912               l->name, nb, (int)(sizeof tun.data));
913    m_freem(bp);
914    return 0;
915  }
916  mbuf_Read(bp, tun.data, nb);
917
918  secs = 0;
919  if (PacketCheck(bundle, af, tun.data, nb, &bundle->filter.in,
920                  NULL, &secs) < 0)
921    return 0;
922
923  alivesecs = 0;
924  if (!FilterCheck(tun.data, af, &bundle->filter.alive, &alivesecs)) {
925    if (secs == 0)
926      secs = alivesecs;
927    bundle_StartIdleTimer(bundle, secs);
928  }
929
930  if (bundle->dev.header) {
931    tun.header.family = htonl(af);
932    nb += sizeof tun - sizeof tun.data;
933    data = (char *)&tun;
934  } else
935    data = tun.data;
936
937  nw = write(bundle->dev.fd, data, nb);
938  if (nw != (ssize_t)nb) {
939    if (nw == -1)
940      log_Printf(LogERROR, "ip_Input: %s: wrote %zd, got %s\n",
941                 l->name, nb, strerror(errno));
942    else
943      log_Printf(LogERROR, "ip_Input: %s: wrote %zd, got %zd\n", l->name, nb,
944	  nw);
945  }
946
947  return nb;
948}
949
950struct mbuf *
951ipv4_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
952{
953  int nb;
954
955  if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
956    log_Printf(LogWARN, "ipv4_Input: IPCP not open - packet dropped\n");
957    m_freem(bp);
958    return NULL;
959  }
960
961  m_settype(bp, MB_IPIN);
962
963  nb = ip_Input(bundle, l, bp, AF_INET);
964  ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
965
966  return NULL;
967}
968
969#ifndef NOINET6
970struct mbuf *
971ipv6_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
972{
973  int nb;
974
975  if (bundle->ncp.ipv6cp.fsm.state != ST_OPENED) {
976    log_Printf(LogWARN, "ipv6_Input: IPV6CP not open - packet dropped\n");
977    m_freem(bp);
978    return NULL;
979  }
980
981  m_settype(bp, MB_IPV6IN);
982
983  nb = ip_Input(bundle, l, bp, AF_INET6);
984  ipv6cp_AddInOctets(&bundle->ncp.ipv6cp, nb);
985
986  return NULL;
987}
988#endif
989