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