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