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