1 /*
2 * IP firewalling code. This is taken from 4.4BSD. Please note the
3 * copyright message below. As per the GPL it must be maintained
4 * and the licenses thus do not conflict. While this port is subject
5 * to the GPL I also place my modifications under the original
6 * license in recognition of the original copyright.
7 * -- Alan Cox.
8 *
9 * Ported from BSD to Linux,
10 * Alan Cox 22/Nov/1994.
11 * Zeroing /proc and other additions
12 * Jos Vos 4/Feb/1995.
13 * Merged and included the FreeBSD-Current changes at Ugen's request
14 * (but hey it's a lot cleaner now). Ugen would prefer in some ways
15 * we waited for his final product but since Linux 1.2.0 is about to
16 * appear it's not practical - Read: It works, it's not clean but please
17 * don't consider it to be his standard of finished work.
18 * Alan Cox 12/Feb/1995
19 * Porting bidirectional entries from BSD, fixing accounting issues,
20 * adding struct ip_fwpkt for checking packets with interface address
21 * Jos Vos 5/Mar/1995.
22 * Established connections (ACK check), ACK check on bidirectional rules,
23 * ICMP type check.
24 * Wilfred Mollenvanger 7/7/1995.
25 * TCP attack protection.
26 * Alan Cox 25/8/95, based on information from bugtraq.
27 *
28 * Masquerading functionality
29 *
30 * Copyright (c) 1994 Pauline Middelink
31 *
32 * The pieces which added masquerading functionality are totaly
33 * my responsibility and have nothing to with the original authors
34 * copyright or doing.
35 *
36 * Parts distributed under GPL.
37 *
38 * Fixes:
39 * Pauline Middelink : Added masquerading.
40 * Alan Cox : Fixed an error in the merge.
41 * Thomas Quinot : Fixed port spoofing.
42 * Alan Cox : Cleaned up retransmits in spoofing.
43 *
44 * All the real work was done by .....
45 *
46 */
47
48
49 /*
50 * Copyright (c) 1993 Daniel Boulet
51 * Copyright (c) 1994 Ugen J.S.Antsilevich
52 *
53 * Redistribution and use in source forms, with and without modification,
54 * are permitted provided that this entire comment appears intact.
55 *
56 * Redistribution in binary form may occur without any restrictions.
57 * Obviously, it would be nice if you gave credit where credit is due
58 * but requiring it would be too onerous.
59 *
60 * This software is provided ``AS IS'' without any warranties of any kind.
61 */
62
63 #include <linux/config.h>
64 #include <asm/segment.h>
65 #include <asm/system.h>
66 #include <linux/types.h>
67 #include <linux/kernel.h>
68 #include <linux/sched.h>
69 #include <linux/string.h>
70 #include <linux/errno.h>
71 #include <linux/config.h>
72
73 #include <linux/socket.h>
74 #include <linux/sockios.h>
75 #include <linux/in.h>
76 #include <linux/inet.h>
77 #include <linux/netdevice.h>
78 #include <linux/icmp.h>
79 #include <linux/udp.h>
80 #include <net/ip.h>
81 #include <net/protocol.h>
82 #include <net/route.h>
83 #include <net/tcp.h>
84 #include <net/udp.h>
85 #include <linux/skbuff.h>
86 #include <net/sock.h>
87 #include <net/icmp.h>
88 #include <linux/ip_fw.h>
89 #include <net/checksum.h>
90 #include <linux/proc_fs.h>
91 #include <linux/stat.h>
92
93 /*
94 * Implement IP packet firewall
95 */
96
97 #ifdef CONFIG_IPFIREWALL_DEBUG
98 #define dprintf1(a) printk(a)
99 #define dprintf2(a1,a2) printk(a1,a2)
100 #define dprintf3(a1,a2,a3) printk(a1,a2,a3)
101 #define dprintf4(a1,a2,a3,a4) printk(a1,a2,a3,a4)
102 #else
103 #define dprintf1(a)
104 #define dprintf2(a1,a2)
105 #define dprintf3(a1,a2,a3)
106 #define dprintf4(a1,a2,a3,a4)
107 #endif
108
109 #define print_ip(a) printk("%ld.%ld.%ld.%ld",(ntohl(a)>>24)&0xFF,\
110 (ntohl(a)>>16)&0xFF,\
111 (ntohl(a)>>8)&0xFF,\
112 (ntohl(a))&0xFF);
113
114 #ifdef IPFIREWALL_DEBUG
115 #define dprint_ip(a) print_ip(a)
116 #else
117 #define dprint_ip(a)
118 #endif
119
120 #ifdef CONFIG_IP_FIREWALL
121 struct ip_fw *ip_fw_fwd_chain;
122 struct ip_fw *ip_fw_blk_chain;
123 int ip_fw_blk_policy=IP_FW_F_ACCEPT;
124 int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
125 #endif
126 #ifdef CONFIG_IP_ACCT
127 struct ip_fw *ip_acct_chain;
128 #endif
129
130 #define IP_INFO_BLK 0
131 #define IP_INFO_FWD 1
132 #define IP_INFO_ACCT 2
133
134 #ifdef CONFIG_IP_MASQUERADE
135 /*
136 * Implement IP packet masquerading
137 */
138
139 static unsigned short masq_port = PORT_MASQ_BEGIN;
140 static const char *strProt[] = {"UDP","TCP"};
141 struct ip_masq *ip_msq_hosts;
142
143 #endif
144
145 /*
146 * Returns 1 if the port is matched by the vector, 0 otherwise
147 */
148
149 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
150 {
151 if (!nports)
152 return 1;
153 if ( range_flag )
154 {
155 if ( portptr[0] <= port && port <= portptr[1] )
156 {
157 return( 1 );
158 }
159 nports -= 2;
160 portptr += 2;
161 }
162 while ( nports-- > 0 )
163 {
164 if ( *portptr++ == port )
165 {
166 return( 1 );
167 }
168 }
169 return(0);
170 }
171
172 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
173
174
175 /*
176 * Returns 0 if packet should be dropped, 1 if it should be accepted,
177 * and -1 if an ICMP host unreachable packet should be sent.
178 * Also does accounting so you can feed it the accounting chain.
179 * If opt is set to 1, it means that we do this for accounting
180 * purposes (searches all entries and handles fragments different).
181 * If opt is set to 2, it doesn't count a matching packet, which
182 * is used when calling this for checking purposes (IP_FW_CHK_*).
183 */
184
185
186 int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
187 {
188 struct ip_fw *f;
189 struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
190 struct udphdr *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
191 struct icmphdr *icmp=(struct icmphdr *)((unsigned long *)ip+ip->ihl);
192 __u32 src, dst;
193 __u16 src_port=0, dst_port=0, icmp_type=0;
194 unsigned short f_prt=0, prt;
195 char notcpsyn=1, notcpack=1, match;
196 unsigned short f_flag;
197 unsigned short offset;
198
199 /*
200 * If the chain is empty follow policy. The BSD one
201 * accepts anything giving you a time window while
202 * flushing and rebuilding the tables.
203 */
204
205 src = ip->saddr;
206 dst = ip->daddr;
207
208 /*
209 * This way we handle fragmented packets.
210 * we ignore all fragments but the first one
211 * so the whole packet can't be reassembled.
212 * This way we relay on the full info which
213 * stored only in first packet.
214 *
215 * Note that this theoretically allows partial packet
216 * spoofing. Not very dangerous but paranoid people may
217 * wish to play with this. It also allows the so called
218 * "fragment bomb" denial of service attack on some types
219 * of system.
220 */
221
222 offset = ntohs(ip->frag_off) & IP_OFFSET;
223
224 /*
225 * Don't allow a fragment of TCP 8 bytes in. Nobody
226 * normal causes this. Its a cracker trying to break
227 * in by doing a flag overwrite to pass the direction
228 * checks.
229 */
230
231 if (offset == 1 && ip->protocol == IPPROTO_TCP)
232 return FW_BLOCK;
233
234 if (offset!=0 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
235 ip->protocol == IPPROTO_UDP))
236 return FW_ACCEPT;
237
238 /*
239 * Header fragment for TCP is too small to check the bits.
240 */
241
242 if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))
243 return FW_BLOCK;
244
245 /*
246 * Too short.
247 */
248
249 else if(ntohs(ip->tot_len)<8+(ip->ihl<<2))
250 return FW_BLOCK;
251
252 src = ip->saddr;
253 dst = ip->daddr;
254
255 /*
256 * If we got interface from which packet came
257 * we can use the address directly. This is unlike
258 * 4.4BSD derived systems that have an address chain
259 * per device. We have a device per address with dummy
260 * devices instead.
261 */
262
263 dprintf1("Packet ");
264 switch(ip->protocol)
265 {
266 case IPPROTO_TCP:
267 dprintf1("TCP ");
268 /* ports stay 0 if it is not the first fragment */
269 if (offset!=0) {
270 src_port=ntohs(tcp->source);
271 dst_port=ntohs(tcp->dest);
272 if(tcp->ack)
273 /* We *DO* have ACK, value FALSE */
274 notcpack=0;
275 if(tcp->syn && notcpack)
276 /* We *DO* have SYN, value FALSE */
277 notcpsyn=0;
278 }
279 prt=IP_FW_F_TCP;
280 break;
281 case IPPROTO_UDP:
282 dprintf1("UDP ");
283 /* ports stay 0 if it is not the first fragment */
284 if (offset!=0) {
285 src_port=ntohs(udp->source);
286 dst_port=ntohs(udp->dest);
287 }
288 prt=IP_FW_F_UDP;
289 break;
290 case IPPROTO_ICMP:
291 icmp_type=(__u16)(icmp->type);
292 dprintf2("ICMP:%d ",icmp_type);
293 prt=IP_FW_F_ICMP;
294 break;
295 default:
296 dprintf2("p=%d ",ip->protocol);
297 prt=IP_FW_F_ALL;
298 break;
299 }
300 #ifdef CONFIG_IP_FIREWALL_DEBUG
301 dprint_ip(ip->saddr);
302
303 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
304 /* This will print 0 when it is not the first fragment! */
305 dprintf2(":%d ", src_port);
306 dprint_ip(ip->daddr);
307 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
308 /* This will print 0 when it is not the first fragment! */
309 dprintf2(":%d ",dst_port);
310 dprintf1("\n");
311 #endif
312
313 for (f=chain;f;f=f->fw_next)
314 {
315 /*
316 * This is a bit simpler as we don't have to walk
317 * an interface chain as you do in BSD - same logic
318 * however.
319 */
320
321 /*
322 * Match can become 0x01 (a "normal" match was found),
323 * 0x02 (a reverse match was found), and 0x03 (the
324 * IP addresses match in both directions).
325 * Now we know in which direction(s) we should look
326 * for a match for the TCP/UDP ports. Both directions
327 * might match (e.g., when both addresses are on the
328 * same network for which an address/mask is given), but
329 * the ports might only match in one direction.
330 * This was obviously wrong in the original BSD code.
331 */
332 match = 0x00;
333
334 if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
335 && (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
336 /* normal direction */
337 match |= 0x01;
338
339 if ((f->fw_flg & IP_FW_F_BIDIR) &&
340 (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
341 && (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
342 /* reverse direction */
343 match |= 0x02;
344
345 if (match)
346 {
347 /*
348 * Look for a VIA match
349 */
350 if(f->fw_via.s_addr && rif)
351 {
352 if(rif->pa_addr!=f->fw_via.s_addr)
353 continue; /* Mismatch */
354 }
355 /*
356 * Drop through - this is a match
357 */
358 }
359 else
360 continue;
361
362 /*
363 * Ok the chain addresses match.
364 */
365
366 f_prt=f->fw_flg&IP_FW_F_KIND;
367 if (f_prt!=IP_FW_F_ALL)
368 {
369 /*
370 * This is actually buggy as if you set SYN flag
371 * on UDP or ICMP firewall it will never work,but
372 * actually it is a concern of software which sets
373 * firewall entries.
374 */
375
376 if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
377 continue;
378
379 /*
380 * When a bidirectional rule is used we only check
381 * for ack bits on reverse matches. This way it's
382 * easy to set up rules which only allow connections
383 * initiated from "normal" match adresses.
384 */
385
386 if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
387 if(f->fw_flg&IP_FW_F_BIDIR) {
388 if(match & 0x02)
389 continue;
390 } else
391 continue;
392
393 /*
394 * Specific firewall - packet's protocol
395 * must match firewall's.
396 */
397
398 if(prt!=f_prt)
399 continue;
400
401 if((prt==IP_FW_F_ICMP &&
402 ! port_match(&f->fw_pts[0], f->fw_nsp,
403 icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
404 !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
405 port_match(&f->fw_pts[0], f->fw_nsp, src_port,
406 f->fw_flg&IP_FW_F_SRNG) &&
407 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
408 f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
409 port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
410 f->fw_flg&IP_FW_F_SRNG) &&
411 port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
412 f->fw_flg&IP_FW_F_DRNG))))
413 {
414 continue;
415 }
416 }
417 #ifdef CONFIG_IP_FIREWALL_VERBOSE
418 /*
419 * VERY ugly piece of code which actually
420 * makes kernel printf for denied packets...
421 */
422
423 if (f->fw_flg & IP_FW_F_PRN)
424 {
425 if(opt != 1) {
426 if(f->fw_flg&IP_FW_F_ACCEPT)
427 printk("Accept ");
428 else if(f->fw_flg&IP_FW_F_ICMPRPL)
429 printk("Reject ");
430 else
431 printk("Deny ");
432 }
433 switch(ip->protocol)
434 {
435 case IPPROTO_TCP:
436 printk("TCP ");
437 break;
438 case IPPROTO_UDP:
439 printk("UDP ");
440 case IPPROTO_ICMP:
441 printk("ICMP ");
442 break;
443 default:
444 printk("p=%d ",ip->protocol);
445 break;
446 }
447 print_ip(ip->saddr);
448 if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
449 printk(":%d", src_port);
450 printk(" ");
451 print_ip(ip->daddr);
452 if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
453 printk(":%d",dst_port);
454 printk("\n");
455 }
456 #endif
457 if (opt != 2) {
458 f->fw_bcnt+=ntohs(ip->tot_len);
459 f->fw_pcnt++;
460 }
461 if (opt != 1)
462 break;
463 } /* Loop */
464
465 if(opt == 1)
466 return 0;
467
468 /*
469 * We rely on policy defined in the rejecting entry or, if no match
470 * was found, we rely on the general policy variable for this type
471 * of firewall.
472 */
473
474 if(f!=NULL) /* A match was found */
475 f_flag=f->fw_flg;
476 else
477 f_flag=policy;
478 if(f_flag&IP_FW_F_ACCEPT)
479 return ((f_flag&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT);
480 if(f_flag&IP_FW_F_ICMPRPL)
481 return FW_REJECT;
482 return FW_BLOCK;
483 }
484
485 #ifdef CONFIG_IP_MASQUERADE
486
487 static void masq_expire(unsigned long data)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
488 {
489 struct ip_masq *ms = (struct ip_masq *)data;
490 struct ip_masq *old,*cur;
491 unsigned long flags;
492
493 #ifdef DEBUG_MASQ
494 printk("Masqueraded %s %lX:%X expired\n",
495 strProt[ms->protocol==IPPROTO_TCP],
496 ntohl(ms->src),ntohs(ms->sport));
497 #endif
498
499 save_flags(flags);
500 cli();
501
502 /* delete from list of hosts */
503 old = NULL;
504 cur = ip_msq_hosts;
505 while (cur!=NULL) {
506 if (cur==ms) {
507 if (old==NULL) ip_msq_hosts = ms->next;
508 else old->next = ms->next;
509 kfree_s(ms,sizeof(*ms));
510 break;
511 }
512 old = cur;
513 cur=cur->next;
514 }
515 restore_flags(flags);
516 }
517
518 /*
519 * Create a new masquerade list entry, also allocate an
520 * unused mport, keeping the portnumber between the
521 * given boundaries MASQ_BEGIN and MASQ_END.
522 *
523 * FIXME: possible deadlock if all free ports are exhausted!
524 */
525 static struct ip_masq *alloc_masq_entry(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
526 {
527 struct ip_masq *ms, *mst;
528 unsigned long flags;
529
530 ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
531 if (ms==NULL)
532 return NULL;
533
534 memset(ms,0,sizeof(*ms));
535 init_timer(&ms->timer);
536 ms->timer.data = (unsigned long)ms;
537 ms->timer.function = masq_expire;
538
539 save_flags(flags);
540 cli();
541 do
542 {
543 /* Try the next available port number */
544 ms->mport = htons(masq_port++);
545 if (masq_port==PORT_MASQ_END)
546 masq_port = PORT_MASQ_BEGIN;
547
548 /* Now hunt through the used ports to see if
549 * this port is in use... */
550 mst = ip_msq_hosts;
551 while (mst && mst->mport!=ms->mport)
552 mst = mst->next;
553 }
554 while (mst!=NULL);
555
556 /* add new entry in front of list to minimize lookup-time */
557 ms->next = ip_msq_hosts;
558 ip_msq_hosts = ms;
559 restore_flags(flags);
560
561 return ms;
562 }
563
564 /*
565 * When passing an FTP 'PORT' command, try to replace the IP
566 * address with an newly assigned (masquereded) port on this
567 * host, so the ftp-data connect FROM the site will succeed...
568 *
569 * Also, when the size of the packet changes, create an delta
570 * offset, which will be added to every th->seq (and subtracted for
571 * (th->acqseq) whose seq > init_seq.
572 *
573 * Not for the faint of heart!
574 */
575
576 static struct sk_buff *revamp(struct sk_buff *skb, struct device *dev, struct ip_masq *ftp)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
577 {
578 struct iphdr *iph = skb->h.iph;
579 struct tcphdr *th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
580 struct sk_buff *skb2;
581 char *p, *data = (char *)&th[1];
582 unsigned char p1,p2,p3,p4,p5,p6;
583 unsigned long from;
584 unsigned short port;
585 struct ip_masq *ms;
586 char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
587 int diff;
588
589 /*
590 * Adjust seq and ack_seq with delta-offset for
591 * the packets AFTER this one...
592 */
593 if (ftp->delta && after(ftp->init_seq,th->seq))
594 {
595 th->seq += ftp->delta;
596 /* th->ack_seq += ftp->delta;*/
597 }
598
599 while (skb->len - ((unsigned char *)data - skb->h.raw) > 18)
600 {
601 if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5))
602 {
603 data ++;
604 continue;
605 }
606 p = data+5;
607 p1 = simple_strtoul(data+5,&data,10);
608 if (*data!=',')
609 continue;
610 p2 = simple_strtoul(data+1,&data,10);
611 if (*data!=',')
612 continue;
613 p3 = simple_strtoul(data+1,&data,10);
614 if (*data!=',')
615 continue;
616 p4 = simple_strtoul(data+1,&data,10);
617 if (*data!=',')
618 continue;
619 p5 = simple_strtoul(data+1,&data,10);
620 if (*data!=',')
621 continue;
622 p6 = simple_strtoul(data+1,&data,10);
623 if (*data!='\r' && *data!='\n')
624 continue;
625
626 from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
627 port = (p5<<8) | p6;
628 printk("PORT %lX:%X detected\n",from,port);
629
630 /*
631 * Now create an masquerade entry for it
632 */
633 ms = alloc_masq_entry();
634 if (ms==NULL)
635 return skb;
636 ms->protocol = IPPROTO_TCP;
637 ms->src = htonl(from); /* derived from PORT cmd */
638 ms->sport = htons(port); /* derived from PORT cmd */
639 ms->dst = iph->daddr;
640 ms->dport = htons(20); /* ftp-data */
641 ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP_FIN;
642 add_timer(&ms->timer);
643
644 /*
645 * Replace the old PORT with the new one
646 */
647 from = ntohl(dev->pa_addr);
648 port = ntohs(ms->mport);
649 sprintf(buf,"%ld,%ld,%ld,%ld,%d,%d",
650 from>>24&255,from>>16&255,from>>8&255,from&255,
651 port>>8&255,port&255);
652
653 /*
654 * Calculate required delta-offset to keep TCP happy
655 */
656
657 diff = strlen(buf) - (data-p);
658
659 /*
660 * No shift.
661 */
662
663 if (diff==0)
664 {
665 /*
666 * simple case, just replace the old PORT cmd
667 */
668 ftp->init_seq = 0;
669 memcpy(p,buf,strlen(buf));
670 return skb;
671 }
672
673 /*
674 * If the PORT command we have fiddled is the first, or is a
675 * resend don't do the delta shift again. Doesn't work for
676 * pathological cases, but we would need a history for that.
677 * Also fails if you send 2^31 bytes of data down the link
678 * after the first port command.
679 *
680 * FIXME: use ftp->init_seq_valid - 0 is a valid sequence.
681 */
682
683 if(!ftp->init_seq || after(ftp->init_seq,th->seq))
684 ftp->delta+=diff;
685 /*
686 * Sizes differ, make a copy
687 */
688 printk("MASQUERADE: resizing needed for %d bytes (%ld)\n",ftp->delta, skb->len);
689 if (!ftp->init_seq)
690 ftp->init_seq = th->seq;
691
692 skb2 = alloc_skb(MAX_HEADER + skb->len+ftp->delta, GFP_ATOMIC);
693 if (skb2 == NULL) {
694 printk("MASQUERADE: No memory available\n");
695 return skb;
696 }
697 skb2->free = skb->free;
698 skb_reserve(skb2,MAX_HEADER);
699 skb_put(skb2,skb->len + ftp->delta);
700 /* skb2->h.raw = &skb2->data[skb->h.raw - skb->data];*/
701 skb2->h.raw = skb2->data + (skb->h.raw - skb->data);
702 iph=skb2->h.iph;
703
704 /*
705 * Copy the packet data into the new buffer.
706 * Thereby replacing the PORT cmd.
707 */
708 memcpy(skb2->data, skb->data, (p - (char *)skb->data));
709 memcpy(&skb2->data[(p - (char *)skb->data)], buf, strlen(buf));
710 memcpy(&skb2->data[(p - (char *)skb->data) + strlen(buf)], data,
711 skb->len - (data-(char *)skb->data));
712
713 /*
714 * Problem, how to replace the new skb with old one,
715 * preferably inplace, so all the pointers in the
716 * calling tree keep ok :(
717 */
718 kfree_skb(skb, FREE_WRITE);
719 return skb2;
720 }
721 return skb;
722 }
723
724 static void recalc_check(struct udphdr *uh, unsigned long saddr,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
725 unsigned long daddr, int len)
726 {
727 uh->check=0;
728 uh->check=csum_tcpudp_magic(saddr,daddr,len,
729 IPPROTO_UDP, csum_partial((char *)uh,len,0));
730 if(uh->check==0)
731 uh->check=0xFFFF;
732 }
733
734 void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
735 {
736 struct sk_buff *skb=*skb_ptr;
737 struct iphdr *iph = skb->h.iph;
738 unsigned short *portptr;
739 struct ip_masq *ms;
740 int size;
741
742 /*
743 * We can only masquerade protocols with ports...
744 */
745
746 if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
747 return;
748
749 /*
750 * Now hunt the list to see if we have an old entry
751 */
752
753 portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
754 ms = ip_msq_hosts;
755
756 #ifdef DEBUG_MASQ
757 printk("Outgoing %s %lX:%X -> %lX:%X\n",
758 strProt[iph->protocol==IPPROTO_TCP],
759 ntohl(iph->saddr), ntohs(portptr[0]),
760 ntohl(iph->daddr), ntohs(portptr[1]));
761 #endif
762 while (ms!=NULL)
763 {
764 if (iph->protocol == ms->protocol &&
765 iph->saddr == ms->src && iph->daddr == ms->dst &&
766 portptr[0] == ms->sport && portptr[1] == ms->dport)
767 {
768 del_timer(&ms->timer);
769 break;
770 }
771 ms = ms->next;
772 }
773
774 /*
775 * Nope, not found, create a new entry for it
776 */
777
778 if (ms==NULL)
779 {
780 ms = alloc_masq_entry();
781 if (ms==NULL)
782 {
783 printk("MASQUERADE: no memory left !\n");
784 return;
785 }
786 ms->protocol = iph->protocol;
787 ms->src = iph->saddr;
788 ms->dst = iph->daddr;
789 ms->sport = portptr[0];
790 ms->dport = portptr[1];
791 }
792
793 /*
794 * Change the fragments origin
795 */
796
797 size = skb->len - ((unsigned char *)portptr - skb->h.raw);
798 iph->saddr = dev->pa_addr; /* my own address */
799 portptr[0] = ms->mport;
800
801 /*
802 * Adjust packet accordingly to protocol
803 */
804
805 if (iph->protocol==IPPROTO_UDP)
806 {
807 ms->timer.expires = jiffies+MASQUERADE_EXPIRE_UDP;
808 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
809 }
810 else
811 {
812 struct tcphdr *th;
813 if (portptr[1]==htons(21))
814 {
815 skb = revamp(*skb_ptr, dev, ms);
816 *skb_ptr = skb;
817 iph = skb->h.iph;
818 portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
819 size = skb->len - ((unsigned char *)portptr-skb->h.raw);
820 }
821 th = (struct tcphdr *)portptr;
822
823 /*
824 * Timeout depends if FIN packet was seen
825 */
826 if (ms->sawfin || th->fin)
827 {
828 ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP_FIN;
829 ms->sawfin = 1;
830 }
831 else ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP;
832
833 tcp_send_check(th,iph->saddr,iph->daddr,size,skb->sk);
834 }
835 add_timer(&ms->timer);
836 ip_send_check(iph);
837
838 #ifdef DEBUG_MASQ
839 printk("O-routed from %lX:%X over %s\n",ntohl(dev->pa_addr),ntohs(ms->mport),dev->name);
840 #endif
841 }
842
843 /*
844 * Check if it's an masqueraded port, look it up,
845 * and send it on it's way...
846 *
847 * Better not have many hosts using the designated portrange
848 * as 'normal' ports, or you'll be spending lots of time in
849 * this function.
850 */
851
852 int ip_fw_demasquerade(struct sk_buff *skb_ptr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
853 {
854 struct iphdr *iph = skb_ptr->h.iph;
855 unsigned short *portptr;
856 struct ip_masq *ms;
857 struct tcphdr *th = (struct tcphdr *)(skb_ptr->h.raw+(iph->ihl<<2));
858
859 if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
860 return 0;
861
862 portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
863 if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
864 ntohs(portptr[1]) > PORT_MASQ_END)
865 return 0;
866
867 #ifdef DEBUG_MASQ
868 printk("Incoming %s %lX:%X -> %lX:%X\n",
869 strProt[iph->protocol==IPPROTO_TCP],
870 ntohl(iph->saddr), ntohs(portptr[0]),
871 ntohl(iph->daddr), ntohs(portptr[1]));
872 #endif
873 /*
874 * reroute to original host:port if found...
875 *
876 * NB. Cannot check destination address, just for the incoming port.
877 * reason: archie.doc.ac.uk has 6 interfaces, you send to
878 * phoenix and get a reply from any other interface(==dst)!
879 *
880 * [Only for UDP] - AC
881 */
882 ms = ip_msq_hosts;
883 while (ms!=NULL)
884 {
885 if (iph->protocol==ms->protocol &&
886 (iph->saddr==ms->dst || iph->protocol==IPPROTO_UDP) &&
887 portptr[0]==ms->dport &&
888 portptr[1]==ms->mport)
889 {
890 int size = skb_ptr->len - ((unsigned char *)portptr - skb_ptr->h.raw);
891 iph->daddr = ms->src;
892 portptr[1] = ms->sport;
893
894 /*
895 * Yug! adjust UDP/TCP and IP checksums
896 */
897 if (iph->protocol==IPPROTO_UDP)
898 recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
899 else
900 {
901 /*
902 * Adjust seq and ack_seq with delta-offset for
903 * the packets AFTER this one...
904 */
905 if (ms->delta && after(ms->init_seq,th->ack_seq))
906 {
907 /* th->seq += ms->delta;*/
908 th->ack_seq -= ms->delta;
909 }
910 tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb_ptr->sk);
911 }
912 ip_send_check(iph);
913 #ifdef DEBUG_MASQ
914 printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
915 #endif
916 return 1;
917 }
918 ms = ms->next;
919 }
920
921 /* sorry, all this trouble for a no-hit :) */
922 return 0;
923 }
924 #endif
925
926
927
928 static void zero_fw_chain(struct ip_fw *chainptr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
929 {
930 struct ip_fw *ctmp=chainptr;
931 while(ctmp)
932 {
933 ctmp->fw_pcnt=0L;
934 ctmp->fw_bcnt=0L;
935 ctmp=ctmp->fw_next;
936 }
937 }
938
939 static void free_fw_chain(struct ip_fw *volatile* chainptr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
940 {
941 unsigned long flags;
942 save_flags(flags);
943 cli();
944 while ( *chainptr != NULL )
945 {
946 struct ip_fw *ftmp;
947 ftmp = *chainptr;
948 *chainptr = ftmp->fw_next;
949 kfree_s(ftmp,sizeof(*ftmp));
950 }
951 restore_flags(flags);
952 }
953
954 /* Volatiles to keep some of the compiler versions amused */
955
956 static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
957 {
958 struct ip_fw *ftmp;
959 struct ip_fw *chtmp=NULL;
960 struct ip_fw *volatile chtmp_prev=NULL;
961 unsigned long flags;
962 unsigned long m_src_mask,m_dst_mask;
963 unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
964 unsigned short n_sr,n_dr,o_sr,o_dr;
965 unsigned short oldkind,newkind;
966 int addb4=0;
967 int n_o,n_n;
968
969 save_flags(flags);
970
971 ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
972 if ( ftmp == NULL )
973 {
974 #ifdef DEBUG_CONFIG_IP_FIREWALL
975 printk("ip_fw_ctl: malloc said no\n");
976 #endif
977 return( ENOMEM );
978 }
979
980 memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
981
982 ftmp->fw_pcnt=0L;
983 ftmp->fw_bcnt=0L;
984
985 ftmp->fw_next = NULL;
986
987 cli();
988
989 if (*chainptr==NULL)
990 {
991 *chainptr=ftmp;
992 }
993 else
994 {
995 chtmp_prev=NULL;
996 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
997 {
998 addb4=0;
999 newkind=ftmp->fw_flg & IP_FW_F_KIND;
1000 oldkind=chtmp->fw_flg & IP_FW_F_KIND;
1001
1002 if (newkind!=IP_FW_F_ALL
1003 && oldkind!=IP_FW_F_ALL
1004 && oldkind!=newkind)
1005 {
1006 chtmp_prev=chtmp;
1007 continue;
1008 }
1009
1010 /*
1011 * Very very *UGLY* code...
1012 * Sorry,but i had to do this....
1013 */
1014
1015 n_sa=ntohl(ftmp->fw_src.s_addr);
1016 n_da=ntohl(ftmp->fw_dst.s_addr);
1017 n_sm=ntohl(ftmp->fw_smsk.s_addr);
1018 n_dm=ntohl(ftmp->fw_dmsk.s_addr);
1019
1020 o_sa=ntohl(chtmp->fw_src.s_addr);
1021 o_da=ntohl(chtmp->fw_dst.s_addr);
1022 o_sm=ntohl(chtmp->fw_smsk.s_addr);
1023 o_dm=ntohl(chtmp->fw_dmsk.s_addr);
1024
1025 m_src_mask = o_sm & n_sm;
1026 m_dst_mask = o_dm & n_dm;
1027
1028 if ((o_sa & m_src_mask) == (n_sa & m_src_mask))
1029 {
1030 if (n_sm > o_sm)
1031 addb4++;
1032 if (n_sm < o_sm)
1033 addb4--;
1034 }
1035
1036 if ((o_da & m_dst_mask) == (n_da & m_dst_mask))
1037 {
1038 if (n_dm > o_dm)
1039 addb4++;
1040 if (n_dm < o_dm)
1041 addb4--;
1042 }
1043
1044 if (((o_da & o_dm) == (n_da & n_dm))
1045 &&((o_sa & o_sm) == (n_sa & n_sm)))
1046 {
1047 if (newkind!=IP_FW_F_ALL &&
1048 oldkind==IP_FW_F_ALL)
1049 addb4++;
1050 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
1051 || oldkind==IP_FW_F_UDP))
1052 {
1053
1054 /*
1055 * Here the main idea is to check the size
1056 * of port range which the frwl covers
1057 * We actually don't check their values but
1058 * just the wideness of range they have
1059 * so that less wide ranges or single ports
1060 * go first and wide ranges go later. No ports
1061 * at all treated as a range of maximum number
1062 * of ports.
1063 */
1064
1065 if (ftmp->fw_flg & IP_FW_F_SRNG)
1066 n_sr=ftmp->fw_pts[1]-ftmp->fw_pts[0];
1067 else
1068 n_sr=(ftmp->fw_nsp)?
1069 ftmp->fw_nsp : 0xFFFF;
1070
1071 if (chtmp->fw_flg & IP_FW_F_SRNG)
1072 o_sr=chtmp->fw_pts[1]-chtmp->fw_pts[0];
1073 else
1074 o_sr=(chtmp->fw_nsp)?chtmp->fw_nsp : 0xFFFF;
1075
1076 if (n_sr<o_sr)
1077 addb4++;
1078 if (n_sr>o_sr)
1079 addb4--;
1080
1081 n_n=ftmp->fw_nsp;
1082 n_o=chtmp->fw_nsp;
1083
1084 /*
1085 * Actually this cannot happen as the frwl control
1086 * procedure checks for number of ports in source and
1087 * destination range but we will try to be more safe.
1088 */
1089
1090 if ((n_n>(IP_FW_MAX_PORTS-2)) ||
1091 (n_o>(IP_FW_MAX_PORTS-2)))
1092 goto skip_check;
1093
1094 if (ftmp->fw_flg & IP_FW_F_DRNG)
1095 n_dr=ftmp->fw_pts[n_n+1]-ftmp->fw_pts[n_n];
1096 else
1097 n_dr=(ftmp->fw_ndp)? ftmp->fw_ndp : 0xFFFF;
1098
1099 if (chtmp->fw_flg & IP_FW_F_DRNG)
1100 o_dr=chtmp->fw_pts[n_o+1]-chtmp->fw_pts[n_o];
1101 else
1102 o_dr=(chtmp->fw_ndp)? chtmp->fw_ndp : 0xFFFF;
1103 if (n_dr<o_dr)
1104 addb4++;
1105 if (n_dr>o_dr)
1106 addb4--;
1107 skip_check:
1108 }
1109 /* finally look at the interface address */
1110 if ((addb4 == 0) && ftmp->fw_via.s_addr &&
1111 !(chtmp->fw_via.s_addr))
1112 addb4++;
1113 }
1114 if (addb4>0)
1115 {
1116 if (chtmp_prev)
1117 {
1118 chtmp_prev->fw_next=ftmp;
1119 ftmp->fw_next=chtmp;
1120 }
1121 else
1122 {
1123 *chainptr=ftmp;
1124 ftmp->fw_next=chtmp;
1125 }
1126 restore_flags(flags);
1127 return 0;
1128 }
1129 chtmp_prev=chtmp;
1130 }
1131 }
1132
1133 if (chtmp_prev)
1134 chtmp_prev->fw_next=ftmp;
1135 else
1136 *chainptr=ftmp;
1137 restore_flags(flags);
1138 return(0);
1139 }
1140
1141 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1142 {
1143 struct ip_fw *ftmp,*ltmp;
1144 unsigned short tport1,tport2,tmpnum;
1145 char matches,was_found;
1146 unsigned long flags;
1147
1148 save_flags(flags);
1149 cli();
1150
1151 ftmp=*chainptr;
1152
1153 if ( ftmp == NULL )
1154 {
1155 #ifdef DEBUG_CONFIG_IP_FIREWALL
1156 printk("ip_fw_ctl: chain is empty\n");
1157 #endif
1158 restore_flags(flags);
1159 return( EINVAL );
1160 }
1161
1162 ltmp=NULL;
1163 was_found=0;
1164
1165 while( ftmp != NULL )
1166 {
1167 matches=1;
1168 if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
1169 || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
1170 || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
1171 || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
1172 || ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
1173 || ftmp->fw_flg!=frwl->fw_flg)
1174 matches=0;
1175
1176 tport1=ftmp->fw_nsp+ftmp->fw_ndp;
1177 tport2=frwl->fw_nsp+frwl->fw_ndp;
1178 if (tport1!=tport2)
1179 matches=0;
1180 else if (tport1!=0)
1181 {
1182 for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
1183 if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
1184 matches=0;
1185 }
1186 if(matches)
1187 {
1188 was_found=1;
1189 if (ltmp)
1190 {
1191 ltmp->fw_next=ftmp->fw_next;
1192 kfree_s(ftmp,sizeof(*ftmp));
1193 ftmp=ltmp->fw_next;
1194 }
1195 else
1196 {
1197 *chainptr=ftmp->fw_next;
1198 kfree_s(ftmp,sizeof(*ftmp));
1199 ftmp=*chainptr;
1200 }
1201 }
1202 else
1203 {
1204 ltmp = ftmp;
1205 ftmp = ftmp->fw_next;
1206 }
1207 }
1208 restore_flags(flags);
1209 if (was_found)
1210 return 0;
1211 else
1212 return(EINVAL);
1213 }
1214
1215 #endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
1216
1217 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1218 {
1219
1220 if ( len != sizeof(struct ip_fw) )
1221 {
1222 #ifdef DEBUG_CONFIG_IP_FIREWALL
1223 printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
1224 #endif
1225 return(NULL);
1226 }
1227
1228 if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
1229 {
1230 #ifdef DEBUG_CONFIG_IP_FIREWALL
1231 printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
1232 frwl->fw_flg);
1233 #endif
1234 return(NULL);
1235 }
1236
1237 if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
1238 {
1239 #ifdef DEBUG_CONFIG_IP_FIREWALL
1240 printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
1241 frwl->fw_nsp);
1242 #endif
1243 return(NULL);
1244 }
1245
1246 if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
1247 {
1248 #ifdef DEBUG_CONFIG_IP_FIREWALL
1249 printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
1250 frwl->fw_ndp);
1251 #endif
1252 return(NULL);
1253 }
1254
1255 if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS )
1256 {
1257 #ifdef DEBUG_CONFIG_IP_FIREWALL
1258 printk("ip_fw_ctl: too many ports (%d+%d)\n",
1259 frwl->fw_nsp,frwl->fw_ndp);
1260 #endif
1261 return(NULL);
1262 }
1263
1264 return frwl;
1265 }
1266
1267
1268
1269
1270 #ifdef CONFIG_IP_ACCT
1271
1272 #if 0
1273 void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1274 {
1275 (void) ip_fw_chk(iph, dev, f, 0, 1);
1276 return;
1277 }
1278 #endif
1279
1280 int ip_acct_ctl(int stage, void *m, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1281 {
1282 if ( stage == IP_ACCT_FLUSH )
1283 {
1284 free_fw_chain(&ip_acct_chain);
1285 return(0);
1286 }
1287 if ( stage == IP_ACCT_ZERO )
1288 {
1289 zero_fw_chain(ip_acct_chain);
1290 return(0);
1291 }
1292 if ( stage == IP_ACCT_ADD
1293 || stage == IP_ACCT_DEL
1294 )
1295 {
1296 struct ip_fw *frwl;
1297
1298 if (!(frwl=check_ipfw_struct(m,len)))
1299 return (EINVAL);
1300
1301 switch (stage)
1302 {
1303 case IP_ACCT_ADD:
1304 return( add_to_chain(&ip_acct_chain,frwl));
1305 case IP_ACCT_DEL:
1306 return( del_from_chain(&ip_acct_chain,frwl));
1307 default:
1308 /*
1309 * Should be panic but... (Why ??? - AC)
1310 */
1311 #ifdef DEBUG_CONFIG_IP_FIREWALL
1312 printk("ip_acct_ctl: unknown request %d\n",stage);
1313 #endif
1314 return(EINVAL);
1315 }
1316 }
1317 #ifdef DEBUG_CONFIG_IP_FIREWALL
1318 printk("ip_acct_ctl: unknown request %d\n",stage);
1319 #endif
1320 return(EINVAL);
1321 }
1322 #endif
1323
1324 #ifdef CONFIG_IP_FIREWALL
1325 int ip_fw_ctl(int stage, void *m, int len)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1326 {
1327 int ret;
1328
1329 if ( stage == IP_FW_FLUSH_BLK )
1330 {
1331 free_fw_chain(&ip_fw_blk_chain);
1332 return(0);
1333 }
1334
1335 if ( stage == IP_FW_FLUSH_FWD )
1336 {
1337 free_fw_chain(&ip_fw_fwd_chain);
1338 return(0);
1339 }
1340
1341 if ( stage == IP_FW_ZERO_BLK )
1342 {
1343 zero_fw_chain(ip_fw_blk_chain);
1344 return(0);
1345 }
1346
1347 if ( stage == IP_FW_ZERO_FWD )
1348 {
1349 zero_fw_chain(ip_fw_fwd_chain);
1350 return(0);
1351 }
1352
1353 if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
1354 {
1355 int *tmp_policy_ptr;
1356 tmp_policy_ptr=(int *)m;
1357 if ( stage == IP_FW_POLICY_BLK )
1358 ip_fw_blk_policy=*tmp_policy_ptr;
1359 else
1360 ip_fw_fwd_policy=*tmp_policy_ptr;
1361 return 0;
1362 }
1363
1364 if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
1365 {
1366 struct device viadev;
1367 struct ip_fwpkt *ipfwp;
1368 struct iphdr *ip;
1369
1370 if ( len < sizeof(struct ip_fwpkt) )
1371 {
1372 #ifdef DEBUG_CONFIG_IP_FIREWALL
1373 printk("ip_fw_ctl: length=%d, expected %d\n",
1374 len, sizeof(struct ip_fwpkt));
1375 #endif
1376 return( EINVAL );
1377 }
1378
1379 ipfwp = (struct ip_fwpkt *)m;
1380 ip = &(ipfwp->fwp_iph);
1381
1382 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
1383 {
1384 #ifdef DEBUG_CONFIG_IP_FIREWALL
1385 printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
1386 sizeof(struct iphdr)/sizeof(int));
1387 #endif
1388 return(EINVAL);
1389 }
1390
1391 viadev.pa_addr = ipfwp->fwp_via.s_addr;
1392
1393 if ((ret = ip_fw_chk(ip, &viadev,
1394 stage == IP_FW_CHK_BLK ?
1395 ip_fw_blk_chain : ip_fw_fwd_chain,
1396 stage == IP_FW_CHK_BLK ?
1397 ip_fw_blk_policy : ip_fw_fwd_policy, 2 )) > 0
1398 )
1399 return(0);
1400 else if (ret == -1)
1401 return(ECONNREFUSED);
1402 else
1403 return(ETIMEDOUT);
1404 }
1405
1406 /*
1407 * Here we really working hard-adding new elements
1408 * to blocking/forwarding chains or deleting 'em
1409 */
1410
1411 if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
1412 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
1413 )
1414 {
1415 struct ip_fw *frwl;
1416 frwl=check_ipfw_struct(m,len);
1417 if (frwl==NULL)
1418 return (EINVAL);
1419
1420 switch (stage)
1421 {
1422 case IP_FW_ADD_BLK:
1423 return(add_to_chain(&ip_fw_blk_chain,frwl));
1424 case IP_FW_ADD_FWD:
1425 return(add_to_chain(&ip_fw_fwd_chain,frwl));
1426 case IP_FW_DEL_BLK:
1427 return(del_from_chain(&ip_fw_blk_chain,frwl));
1428 case IP_FW_DEL_FWD:
1429 return(del_from_chain(&ip_fw_fwd_chain,frwl));
1430 default:
1431 /*
1432 * Should be panic but... (Why are BSD people panic obsessed ??)
1433 */
1434 #ifdef DEBUG_CONFIG_IP_FIREWALL
1435 printk("ip_fw_ctl: unknown request %d\n",stage);
1436 #endif
1437 return(EINVAL);
1438 }
1439 }
1440
1441 #ifdef DEBUG_CONFIG_IP_FIREWALL
1442 printk("ip_fw_ctl: unknown request %d\n",stage);
1443 #endif
1444 return(EINVAL);
1445 }
1446 #endif /* CONFIG_IP_FIREWALL */
1447
1448 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
1449
1450 static int ip_chain_procinfo(int stage, char *buffer, char **start,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1451 off_t offset, int length, int reset)
1452 {
1453 off_t pos=0, begin=0;
1454 struct ip_fw *i;
1455 unsigned long flags;
1456 int len, p;
1457
1458
1459 switch(stage)
1460 {
1461 #ifdef CONFIG_IP_FIREWALL
1462 case IP_INFO_BLK:
1463 i = ip_fw_blk_chain;
1464 len=sprintf(buffer, "IP firewall block rules, default %d\n",
1465 ip_fw_blk_policy);
1466 break;
1467 case IP_INFO_FWD:
1468 i = ip_fw_fwd_chain;
1469 len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1470 ip_fw_fwd_policy);
1471 break;
1472 #endif
1473 #ifdef CONFIG_IP_ACCT
1474 case IP_INFO_ACCT:
1475 i = ip_acct_chain;
1476 len=sprintf(buffer,"IP accounting rules\n");
1477 break;
1478 #endif
1479 default:
1480 /* this should never be reached, but safety first... */
1481 i = NULL;
1482 len=0;
1483 break;
1484 }
1485
1486 save_flags(flags);
1487 cli();
1488
1489 while(i!=NULL)
1490 {
1491 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
1492 ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
1493 ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
1494 ntohl(i->fw_via.s_addr),i->fw_flg);
1495 len+=sprintf(buffer+len,"%u %u %-9lu %-9lu",
1496 i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
1497 for (p = 0; p < IP_FW_MAX_PORTS; p++)
1498 len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
1499 buffer[len++]='\n';
1500 buffer[len]='\0';
1501 pos=begin+len;
1502 if(pos<offset)
1503 {
1504 len=0;
1505 begin=pos;
1506 }
1507 else if(reset)
1508 {
1509 /* This needs to be done at this specific place! */
1510 i->fw_pcnt=0L;
1511 i->fw_bcnt=0L;
1512 }
1513 if(pos>offset+length)
1514 break;
1515 i=i->fw_next;
1516 }
1517 restore_flags(flags);
1518 *start=buffer+(offset-begin);
1519 len-=(offset-begin);
1520 if(len>length)
1521 len=length;
1522 return len;
1523 }
1524 #endif
1525
1526 #ifdef CONFIG_IP_ACCT
1527
1528 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1529 int length, int reset)
1530 {
1531 return ip_chain_procinfo(IP_INFO_ACCT, buffer,start, offset,length,
1532 reset);
1533 }
1534
1535 #endif
1536
1537 #ifdef CONFIG_IP_FIREWALL
1538
1539 static int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1540 int length, int reset)
1541 {
1542 return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,
1543 reset);
1544 }
1545
1546 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1547 int length, int reset)
1548 {
1549 return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,
1550 reset);
1551 }
1552 #endif
1553
1554 #ifdef CONFIG_IP_MASQUERADE
1555
1556 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1557 int length, int unused)
1558 {
1559 off_t pos=0, begin=0;
1560 struct ip_masq *ms;
1561 unsigned long flags;
1562 int len=0;
1563
1564 len=sprintf(buffer,"Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta Expires\n");
1565 save_flags(flags);
1566 cli();
1567
1568 ms=ip_msq_hosts;
1569 while (ms!=NULL)
1570 {
1571 int timer_active = del_timer(&ms->timer);
1572 if (!timer_active)
1573 ms->timer.expires = jiffies;
1574 len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08X %5d %lu\n",
1575 strProt[ms->protocol==IPPROTO_TCP],
1576 ntohl(ms->src),ntohs(ms->sport),
1577 ntohl(ms->dst),ntohs(ms->dport),
1578 ntohs(ms->mport),
1579 ms->init_seq,ms->delta,ms->timer.expires-jiffies);
1580 if (timer_active)
1581 add_timer(&ms->timer);
1582
1583 pos=begin+len;
1584 if(pos<offset)
1585 {
1586 len=0;
1587 begin=pos;
1588 }
1589 if(pos>offset+length)
1590 break;
1591 ms=ms->next;
1592 }
1593 restore_flags(flags);
1594 *start=buffer+(offset-begin);
1595 len-=(offset-begin);
1596 if(len>length)
1597 len=length;
1598 return len;
1599 }
1600
1601 #endif
1602
1603 void ip_fw_init(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1604 {
1605 #ifdef CONFIG_IP_ACCT
1606 proc_net_register(&(struct proc_dir_entry) {
1607 PROC_NET_IPACCT, 7, "ip_acct",
1608 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1609 0, &proc_net_inode_operations,
1610 ip_acct_procinfo
1611 });
1612 #endif
1613 #ifdef CONFIG_IP_FIREWALL
1614 proc_net_register(&(struct proc_dir_entry) {
1615 PROC_NET_IPFWBLK, 8, "ip_block",
1616 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1617 0, &proc_net_inode_operations,
1618 ip_fw_blk_procinfo
1619 });
1620 proc_net_register(&(struct proc_dir_entry) {
1621 PROC_NET_IPFWFWD, 10, "ip_forward",
1622 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1623 0, &proc_net_inode_operations,
1624 ip_fw_fwd_procinfo
1625 });
1626 #endif
1627 #ifdef CONFIG_IP_MASQUERADE
1628 proc_net_register(&(struct proc_dir_entry) {
1629 PROC_NET_IPMSQHST, 13, "ip_masquerade",
1630 S_IFREG | S_IRUGO, 1, 0, 0,
1631 0, &proc_net_inode_operations,
1632 ip_msqhst_procinfo
1633 });
1634 #endif
1635 }