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