xref: /freebsd/usr.sbin/ppp/ip.c (revision 5ebc7e6281887681c3a348a5a4c902e262ccd656)
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  * $Id: ip.c,v 1.3 1995/03/11 15:18:42 amurai Exp $
21  *
22  *	TODO:
23  *		o Return ICMP message for filterd packet
24  *		  and optionaly record it into log.
25  */
26 #include "fsm.h"
27 #include "lcpproto.h"
28 #include "hdlc.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 "vars.h"
35 #include "filter.h"
36 
37 extern void SendPppFrame();
38 extern int PacketCheck();
39 extern void LcpClose();
40 
41 static struct pppTimer IdleTimer;
42 
43 static void IdleTimeout()
44 {
45   LogPrintf(LOG_PHASE, "Idle timer expired.\n");
46   LcpClose();
47 }
48 
49 /*
50  *  Start Idle timer. If timeout is reached, we call LcpClose() to
51  *  close LCP and link.
52  */
53 void
54 StartIdleTimer()
55 {
56   if (!(mode & MODE_DEDICATED)) {
57     StopTimer(&IdleTimer);
58     IdleTimer.func = IdleTimeout;
59     IdleTimer.load = VarIdleTimeout * SECTICKS;
60     IdleTimer.state = TIMER_STOPPED;
61     StartTimer(&IdleTimer);
62   }
63 }
64 
65 void
66 StopIdleTimer()
67 {
68   StopTimer(&IdleTimer);
69 }
70 
71 /*
72  *  If any IP layer traffic is detected, refresh IdleTimer.
73  */
74 static void
75 RestartIdleTimer()
76 {
77   if (!(mode & MODE_DEDICATED) && ipKeepAlive ) {
78     StartTimer(&IdleTimer);
79     ipIdleSecs = 0;
80   }
81 }
82 
83 static u_short interactive_ports[8] = {
84   0, 513, 0, 0, 0, 21, 0, 23,
85 };
86 
87 #define	INTERACTIVE(p)	(interactive_ports[(p) & 7] == (p))
88 
89 static char *TcpFlags[] = {
90   "FIN", "SYN", "RST", "PSH", "ACK", "URG",
91 };
92 
93 static char *Direction[] = { "INP", "OUT", "OUT", "IN/OUT" };
94 static struct filterent *Filters[] = { ifilters, ofilters, dfilters, afilters };
95 
96 static int
97 PortMatch(op, pport, rport)
98 int op;
99 u_short pport, rport;
100 {
101   switch (op) {
102   case OP_EQ:
103     return(pport == rport);
104   case OP_GT:
105     return(pport > rport);
106   case OP_LT:
107     return(pport < rport);
108   default:
109     return(0);
110   }
111 }
112 
113 /*
114  *  Check a packet against with defined filters
115  */
116 static int
117 FilterCheck(pip, direction)
118 struct ip *pip;
119 int direction;
120 {
121   struct filterent *fp = Filters[direction];
122   int gotinfo, cproto, estab, n;
123   struct tcphdr *th;
124   struct udphdr *uh;
125   struct icmp *ih;
126   char *ptop;
127   u_short sport, dport;
128 
129   if (fp->action) {
130     cproto = gotinfo = estab = 0;
131     sport = dport = 0;
132     for (n = 0; n < MAXFILTERS; n++) {
133       if (fp->action) {
134 #ifdef DEBUG
135 logprintf("rule = %d\n", n);
136 #endif
137 	if ((pip->ip_src.s_addr & fp->smask.s_addr) == fp->saddr.s_addr
138 	    && (pip->ip_dst.s_addr & fp->dmask.s_addr) == fp->daddr.s_addr) {
139 	  if (fp->proto) {
140 	    if (!gotinfo) {
141 	      ptop = (char *)pip + (pip->ip_hl << 2);
142 
143 	      switch (pip->ip_p) {
144 	      case IPPROTO_ICMP:
145 		cproto = P_ICMP; ih = (struct icmp *)ptop;
146 		sport = ih->icmp_type; estab = 1;
147 		break;
148 	      case IPPROTO_UDP:
149 		cproto = P_UDP; uh = (struct udphdr *)ptop;
150 		sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport);
151 		estab = 1;
152 		break;
153 	      case IPPROTO_TCP:
154 		cproto = P_TCP; th = (struct tcphdr *)ptop;
155 		sport = ntohs(th->th_sport); dport = ntohs(th->th_dport);
156 		estab = (th->th_flags & TH_ACK);
157 #ifdef DEBUG
158 if (estab == 0)
159 logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport);
160 #endif
161 		break;
162 	      default:
163 		return(A_DENY);	/* We'll block unknown type of packet */
164 	      }
165 	      gotinfo = 1;
166 #ifdef DEBUG
167 logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n",
168 direction, cproto, fp->opt.srcop, fp->opt.dstop, estab);
169 #endif
170 	    }
171 #ifdef DEBUG
172 	    logprintf("check0: rule = %d, proto = %d, sport = %d, dport = %d\n",
173 		      n, cproto, sport, dport);
174 	    logprintf("check0: action = %d\n", fp->action);
175 #endif
176 	    if (cproto == fp->proto) {
177 	      if ((fp->opt.srcop == OP_NONE ||
178 		  PortMatch(fp->opt.srcop, sport, fp->opt.srcport))
179 	       &&
180 		  (fp->opt.dstop == OP_NONE ||
181 		  PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
182 	       &&
183 		  (fp->opt.estab == 0 || estab)) {
184 		return(fp->action);
185 	      }
186 	    }
187 	  } else {
188 	    /* Address is mached. Make a decision. */
189 #ifdef DEBUG
190 	    logprintf("check1: action = %d\n", fp->action);
191 #endif
192 	    return(fp->action);
193 	  }
194 	}
195       }
196       fp++;
197     }
198 drop:
199     return(A_DENY);	/* No rule is mached. Deny this packet */
200   }
201   return(A_PERMIT);	/* No rule is given. Permit this packet */
202 }
203 
204 static void
205 IcmpError(pip, code)
206 struct ip *pip;
207 int code;
208 {
209 #ifdef notdef
210   struct mbuf *bp;
211 
212   if (pip->ip_p != IPPROTO_ICMP) {
213     bp = mballoc(cnt, MB_IPIN);
214     bcopy(ptr, MBUF_CTOP(bp), cnt);
215     SendPppFrame(PRI_URGENT, bp);
216     RestartIdleTimer();
217     ipOutOctets += cnt;
218   }
219 #endif
220 }
221 
222 /*
223  *  For debugging aid.
224  */
225 int
226 PacketCheck(cp, nb, direction)
227 char *cp;
228 int nb;
229 int direction;
230 {
231   struct ip *pip;
232   struct tcphdr *th;
233   struct udphdr *uh;
234   struct icmp *icmph;
235   char *ptop;
236   int mask, len, n;
237   int logit;
238   int pri = PRI_NORMAL;
239 
240   logit = (loglevel & (1 << LOG_TCPIP));
241 
242   pip = (struct ip *)cp;
243 
244   if (logit) logprintf("%s  ", Direction[direction]);
245 
246   ptop = (cp + (pip->ip_hl << 2));
247 
248   switch (pip->ip_p) {
249   case IPPROTO_ICMP:
250     if (logit) {
251       icmph = (struct icmp *)ptop;
252       logprintf("ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
253       logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), icmph->icmp_type);
254     }
255     break;
256   case IPPROTO_UDP:
257     if (logit) {
258       uh = (struct udphdr *)ptop;
259       logprintf("UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
260       logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
261     }
262     break;
263   case IPPROTO_TCP:
264     th = (struct tcphdr *)ptop;
265     if (pip->ip_tos == IPTOS_LOWDELAY)
266       pri = PRI_FAST;
267     else if (pip->ip_off == 0) {
268       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
269 	 pri = PRI_FAST;
270     }
271 
272     if (logit) {
273       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
274       logprintf("TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
275       logprintf("%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
276       n = 0;
277       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
278 	if (th->th_flags & mask)
279 	  logprintf(" %s", TcpFlags[n]);
280 	n++;
281       }
282       logprintf("  seq:%x  ack:%x (%d/%d)\n",
283 	ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
284       if ((th->th_flags & TH_SYN) && nb > 40) {
285         u_short *sp;
286 
287 	ptop += 20;
288 	sp = (u_short *)ptop;
289 	if (ntohs(sp[0]) == 0x0204)
290 	  logprintf(" MSS = %d\n", ntohs(sp[1]));
291       }
292     }
293     break;
294   }
295   pri = FilterCheck(pip, direction);
296   if (pri & A_DENY) {
297 #ifdef DEBUG
298     logprintf("blocked.\n");
299 #endif
300     if (direction == 0) IcmpError(pip, pri);
301     return(-1);
302   } else {
303     if ( FilterCheck(pip, FL_KEEP ) & A_DENY ) {  /* Check Keep Alive filter */
304 	ipKeepAlive = FALSE;
305     } else {
306 	ipKeepAlive = TRUE;
307     }
308     return(pri);
309   }
310 }
311 
312 void
313 IpInput(bp)
314 struct mbuf *bp;		/* IN: Pointer to IP pakcet */
315 {
316   u_char *cp;
317   struct mbuf *wp;
318   int nb, nw;
319   u_char tunbuff[MAX_MRU];
320 
321   cp = tunbuff;
322   nb = 0;
323   for (wp = bp; wp; wp = wp->next) {		/* Copy to continuois region */
324     bcopy(MBUF_CTOP(wp), cp, wp->cnt);
325     cp += wp->cnt;
326     nb += wp->cnt;
327   }
328 
329   if ( PacketCheck(tunbuff, nb, FL_IN ) < 0) {
330     pfree(bp);
331     return;
332   }
333 
334   ipInOctets += nb;
335   /*
336    *  Pass it to tunnel device
337    */
338   nw = write(tun_out, tunbuff, nb);
339   if (nw != nb)
340     fprintf(stderr, "wrote %d, got %d\r\n");
341   pfree(bp);
342 
343   RestartIdleTimer();
344 }
345 
346 void
347 IpOutput(ptr, cnt)
348 u_char *ptr;			/* IN: Pointer to IP packet */
349 int cnt;			/* IN: Length of packet */
350 {
351   struct mbuf *bp;
352   int pri;
353 
354   if (IpcpFsm.state != ST_OPENED)
355     return;
356 
357   pri = PacketCheck(ptr, cnt, FL_OUT);
358   if (pri >= 0) {
359     bp = mballoc(cnt, MB_IPIN);
360     bcopy(ptr, MBUF_CTOP(bp), cnt);
361     SendPppFrame(pri, bp);
362     RestartIdleTimer();
363     ipOutOctets += cnt;
364   }
365 }
366 
367 static struct mqueue IpOutputQueues[PRI_URGENT+1];
368 
369 void
370 IpEnqueue(pri, ptr, count)
371 int pri;
372 char *ptr;
373 int count;
374 {
375   struct mbuf *bp;
376 
377   bp = mballoc(count, MB_IPQ);
378   bcopy(ptr, MBUF_CTOP(bp), count);
379   Enqueue(&IpOutputQueues[pri], bp);
380 }
381 
382 int
383 IsIpEnqueued()
384 {
385   struct mqueue *queue;
386   int    exist = FALSE;
387   for (queue = &IpOutputQueues[PRI_URGENT]; queue >= IpOutputQueues; queue--) {
388      if ( queue->qlen > 0 ) {
389        exist = TRUE;
390        break;
391      }
392   }
393   return( exist );
394 }
395 
396 void
397 IpStartOutput()
398 {
399   struct mqueue *queue;
400   struct mbuf *bp;
401   int pri, cnt;
402 
403   if (IpcpFsm.state != ST_OPENED)
404     return;
405   pri = PRI_URGENT;
406   for (queue = &IpOutputQueues[PRI_URGENT]; queue >= IpOutputQueues; queue--) {
407     if (queue->top) {
408       bp = Dequeue(queue);
409       if (bp) {
410 	cnt = plength(bp);
411 	SendPppFrame(pri, bp);
412 	RestartIdleTimer();
413 	ipOutOctets += cnt;
414        }
415     }
416     pri--;
417   }
418 }
419