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