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