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