ip.c revision 49140
1/*
2 *		PPP IP Protocol Interface
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: ip.c,v 1.64 1999/06/23 16:48:23 brian Exp $
21 *
22 *	TODO:
23 *		o Return ICMP message for filterd packet
24 *		  and optionaly record it into log.
25 */
26#include <sys/param.h>
27#if defined(__OpenBSD__) || defined(__NetBSD__)
28#include <sys/socket.h>
29#endif
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33#include <netinet/ip_icmp.h>
34#include <netinet/udp.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <sys/un.h>
38
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <termios.h>
44#include <unistd.h>
45
46#include "layer.h"
47#include "proto.h"
48#include "mbuf.h"
49#include "log.h"
50#include "defs.h"
51#include "timer.h"
52#include "fsm.h"
53#include "lqr.h"
54#include "hdlc.h"
55#include "throughput.h"
56#include "iplist.h"
57#include "slcompress.h"
58#include "ipcp.h"
59#include "filter.h"
60#include "descriptor.h"
61#include "lcp.h"
62#include "ccp.h"
63#include "link.h"
64#include "mp.h"
65#ifndef NORADIUS
66#include "radius.h"
67#endif
68#include "bundle.h"
69#include "vjcomp.h"
70#include "tun.h"
71#include "ip.h"
72
73static const u_short interactive_ports[32] = {
74  544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75  80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
76};
77
78#define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
79
80static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
81
82static __inline int
83PortMatch(int op, u_short pport, u_short rport)
84{
85  switch (op) {
86  case OP_EQ:
87    return (pport == rport);
88  case OP_GT:
89    return (pport > rport);
90  case OP_LT:
91    return (pport < rport);
92  default:
93    return (0);
94  }
95}
96
97/*
98 *  Check a packet against a defined filter
99 *  Returns 0 to accept the packet, non-zero to drop the packet
100 *
101 *  If filtering is enabled, the initial fragment of a datagram must
102 *  contain the complete protocol header, and subsequent fragments
103 *  must not attempt to over-write it.
104 */
105static int
106FilterCheck(const struct ip *pip, const struct filter *filter)
107{
108  int gotinfo;			/* true if IP payload decoded */
109  int cproto;			/* P_* protocol type if (gotinfo) */
110  int estab, syn, finrst;	/* TCP state flags if (gotinfo) */
111  u_short sport, dport;		/* src, dest port from packet if (gotinfo) */
112  int n;			/* filter rule to process */
113  int len;			/* bytes used in dbuff */
114  int didname;			/* true if filter header printed */
115  int match;			/* true if condition matched */
116  const struct filterent *fp = filter->rule;
117  char dbuff[100];
118
119  if (fp->f_action == A_NONE)
120    return (0);		/* No rule is given. Permit this packet */
121
122  /* Deny any packet fragment that tries to over-write the header.
123   * Since we no longer have the real header available, punt on the
124   * largest normal header - 20 bytes for TCP without options, rounded
125   * up to the next possible fragment boundary.  Since the smallest
126   * `legal' MTU is 576, and the smallest recommended MTU is 296, any
127   * fragmentation within this range is dubious at best */
128  len = ntohs(pip->ip_off) & IP_OFFMASK;	/* fragment offset */
129  if (len > 0) {		/* Not first fragment within datagram */
130    if (len < (24 >> 3))	/* don't allow fragment to over-write header */
131      return (1);
132    /* permit fragments on in and out filter */
133    return (filter->fragok);
134  }
135
136  cproto = gotinfo = estab = syn = finrst = didname = 0;
137  sport = dport = 0;
138  for (n = 0; n < MAXFILTERS; ) {
139    if (fp->f_action == A_NONE) {
140      n++;
141      fp++;
142      continue;
143    }
144
145    if (!didname) {
146      log_Printf(LogDEBUG, "%s filter:\n", filter->name);
147      didname = 1;
148    }
149
150    match = 0;
151    if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
152	  fp->f_src.mask.s_addr) &&
153	!((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
154	  fp->f_dst.mask.s_addr)) {
155      if (fp->f_proto != P_NONE) {
156	if (!gotinfo) {
157	  const char *ptop = (const char *) pip + (pip->ip_hl << 2);
158	  const struct tcphdr *th;
159	  const struct udphdr *uh;
160	  const struct icmp *ih;
161	  int datalen;	/* IP datagram length */
162
163	  datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
164	  switch (pip->ip_p) {
165	  case IPPROTO_ICMP:
166	    cproto = P_ICMP;
167	    if (datalen < 8)	/* ICMP must be at least 8 octets */
168	      return (1);
169	    ih = (const struct icmp *) ptop;
170	    sport = ih->icmp_type;
171	    estab = syn = finrst = -1;
172	    if (log_IsKept(LogDEBUG))
173	      snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
174	    break;
175	  case IPPROTO_IGMP:
176	    cproto = P_IGMP;
177	    if (datalen < 8)	/* IGMP uses 8-octet messages */
178	      return (1);
179	    estab = syn = finrst = -1;
180	    sport = ntohs(0);
181	    break;
182	  case IPPROTO_UDP:
183	  case IPPROTO_IPIP:
184	    cproto = P_UDP;
185	    if (datalen < 8)	/* UDP header is 8 octets */
186	      return (1);
187	    uh = (const struct udphdr *) ptop;
188	    sport = ntohs(uh->uh_sport);
189	    dport = ntohs(uh->uh_dport);
190	    estab = syn = finrst = -1;
191	    if (log_IsKept(LogDEBUG))
192	      snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
193		       sport, dport);
194	    break;
195	  case IPPROTO_TCP:
196	    cproto = P_TCP;
197	    th = (const struct tcphdr *) ptop;
198	    /* TCP headers are variable length.  The following code
199	     * ensures that the TCP header length isn't de-referenced if
200	     * the datagram is too short
201	     */
202	    if (datalen < 20 || datalen < (th->th_off << 2))
203	      return (1);
204	    sport = ntohs(th->th_sport);
205	    dport = ntohs(th->th_dport);
206	    estab = (th->th_flags & TH_ACK);
207	    syn = (th->th_flags & TH_SYN);
208	    finrst = (th->th_flags & (TH_FIN|TH_RST));
209	    if (log_IsKept(LogDEBUG)) {
210	      if (!estab)
211		snprintf(dbuff, sizeof dbuff,
212			 "flags = %02x, sport = %d, dport = %d",
213			 th->th_flags, sport, dport);
214	      else
215		*dbuff = '\0';
216	    }
217	    break;
218	  default:
219	    return (1);	/* We'll block unknown type of packet */
220	  }
221
222	  if (log_IsKept(LogDEBUG)) {
223	    if (estab != -1) {
224	      len = strlen(dbuff);
225	      snprintf(dbuff + len, sizeof dbuff - len,
226		       ", estab = %d, syn = %d, finrst = %d",
227		       estab, syn, finrst);
228	    }
229	    log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
230		       filter_Proto2Nam(cproto), dbuff);
231	  }
232	  gotinfo = 1;
233	}
234	if (log_IsKept(LogDEBUG)) {
235	  if (fp->f_srcop != OP_NONE) {
236	    snprintf(dbuff, sizeof dbuff, ", src %s %d",
237		     filter_Op2Nam(fp->f_srcop), fp->f_srcport);
238	    len = strlen(dbuff);
239	  } else
240	    len = 0;
241	  if (fp->f_dstop != OP_NONE) {
242	    snprintf(dbuff + len, sizeof dbuff - len,
243		     ", dst %s %d", filter_Op2Nam(fp->f_dstop),
244		     fp->f_dstport);
245	  } else if (!len)
246	    *dbuff = '\0';
247
248	  log_Printf(LogDEBUG, "  rule = %d: Address match, "
249		     "check against proto %s%s, action = %s\n",
250		     n, filter_Proto2Nam(fp->f_proto),
251		     dbuff, filter_Action2Nam(fp->f_action));
252	}
253
254	if (cproto == fp->f_proto) {
255	  if ((fp->f_srcop == OP_NONE ||
256	       PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
257	      (fp->f_dstop == OP_NONE ||
258	       PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
259	      (fp->f_estab == 0 || estab) &&
260	      (fp->f_syn == 0 || syn) &&
261	      (fp->f_finrst == 0 || finrst)) {
262	    match = 1;
263	  }
264	}
265      } else {
266	/* Address is matched and no protocol specified. Make a decision. */
267	log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
268		   filter_Action2Nam(fp->f_action));
269	match = 1;
270      }
271    } else
272      log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
273
274    if (match != fp->f_invert) {
275      /* Take specified action */
276      if (fp->f_action < A_NONE)
277	fp = &filter->rule[n = fp->f_action];
278      else
279	return (fp->f_action != A_PERMIT);
280    } else {
281      n++;
282      fp++;
283    }
284  }
285  return (1);		/* No rule is mached. Deny this packet */
286}
287
288#ifdef notdef
289static void
290IcmpError(struct ip *pip, int code)
291{
292  struct mbuf *bp;
293
294  if (pip->ip_p != IPPROTO_ICMP) {
295    bp = mbuf_Alloc(cnt, MB_IPIN);
296    memcpy(MBUF_CTOP(bp), ptr, cnt);
297    vj_SendFrame(bp);
298    ipcp_AddOutOctets(cnt);
299  }
300}
301#endif
302
303/*
304 *  For debugging aid.
305 */
306int
307PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
308{
309  struct ip *pip;
310  struct tcphdr *th;
311  struct udphdr *uh;
312  struct icmp *icmph;
313  char *ptop;
314  int mask, len, n;
315  int pri = PRI_NORMAL;
316  int logit, loglen;
317  char logbuf[200];
318
319  logit = log_IsKept(LogTCPIP) && filter->logok;
320  loglen = 0;
321
322  pip = (struct ip *) cp;
323
324  if (logit && loglen < sizeof logbuf) {
325    snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
326    loglen += strlen(logbuf + loglen);
327  }
328  ptop = (cp + (pip->ip_hl << 2));
329
330  switch (pip->ip_p) {
331  case IPPROTO_ICMP:
332    if (logit && loglen < sizeof logbuf) {
333      icmph = (struct icmp *) ptop;
334      snprintf(logbuf + loglen, sizeof logbuf - loglen,
335	     "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
336      loglen += strlen(logbuf + loglen);
337      snprintf(logbuf + loglen, sizeof logbuf - loglen,
338	       "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
339      loglen += strlen(logbuf + loglen);
340    }
341    break;
342  case IPPROTO_UDP:
343    if (logit && loglen < sizeof logbuf) {
344      uh = (struct udphdr *) ptop;
345      snprintf(logbuf + loglen, sizeof logbuf - loglen,
346	   "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
347      loglen += strlen(logbuf + loglen);
348      snprintf(logbuf + loglen, sizeof logbuf - loglen,
349	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
350      loglen += strlen(logbuf + loglen);
351    }
352    break;
353  case IPPROTO_IPIP:
354    if (logit && loglen < sizeof logbuf) {
355      uh = (struct udphdr *) ptop;
356      snprintf(logbuf + loglen, sizeof logbuf - loglen,
357	   "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
358      loglen += strlen(logbuf + loglen);
359      snprintf(logbuf + loglen, sizeof logbuf - loglen,
360	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
361      loglen += strlen(logbuf + loglen);
362    }
363    break;
364  case IPPROTO_IGMP:
365    if (logit && loglen < sizeof logbuf) {
366      uh = (struct udphdr *) ptop;
367      snprintf(logbuf + loglen, sizeof logbuf - loglen,
368	   "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
369      loglen += strlen(logbuf + loglen);
370      snprintf(logbuf + loglen, sizeof logbuf - loglen,
371	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
372      loglen += strlen(logbuf + loglen);
373    }
374    break;
375  case IPPROTO_TCP:
376    th = (struct tcphdr *) ptop;
377    if (pip->ip_tos == IPTOS_LOWDELAY)
378      pri = PRI_FAST;
379    else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
380      if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
381	pri = PRI_FAST;
382    }
383    if (logit && loglen < sizeof logbuf) {
384      len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
385      snprintf(logbuf + loglen, sizeof logbuf - loglen,
386	   "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
387      loglen += strlen(logbuf + loglen);
388      snprintf(logbuf + loglen, sizeof logbuf - loglen,
389	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
390      loglen += strlen(logbuf + loglen);
391      n = 0;
392      for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
393	if (th->th_flags & mask) {
394	  snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
395	  loglen += strlen(logbuf + loglen);
396	}
397	n++;
398      }
399      snprintf(logbuf + loglen, sizeof logbuf - loglen,
400	       "  seq:%lx  ack:%lx (%d/%d)",
401	       (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
402      loglen += strlen(logbuf + loglen);
403      if ((th->th_flags & TH_SYN) && nb > 40) {
404	u_short *sp;
405
406	ptop += 20;
407	sp = (u_short *) ptop;
408	if (ntohs(sp[0]) == 0x0204) {
409	  snprintf(logbuf + loglen, sizeof logbuf - loglen,
410		   " MSS = %d", ntohs(sp[1]));
411	  loglen += strlen(logbuf + loglen);
412	}
413      }
414    }
415    break;
416  }
417
418  if (FilterCheck(pip, filter)) {
419    if (logit)
420      log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
421#ifdef notdef
422    if (direction == 0)
423      IcmpError(pip, pri);
424#endif
425    return (-1);
426  } else {
427    /* Check Keep Alive filter */
428    if (logit) {
429      if (FilterCheck(pip, &bundle->filter.alive))
430        log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
431      else
432        log_Printf(LogTCPIP, "%s\n", logbuf);
433    }
434    return (pri);
435  }
436}
437
438struct mbuf *
439ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
440{
441  int nb, nw;
442  struct tun_data tun;
443  struct ip *pip;
444
445  if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
446    log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
447    mbuf_Free(bp);
448    return NULL;
449  }
450
451  mbuf_SetType(bp, MB_IPIN);
452  tun_fill_header(tun, AF_INET);
453  nb = mbuf_Length(bp);
454  if (nb > sizeof tun.data) {
455    log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
456               l->name, nb, (int)(sizeof tun.data));
457    mbuf_Free(bp);
458    return NULL;
459  }
460  mbuf_Read(bp, tun.data, nb);
461
462  if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
463    return NULL;
464
465  pip = (struct ip *)tun.data;
466  if (!FilterCheck(pip, &bundle->filter.alive))
467    bundle_StartIdleTimer(bundle);
468
469  ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
470
471  nb += sizeof tun - sizeof tun.data;
472  nw = write(bundle->dev.fd, &tun, nb);
473  if (nw != nb) {
474    if (nw == -1)
475      log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
476                 l->name, nb, strerror(errno));
477    else
478      log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
479  }
480
481  return NULL;
482}
483
484void
485ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
486{
487  struct mbuf *bp;
488
489  if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0])
490    log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
491  else {
492    /*
493     * We allocate an extra 6 bytes, four at the front and two at the end.
494     * This is an optimisation so that we need to do less work in
495     * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
496     * appending in hdlc_LayerPush().
497     */
498    bp = mbuf_Alloc(count + 6, MB_IPOUT);
499    bp->offset += 4;
500    bp->cnt -= 6;
501    memcpy(MBUF_CTOP(bp), ptr, count);
502    mbuf_Enqueue(&ipcp->Queue[pri], bp);
503  }
504}
505
506void
507ip_DeleteQueue(struct ipcp *ipcp)
508{
509  struct mqueue *queue;
510
511  for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
512    while (queue->top)
513      mbuf_Free(mbuf_Dequeue(queue));
514}
515
516int
517ip_QueueLen(struct ipcp *ipcp)
518{
519  struct mqueue *queue;
520  int result = 0;
521
522  for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
523    result += queue->qlen;
524
525  return result;
526}
527
528int
529ip_PushPacket(struct link *l, struct bundle *bundle)
530{
531  struct ipcp *ipcp = &bundle->ncp.ipcp;
532  struct mqueue *queue;
533  struct mbuf *bp;
534  struct ip *pip;
535  int cnt;
536
537  if (ipcp->fsm.state != ST_OPENED)
538    return 0;
539
540  for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
541    if (queue->top) {
542      bp = mbuf_Contiguous(mbuf_Dequeue(queue));
543      cnt = mbuf_Length(bp);
544      pip = (struct ip *)MBUF_CTOP(bp);
545      if (!FilterCheck(pip, &bundle->filter.alive))
546        bundle_StartIdleTimer(bundle);
547      link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
548      ipcp_AddOutOctets(ipcp, cnt);
549      return 1;
550    }
551
552  return 0;
553}
554