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