xref: /freebsd/usr.sbin/ppp/ip.c (revision a1a4f1a0d87b594d3f17a97dc0127eec1417e6f6)
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$
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 
71 static 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 
78 static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
79 
80 static __inline int
81 PortMatch(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  */
103 static int
104 FilterCheck(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
296 static void
297 IcmpError(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  */
313 int
314 PacketCheck(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 
457 struct mbuf *
458 ip_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 
503 void
504 ip_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 
525 void
526 ip_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 
535 int
536 ip_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 
547 int
548 ip_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