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