Deleted Added
full compact
ip.c (37191) ip.c (37192)
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 *
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.45 1998/06/27 12:03:36 brian Exp $
20 * $Id: ip.c,v 1.46 1998/06/27 14:17:26 brian Exp $
21 *
22 * TODO:
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
25 */
26#include <sys/types.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#ifndef NOALIAS
38#include <alias.h>
39#endif
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46#include "mbuf.h"
47#include "log.h"
48#include "defs.h"
49#include "timer.h"
50#include "fsm.h"
51#include "lqr.h"
52#include "hdlc.h"
21 *
22 * TODO:
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
25 */
26#include <sys/types.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#ifndef NOALIAS
38#include <alias.h>
39#endif
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46#include "mbuf.h"
47#include "log.h"
48#include "defs.h"
49#include "timer.h"
50#include "fsm.h"
51#include "lqr.h"
52#include "hdlc.h"
53#include "loadalias.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#include "bundle.h"
65#include "vjcomp.h"
66#include "tun.h"
67#include "ip.h"
68
69static const u_short interactive_ports[32] = {
70 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
72};
73
74#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
75
76static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
77
78static int
79PortMatch(int op, u_short pport, u_short rport)
80{
81 switch (op) {
82 case OP_EQ:
83 return (pport == rport);
84 case OP_GT:
85 return (pport > rport);
86 case OP_LT:
87 return (pport < rport);
88 default:
89 return (0);
90 }
91}
92
93/*
94 * Check a packet against with defined filters
95 */
96static int
97FilterCheck(struct ip *pip, struct filter *filter)
98{
99 int gotinfo, cproto, estab, syn, finrst, n, len, didname;
100 struct tcphdr *th;
101 struct udphdr *uh;
102 struct icmp *ih;
103 char *ptop;
104 u_short sport, dport;
105 struct filterent *fp = filter->rule;
106 char dbuff[100];
107
108 if (fp->action) {
109 cproto = gotinfo = estab = syn = finrst = didname = 0;
110 sport = dport = 0;
111 for (n = 0; n < MAXFILTERS; n++) {
112 if (fp->action) {
113 /* permit fragments on in and out filter */
114 if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
115 return (A_PERMIT);
116
117 if (!didname)
118 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
119 didname = 1;
120
121 if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
122 (fp->saddr.s_addr & fp->smask.s_addr) &&
123 (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
124 (fp->daddr.s_addr & fp->dmask.s_addr)) {
125 if (fp->proto) {
126 if (!gotinfo) {
127 ptop = (char *) pip + (pip->ip_hl << 2);
128
129 switch (pip->ip_p) {
130 case IPPROTO_ICMP:
131 cproto = P_ICMP;
132 ih = (struct icmp *) ptop;
133 sport = ih->icmp_type;
134 estab = syn = finrst = -1;
135 if (log_IsKept(LogDEBUG))
136 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
137 break;
138 case IPPROTO_UDP:
139 case IPPROTO_IGMP:
140 case IPPROTO_IPIP:
141 cproto = P_UDP;
142 uh = (struct udphdr *) ptop;
143 sport = ntohs(uh->uh_sport);
144 dport = ntohs(uh->uh_dport);
145 estab = syn = finrst = -1;
146 if (log_IsKept(LogDEBUG))
147 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
148 sport, dport);
149 break;
150 case IPPROTO_TCP:
151 cproto = P_TCP;
152 th = (struct tcphdr *) ptop;
153 sport = ntohs(th->th_sport);
154 dport = ntohs(th->th_dport);
155 estab = (th->th_flags & TH_ACK);
156 syn = (th->th_flags & TH_SYN);
157 finrst = (th->th_flags & (TH_FIN|TH_RST));
158 if (log_IsKept(LogDEBUG) && !estab)
159 snprintf(dbuff, sizeof dbuff,
160 "flags = %02x, sport = %d, dport = %d",
161 th->th_flags, sport, dport);
162 break;
163 default:
164 return (A_DENY); /* We'll block unknown type of packet */
165 }
166 if (log_IsKept(LogDEBUG)) {
167 if (estab != -1) {
168 len = strlen(dbuff);
169 snprintf(dbuff + len, sizeof dbuff - len,
170 ", estab = %d, syn = %d, finrst = %d",
171 estab, syn, finrst);
172 }
173 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
174 filter_Proto2Nam(cproto), dbuff);
175 }
176 gotinfo = 1;
177 }
178 if (log_IsKept(LogDEBUG)) {
179 if (fp->opt.srcop != OP_NONE) {
180 snprintf(dbuff, sizeof dbuff, ", src %s %d",
181 filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
182 len = strlen(dbuff);
183 } else
184 len = 0;
185 if (fp->opt.dstop != OP_NONE) {
186 snprintf(dbuff + len, sizeof dbuff - len,
187 ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
188 fp->opt.dstport);
189 } else if (!len)
190 *dbuff = '\0';
191
192 log_Printf(LogDEBUG, " rule = %d: Address match, "
193 "check against proto %s%s, action = %s\n",
194 n, filter_Proto2Nam(fp->proto),
195 dbuff, filter_Action2Nam(fp->action));
196 }
197
198 if (cproto == fp->proto) {
199 if ((fp->opt.srcop == OP_NONE ||
200 PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
201 (fp->opt.dstop == OP_NONE ||
202 PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
203 (fp->opt.estab == 0 || estab) &&
204 (fp->opt.syn == 0 || syn) &&
205 (fp->opt.finrst == 0 || finrst)) {
206 return (fp->action);
207 }
208 }
209 } else {
210 /* Address is mached. Make a decision. */
211 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
212 filter_Action2Nam(fp->action));
213 return (fp->action);
214 }
215 } else
216 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
217 }
218 fp++;
219 }
220 return (A_DENY); /* No rule is mached. Deny this packet */
221 }
222 return (A_PERMIT); /* No rule is given. Permit this packet */
223}
224
225#ifdef notdef
226static void
227IcmpError(struct ip * pip, int code)
228{
229 struct mbuf *bp;
230
231 if (pip->ip_p != IPPROTO_ICMP) {
232 bp = mbuf_Alloc(cnt, MB_IPIN);
233 memcpy(MBUF_CTOP(bp), ptr, cnt);
234 vj_SendFrame(bp);
235 ipcp_AddOutOctets(cnt);
236 }
237}
238#endif
239
240/*
241 * For debugging aid.
242 */
243int
244PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
245{
246 struct ip *pip;
247 struct tcphdr *th;
248 struct udphdr *uh;
249 struct icmp *icmph;
250 char *ptop;
251 int mask, len, n;
252 int pri = PRI_NORMAL;
253 int logit, loglen;
254 char logbuf[200];
255
256 logit = log_IsKept(LogTCPIP) && filter->logok;
257 loglen = 0;
258
259 pip = (struct ip *) cp;
260
261 if (logit && loglen < sizeof logbuf) {
262 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
263 loglen += strlen(logbuf + loglen);
264 }
265 ptop = (cp + (pip->ip_hl << 2));
266
267 switch (pip->ip_p) {
268 case IPPROTO_ICMP:
269 if (logit && loglen < sizeof logbuf) {
270 icmph = (struct icmp *) ptop;
271 snprintf(logbuf + loglen, sizeof logbuf - loglen,
272 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
273 loglen += strlen(logbuf + loglen);
274 snprintf(logbuf + loglen, sizeof logbuf - loglen,
275 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
276 loglen += strlen(logbuf + loglen);
277 }
278 break;
279 case IPPROTO_UDP:
280 if (logit && loglen < sizeof logbuf) {
281 uh = (struct udphdr *) ptop;
282 snprintf(logbuf + loglen, sizeof logbuf - loglen,
283 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
284 loglen += strlen(logbuf + loglen);
285 snprintf(logbuf + loglen, sizeof logbuf - loglen,
286 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
287 loglen += strlen(logbuf + loglen);
288 }
289 break;
290 case IPPROTO_IPIP:
291 if (logit && loglen < sizeof logbuf) {
292 uh = (struct udphdr *) ptop;
293 snprintf(logbuf + loglen, sizeof logbuf - loglen,
294 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
295 loglen += strlen(logbuf + loglen);
296 snprintf(logbuf + loglen, sizeof logbuf - loglen,
297 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
298 loglen += strlen(logbuf + loglen);
299 }
300 break;
301 case IPPROTO_IGMP:
302 if (logit && loglen < sizeof logbuf) {
303 uh = (struct udphdr *) ptop;
304 snprintf(logbuf + loglen, sizeof logbuf - loglen,
305 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
306 loglen += strlen(logbuf + loglen);
307 snprintf(logbuf + loglen, sizeof logbuf - loglen,
308 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
309 loglen += strlen(logbuf + loglen);
310 }
311 break;
312 case IPPROTO_TCP:
313 th = (struct tcphdr *) ptop;
314 if (pip->ip_tos == IPTOS_LOWDELAY)
315 pri = PRI_FAST;
316 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
317 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
318 pri = PRI_FAST;
319 }
320 if (logit && loglen < sizeof logbuf) {
321 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
322 snprintf(logbuf + loglen, sizeof logbuf - loglen,
323 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
324 loglen += strlen(logbuf + loglen);
325 snprintf(logbuf + loglen, sizeof logbuf - loglen,
326 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
327 loglen += strlen(logbuf + loglen);
328 n = 0;
329 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
330 if (th->th_flags & mask) {
331 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
332 loglen += strlen(logbuf + loglen);
333 }
334 n++;
335 }
336 snprintf(logbuf + loglen, sizeof logbuf - loglen,
337 " seq:%x ack:%x (%d/%d)",
338 ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
339 loglen += strlen(logbuf + loglen);
340 if ((th->th_flags & TH_SYN) && nb > 40) {
341 u_short *sp;
342
343 ptop += 20;
344 sp = (u_short *) ptop;
345 if (ntohs(sp[0]) == 0x0204) {
346 snprintf(logbuf + loglen, sizeof logbuf - loglen,
347 " MSS = %d", ntohs(sp[1]));
348 loglen += strlen(logbuf + loglen);
349 }
350 }
351 }
352 break;
353 }
354
355 if ((FilterCheck(pip, filter) & A_DENY)) {
356 if (logit)
357 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
358#ifdef notdef
359 if (direction == 0)
360 IcmpError(pip, pri);
361#endif
362 return (-1);
363 } else {
364 /* Check Keep Alive filter */
365 if (logit) {
366 if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
367 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
368 else
369 log_Printf(LogTCPIP, "%s\n", logbuf);
370 }
371 return (pri);
372 }
373}
374
375void
376ip_Input(struct bundle *bundle, struct mbuf * bp)
377{
378 u_char *cp;
379 struct mbuf *wp;
380 int nb, nw;
381 struct tun_data tun;
382 struct ip *pip = (struct ip *)tun.data;
383 struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
384
385 tun_fill_header(tun, AF_INET);
386 cp = tun.data;
387 nb = 0;
388 for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */
389 if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
390 log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n",
391 mbuf_Length(bp));
392 mbuf_Free(bp);
393 return;
394 }
395 memcpy(cp, MBUF_CTOP(wp), wp->cnt);
396 cp += wp->cnt;
397 nb += wp->cnt;
398 }
399
400#ifndef NOALIAS
401 if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP &&
402 (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) {
403 struct tun_data *frag;
404 int iresult;
405 char *fptr;
406
407 iresult = PacketAliasIn(tun.data, sizeof tun.data);
408 nb = ntohs(((struct ip *) tun.data)->ip_len);
409
410 if (nb > MAX_MRU) {
411 log_Printf(LogWARN, "ip_Input: Problem with IP header length\n");
412 mbuf_Free(bp);
413 return;
414 }
415 if (iresult == PKT_ALIAS_OK
416 || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
417 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
418 mbuf_Free(bp);
419 return;
420 }
421
422 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
423 bundle_StartIdleTimer(bundle);
424
425 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
426
427 nb = ntohs(((struct ip *) tun.data)->ip_len);
428 nb += sizeof tun - sizeof tun.data;
429 nw = write(bundle->dev.fd, &tun, nb);
430 if (nw != nb) {
431 if (nw == -1)
432 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
433 strerror(errno));
434 else
435 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
436 }
437
438 if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
439 while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) {
440 PacketAliasFragmentIn(tun.data, fptr);
441 nb = ntohs(((struct ip *) fptr)->ip_len);
442 frag = (struct tun_data *)
443 ((char *)fptr - sizeof tun + sizeof tun.data);
444 nb += sizeof tun - sizeof tun.data;
445 nw = write(bundle->dev.fd, frag, nb);
446 if (nw != nb) {
447 if (nw == -1)
448 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
449 strerror(errno));
450 else
451 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
452 }
453 free(frag);
454 }
455 }
456 } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
457 nb = ntohs(((struct ip *) tun.data)->ip_len);
458 nb += sizeof tun - sizeof tun.data;
459 frag = (struct tun_data *)malloc(nb);
460 if (frag == NULL)
461 log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n");
462 else {
463 tun_fill_header(*frag, AF_INET);
464 memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
465 PacketAliasSaveFragment(frag->data);
466 }
467 }
468 } else
469#endif /* #ifndef NOALIAS */
470 { /* no aliasing */
471 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
472 mbuf_Free(bp);
473 return;
474 }
475
476 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
477 bundle_StartIdleTimer(bundle);
478
479 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
480
481 nb += sizeof tun - sizeof tun.data;
482 nw = write(bundle->dev.fd, &tun, nb);
483 if (nw != nb) {
484 if (nw == -1)
485 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
486 else
487 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
488 }
489 }
490 mbuf_Free(bp);
491}
492
493static struct mqueue IpOutputQueues[PRI_FAST + 1];
494
495void
496ip_Enqueue(int pri, char *ptr, int count)
497{
498 struct mbuf *bp;
499
500 bp = mbuf_Alloc(count, MB_IPQ);
501 memcpy(MBUF_CTOP(bp), ptr, count);
502 mbuf_Enqueue(&IpOutputQueues[pri], bp);
503}
504
505int
506ip_QueueLen()
507{
508 struct mqueue *queue;
509 int result = 0;
510
511 for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--)
512 result += queue->qlen;
513
514 return result;
515}
516
517int
518ip_FlushPacket(struct link *l, struct bundle *bundle)
519{
520 struct mqueue *queue;
521 struct mbuf *bp;
522 int cnt;
523
524 if (bundle->ncp.ipcp.fsm.state != ST_OPENED)
525 return 0;
526
527 for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--)
528 if (queue->top) {
529 bp = mbuf_Dequeue(queue);
530 if (bp) {
531 struct ip *pip = (struct ip *)MBUF_CTOP(bp);
532
533 cnt = mbuf_Length(bp);
534 vj_SendFrame(l, bp, bundle);
535 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
536 bundle_StartIdleTimer(bundle);
537 ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt);
538 return 1;
539 }
540 }
541
542 return 0;
543}
53#include "throughput.h"
54#include "iplist.h"
55#include "slcompress.h"
56#include "ipcp.h"
57#include "filter.h"
58#include "descriptor.h"
59#include "lcp.h"
60#include "ccp.h"
61#include "link.h"
62#include "mp.h"
63#include "bundle.h"
64#include "vjcomp.h"
65#include "tun.h"
66#include "ip.h"
67
68static const u_short interactive_ports[32] = {
69 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
71};
72
73#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
74
75static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
76
77static int
78PortMatch(int op, u_short pport, u_short rport)
79{
80 switch (op) {
81 case OP_EQ:
82 return (pport == rport);
83 case OP_GT:
84 return (pport > rport);
85 case OP_LT:
86 return (pport < rport);
87 default:
88 return (0);
89 }
90}
91
92/*
93 * Check a packet against with defined filters
94 */
95static int
96FilterCheck(struct ip *pip, struct filter *filter)
97{
98 int gotinfo, cproto, estab, syn, finrst, n, len, didname;
99 struct tcphdr *th;
100 struct udphdr *uh;
101 struct icmp *ih;
102 char *ptop;
103 u_short sport, dport;
104 struct filterent *fp = filter->rule;
105 char dbuff[100];
106
107 if (fp->action) {
108 cproto = gotinfo = estab = syn = finrst = didname = 0;
109 sport = dport = 0;
110 for (n = 0; n < MAXFILTERS; n++) {
111 if (fp->action) {
112 /* permit fragments on in and out filter */
113 if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
114 return (A_PERMIT);
115
116 if (!didname)
117 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
118 didname = 1;
119
120 if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
121 (fp->saddr.s_addr & fp->smask.s_addr) &&
122 (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
123 (fp->daddr.s_addr & fp->dmask.s_addr)) {
124 if (fp->proto) {
125 if (!gotinfo) {
126 ptop = (char *) pip + (pip->ip_hl << 2);
127
128 switch (pip->ip_p) {
129 case IPPROTO_ICMP:
130 cproto = P_ICMP;
131 ih = (struct icmp *) ptop;
132 sport = ih->icmp_type;
133 estab = syn = finrst = -1;
134 if (log_IsKept(LogDEBUG))
135 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
136 break;
137 case IPPROTO_UDP:
138 case IPPROTO_IGMP:
139 case IPPROTO_IPIP:
140 cproto = P_UDP;
141 uh = (struct udphdr *) ptop;
142 sport = ntohs(uh->uh_sport);
143 dport = ntohs(uh->uh_dport);
144 estab = syn = finrst = -1;
145 if (log_IsKept(LogDEBUG))
146 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
147 sport, dport);
148 break;
149 case IPPROTO_TCP:
150 cproto = P_TCP;
151 th = (struct tcphdr *) ptop;
152 sport = ntohs(th->th_sport);
153 dport = ntohs(th->th_dport);
154 estab = (th->th_flags & TH_ACK);
155 syn = (th->th_flags & TH_SYN);
156 finrst = (th->th_flags & (TH_FIN|TH_RST));
157 if (log_IsKept(LogDEBUG) && !estab)
158 snprintf(dbuff, sizeof dbuff,
159 "flags = %02x, sport = %d, dport = %d",
160 th->th_flags, sport, dport);
161 break;
162 default:
163 return (A_DENY); /* We'll block unknown type of packet */
164 }
165 if (log_IsKept(LogDEBUG)) {
166 if (estab != -1) {
167 len = strlen(dbuff);
168 snprintf(dbuff + len, sizeof dbuff - len,
169 ", estab = %d, syn = %d, finrst = %d",
170 estab, syn, finrst);
171 }
172 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
173 filter_Proto2Nam(cproto), dbuff);
174 }
175 gotinfo = 1;
176 }
177 if (log_IsKept(LogDEBUG)) {
178 if (fp->opt.srcop != OP_NONE) {
179 snprintf(dbuff, sizeof dbuff, ", src %s %d",
180 filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
181 len = strlen(dbuff);
182 } else
183 len = 0;
184 if (fp->opt.dstop != OP_NONE) {
185 snprintf(dbuff + len, sizeof dbuff - len,
186 ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
187 fp->opt.dstport);
188 } else if (!len)
189 *dbuff = '\0';
190
191 log_Printf(LogDEBUG, " rule = %d: Address match, "
192 "check against proto %s%s, action = %s\n",
193 n, filter_Proto2Nam(fp->proto),
194 dbuff, filter_Action2Nam(fp->action));
195 }
196
197 if (cproto == fp->proto) {
198 if ((fp->opt.srcop == OP_NONE ||
199 PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
200 (fp->opt.dstop == OP_NONE ||
201 PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
202 (fp->opt.estab == 0 || estab) &&
203 (fp->opt.syn == 0 || syn) &&
204 (fp->opt.finrst == 0 || finrst)) {
205 return (fp->action);
206 }
207 }
208 } else {
209 /* Address is mached. Make a decision. */
210 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
211 filter_Action2Nam(fp->action));
212 return (fp->action);
213 }
214 } else
215 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
216 }
217 fp++;
218 }
219 return (A_DENY); /* No rule is mached. Deny this packet */
220 }
221 return (A_PERMIT); /* No rule is given. Permit this packet */
222}
223
224#ifdef notdef
225static void
226IcmpError(struct ip * pip, int code)
227{
228 struct mbuf *bp;
229
230 if (pip->ip_p != IPPROTO_ICMP) {
231 bp = mbuf_Alloc(cnt, MB_IPIN);
232 memcpy(MBUF_CTOP(bp), ptr, cnt);
233 vj_SendFrame(bp);
234 ipcp_AddOutOctets(cnt);
235 }
236}
237#endif
238
239/*
240 * For debugging aid.
241 */
242int
243PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
244{
245 struct ip *pip;
246 struct tcphdr *th;
247 struct udphdr *uh;
248 struct icmp *icmph;
249 char *ptop;
250 int mask, len, n;
251 int pri = PRI_NORMAL;
252 int logit, loglen;
253 char logbuf[200];
254
255 logit = log_IsKept(LogTCPIP) && filter->logok;
256 loglen = 0;
257
258 pip = (struct ip *) cp;
259
260 if (logit && loglen < sizeof logbuf) {
261 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
262 loglen += strlen(logbuf + loglen);
263 }
264 ptop = (cp + (pip->ip_hl << 2));
265
266 switch (pip->ip_p) {
267 case IPPROTO_ICMP:
268 if (logit && loglen < sizeof logbuf) {
269 icmph = (struct icmp *) ptop;
270 snprintf(logbuf + loglen, sizeof logbuf - loglen,
271 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
272 loglen += strlen(logbuf + loglen);
273 snprintf(logbuf + loglen, sizeof logbuf - loglen,
274 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
275 loglen += strlen(logbuf + loglen);
276 }
277 break;
278 case IPPROTO_UDP:
279 if (logit && loglen < sizeof logbuf) {
280 uh = (struct udphdr *) ptop;
281 snprintf(logbuf + loglen, sizeof logbuf - loglen,
282 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
283 loglen += strlen(logbuf + loglen);
284 snprintf(logbuf + loglen, sizeof logbuf - loglen,
285 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
286 loglen += strlen(logbuf + loglen);
287 }
288 break;
289 case IPPROTO_IPIP:
290 if (logit && loglen < sizeof logbuf) {
291 uh = (struct udphdr *) ptop;
292 snprintf(logbuf + loglen, sizeof logbuf - loglen,
293 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
294 loglen += strlen(logbuf + loglen);
295 snprintf(logbuf + loglen, sizeof logbuf - loglen,
296 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
297 loglen += strlen(logbuf + loglen);
298 }
299 break;
300 case IPPROTO_IGMP:
301 if (logit && loglen < sizeof logbuf) {
302 uh = (struct udphdr *) ptop;
303 snprintf(logbuf + loglen, sizeof logbuf - loglen,
304 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
305 loglen += strlen(logbuf + loglen);
306 snprintf(logbuf + loglen, sizeof logbuf - loglen,
307 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
308 loglen += strlen(logbuf + loglen);
309 }
310 break;
311 case IPPROTO_TCP:
312 th = (struct tcphdr *) ptop;
313 if (pip->ip_tos == IPTOS_LOWDELAY)
314 pri = PRI_FAST;
315 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
316 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
317 pri = PRI_FAST;
318 }
319 if (logit && loglen < sizeof logbuf) {
320 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
321 snprintf(logbuf + loglen, sizeof logbuf - loglen,
322 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
323 loglen += strlen(logbuf + loglen);
324 snprintf(logbuf + loglen, sizeof logbuf - loglen,
325 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
326 loglen += strlen(logbuf + loglen);
327 n = 0;
328 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
329 if (th->th_flags & mask) {
330 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
331 loglen += strlen(logbuf + loglen);
332 }
333 n++;
334 }
335 snprintf(logbuf + loglen, sizeof logbuf - loglen,
336 " seq:%x ack:%x (%d/%d)",
337 ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
338 loglen += strlen(logbuf + loglen);
339 if ((th->th_flags & TH_SYN) && nb > 40) {
340 u_short *sp;
341
342 ptop += 20;
343 sp = (u_short *) ptop;
344 if (ntohs(sp[0]) == 0x0204) {
345 snprintf(logbuf + loglen, sizeof logbuf - loglen,
346 " MSS = %d", ntohs(sp[1]));
347 loglen += strlen(logbuf + loglen);
348 }
349 }
350 }
351 break;
352 }
353
354 if ((FilterCheck(pip, filter) & A_DENY)) {
355 if (logit)
356 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
357#ifdef notdef
358 if (direction == 0)
359 IcmpError(pip, pri);
360#endif
361 return (-1);
362 } else {
363 /* Check Keep Alive filter */
364 if (logit) {
365 if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
366 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
367 else
368 log_Printf(LogTCPIP, "%s\n", logbuf);
369 }
370 return (pri);
371 }
372}
373
374void
375ip_Input(struct bundle *bundle, struct mbuf * bp)
376{
377 u_char *cp;
378 struct mbuf *wp;
379 int nb, nw;
380 struct tun_data tun;
381 struct ip *pip = (struct ip *)tun.data;
382 struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
383
384 tun_fill_header(tun, AF_INET);
385 cp = tun.data;
386 nb = 0;
387 for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */
388 if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
389 log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n",
390 mbuf_Length(bp));
391 mbuf_Free(bp);
392 return;
393 }
394 memcpy(cp, MBUF_CTOP(wp), wp->cnt);
395 cp += wp->cnt;
396 nb += wp->cnt;
397 }
398
399#ifndef NOALIAS
400 if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP &&
401 (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) {
402 struct tun_data *frag;
403 int iresult;
404 char *fptr;
405
406 iresult = PacketAliasIn(tun.data, sizeof tun.data);
407 nb = ntohs(((struct ip *) tun.data)->ip_len);
408
409 if (nb > MAX_MRU) {
410 log_Printf(LogWARN, "ip_Input: Problem with IP header length\n");
411 mbuf_Free(bp);
412 return;
413 }
414 if (iresult == PKT_ALIAS_OK
415 || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
416 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
417 mbuf_Free(bp);
418 return;
419 }
420
421 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
422 bundle_StartIdleTimer(bundle);
423
424 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
425
426 nb = ntohs(((struct ip *) tun.data)->ip_len);
427 nb += sizeof tun - sizeof tun.data;
428 nw = write(bundle->dev.fd, &tun, nb);
429 if (nw != nb) {
430 if (nw == -1)
431 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
432 strerror(errno));
433 else
434 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
435 }
436
437 if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
438 while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) {
439 PacketAliasFragmentIn(tun.data, fptr);
440 nb = ntohs(((struct ip *) fptr)->ip_len);
441 frag = (struct tun_data *)
442 ((char *)fptr - sizeof tun + sizeof tun.data);
443 nb += sizeof tun - sizeof tun.data;
444 nw = write(bundle->dev.fd, frag, nb);
445 if (nw != nb) {
446 if (nw == -1)
447 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
448 strerror(errno));
449 else
450 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
451 }
452 free(frag);
453 }
454 }
455 } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
456 nb = ntohs(((struct ip *) tun.data)->ip_len);
457 nb += sizeof tun - sizeof tun.data;
458 frag = (struct tun_data *)malloc(nb);
459 if (frag == NULL)
460 log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n");
461 else {
462 tun_fill_header(*frag, AF_INET);
463 memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
464 PacketAliasSaveFragment(frag->data);
465 }
466 }
467 } else
468#endif /* #ifndef NOALIAS */
469 { /* no aliasing */
470 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
471 mbuf_Free(bp);
472 return;
473 }
474
475 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
476 bundle_StartIdleTimer(bundle);
477
478 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
479
480 nb += sizeof tun - sizeof tun.data;
481 nw = write(bundle->dev.fd, &tun, nb);
482 if (nw != nb) {
483 if (nw == -1)
484 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
485 else
486 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
487 }
488 }
489 mbuf_Free(bp);
490}
491
492static struct mqueue IpOutputQueues[PRI_FAST + 1];
493
494void
495ip_Enqueue(int pri, char *ptr, int count)
496{
497 struct mbuf *bp;
498
499 bp = mbuf_Alloc(count, MB_IPQ);
500 memcpy(MBUF_CTOP(bp), ptr, count);
501 mbuf_Enqueue(&IpOutputQueues[pri], bp);
502}
503
504int
505ip_QueueLen()
506{
507 struct mqueue *queue;
508 int result = 0;
509
510 for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--)
511 result += queue->qlen;
512
513 return result;
514}
515
516int
517ip_FlushPacket(struct link *l, struct bundle *bundle)
518{
519 struct mqueue *queue;
520 struct mbuf *bp;
521 int cnt;
522
523 if (bundle->ncp.ipcp.fsm.state != ST_OPENED)
524 return 0;
525
526 for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--)
527 if (queue->top) {
528 bp = mbuf_Dequeue(queue);
529 if (bp) {
530 struct ip *pip = (struct ip *)MBUF_CTOP(bp);
531
532 cnt = mbuf_Length(bp);
533 vj_SendFrame(l, bp, bundle);
534 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
535 bundle_StartIdleTimer(bundle);
536 ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt);
537 return 1;
538 }
539 }
540
541 return 0;
542}