This source file includes following definitions.
- print_ip
- port_match
- ip_fw_chk
- ip_acct_cnt
- zero_fw_chain
- free_fw_chain
- add_to_chain
- del_from_chain
- check_ipfw_struct
- ip_acct_ctl
- ip_fw_ctl
- ip_chain_procinfo
- ip_acct_procinfo
- ip_acct0_procinfo
- ip_fw_blk_procinfo
- ip_fw_blk0_procinfo
- ip_fw_fwd_procinfo
- ip_fw_fwd0_procinfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include <asm/segment.h>
29 #include <asm/system.h>
30 #include <linux/types.h>
31 #include <linux/kernel.h>
32 #include <linux/sched.h>
33 #include <linux/string.h>
34 #include <linux/errno.h>
35 #include <linux/config.h>
36
37 #include <linux/socket.h>
38 #include <linux/sockios.h>
39 #include <linux/in.h>
40 #include <linux/inet.h>
41 #include <linux/netdevice.h>
42 #include "ip.h"
43 #include "protocol.h"
44 #include "route.h"
45 #include "tcp.h"
46 #include <linux/skbuff.h>
47 #include "sock.h"
48 #include "icmp.h"
49 #include <linux/ip_fw.h>
50
51
52
53
54
55 #ifdef CONFIG_IP_FIREWALL
56 struct ip_fw *ip_fw_fwd_chain;
57 struct ip_fw *ip_fw_blk_chain;
58 int ip_fw_blk_policy=1;
59 int ip_fw_fwd_policy=1;
60 #endif
61 #ifdef CONFIG_IP_ACCT
62 struct ip_fw *ip_acct_chain;
63 #endif
64
65 #define IP_INFO_BLK 0
66 #define IP_INFO_FWD 1
67 #define IP_INFO_ACCT 2
68
69
70 extern inline void print_ip(unsigned long xaddr)
71 {
72 unsigned long addr = ntohl(xaddr);
73 printk("%ld.%ld.%ld.%ld",(addr>>24) & 0xff,
74 (addr>>16)&0xff,
75 (addr>>8)&0xff,
76 addr&0xFF);
77 }
78
79
80
81
82
83
84 extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
85 {
86 if (!nports)
87 return 1;
88 if ( range_flag )
89 {
90 if ( portptr[0] <= port && port <= portptr[1] )
91 {
92 return( 1 );
93 }
94 nports -= 2;
95 portptr += 2;
96 }
97 while ( nports-- > 0 )
98 {
99 if ( *portptr++ == port )
100 {
101 return( 1 );
102 }
103 }
104 return(0);
105 }
106
107
108
109
110
111
112 #ifdef CONFIG_IP_FIREWALL
113
114 int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain, int policy)
115 {
116 unsigned long src, dst;
117 char got_proto=0;
118 int frwl_proto, proto=0;
119 struct ip_fw *f;
120 unsigned short src_port=0, dst_port=0;
121 unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
122
123 if (!chain)
124 return(policy);
125
126 src = ip->saddr;
127 dst = ip->daddr;
128
129 #ifdef DEBUG_CONFIG_IP_FIREWALL
130 {
131 printk("packet ");
132 switch(ip->protocol)
133 {
134 case IPPROTO_TCP:
135 printf("TCP ");
136 break;
137 case IPPROTO_UDP:
138 printf("UDP ");
139 break;
140 case IPPROTO_ICMP:
141 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
142 break;
143 default:
144 printf("p=%d ",ip->protocol);
145 break;
146 }
147 print_ip(ip->saddr);
148 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
149 {
150 printf(":%d ",ntohs(portptr[0]));
151 }
152 print_ip(ip->daddr);
153 if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
154 {
155 printf(":%d ",ntohs(portptr[1]));
156 }
157 printf("\n");
158 }
159 #endif
160
161 for (f=chain;f;f=f->next)
162 {
163 if ((src&f->src_mask.s_addr)==f->src.s_addr
164 && (dst&f->dst_mask.s_addr)==f->dst.s_addr)
165 {
166 frwl_proto=f->flags&IP_FW_F_KIND;
167 if (frwl_proto==IP_FW_F_ALL)
168 {
169
170
171 #ifdef DEBUG_CONFIG_IP_FIREWALL
172 printf("universal frwl match\n");
173 #endif
174 f->p_cnt++;
175 f->b_cnt+=ntohs(ip->tot_len);
176 #ifdef CONFIG_IP_FIREWALL_VERBOSE
177 if (!(f->flags & IP_FW_F_ACCEPT))
178 goto bad_packet;
179 return 1;
180 #else
181 return( f->flags & IP_FW_F_ACCEPT );
182 #endif
183 }
184 else
185 {
186
187
188
189 if (!got_proto)
190 {
191
192
193
194
195 switch(ip->protocol)
196 {
197 case IPPROTO_TCP:
198
199
200
201 proto=IP_FW_F_TCP;
202 src_port=ntohs(portptr[0]);
203 dst_port=ntohs(portptr[1]);
204 break;
205 case IPPROTO_UDP:
206
207
208
209 proto = IP_FW_F_UDP;
210 src_port = ntohs(portptr[0]);
211 dst_port = ntohs(portptr[1]);
212 break;
213 case IPPROTO_ICMP:
214 proto=IP_FW_F_ICMP;
215 break;
216 default:
217 proto=IP_FW_F_ALL;
218 #ifdef DEBUG_CONFIG_IP_FIREWALL
219 printf("non TCP/UDP packet\n");
220 #endif
221 }
222 got_proto=1;
223 }
224
225
226
227
228 if (proto==frwl_proto)
229 {
230
231 if (proto==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port,
232 f->flags&IP_FW_F_SRNG) &&
233 port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
234 f->flags&IP_FW_F_DRNG)))
235 {
236
237 f->p_cnt++;
238 f->b_cnt+=ntohs(ip->tot_len);
239 #ifdef CONFIG_IP_FIREWALL_VERBOSE
240 if (!(f->flags & IP_FW_F_ACCEPT))
241 goto bad_packet;
242 return 1;
243 #else
244 return( f->flags & IP_FW_F_ACCEPT);
245 #endif
246 }
247 }
248 }
249 }
250 }
251
252
253
254
255
256
257
258 #ifdef CONFIG_IP_FIREWALL_VERBOSE
259 if (!(policy))
260 goto bad_packet;
261 return 1;
262 #else
263 return(policy);
264 #endif
265
266 #ifdef CONFIG_IP_FIREWALL_VERBOSE
267 bad_packet:
268
269
270
271
272 if (f->flags&IP_FW_F_PRN)
273 {
274 printf("ip_fw_chk says no to ");
275 switch(ip->protocol)
276 {
277 case IPPROTO_TCP:
278 printf("TCP ");
279 break;
280 case IPPROTO_UDP:
281 printf("UDP ");
282 break;
283 case IPPROTO_ICMP:
284 printf("ICMP:%d ",((char *)portptr)[0]&0xff);
285 break;
286 default:
287 printf("p=%d ",ip->protocol);
288 break;
289 }
290 print_ip(ip->saddr);
291 if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
292 {
293 printf(":%d ",ntohs(portptr[0]));
294 }
295 else
296 {
297 printf("\n");
298 }
299 print_ip(ip->daddr);
300 if ( ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP )
301 {
302 printf(":%d ",ntohs(portptr[1]));
303 }
304 printf("\n");
305 }
306 return(0);
307 #endif
308 }
309 #endif
310
311
312
313
314 #ifdef CONFIG_IP_ACCT
315 void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain)
316 {
317 unsigned long src, dst;
318 char got_proto=0,rev=0;
319 int frwl_proto, proto=0;
320 struct ip_fw *f;
321 unsigned short src_port=0, dst_port=0;
322 unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
323
324 if (!chain)
325 return;
326
327 src = ip->saddr;
328 dst = ip->daddr;
329
330 for (f=chain;f;f=f->next)
331 {
332 if ((src&f->src_mask.s_addr)==f->src.s_addr
333 && (dst&f->dst_mask.s_addr)==f->dst.s_addr)
334 {
335 rev=0;
336 goto addr_match;
337 }
338 if ((f->flags&IP_FW_F_BIDIR) &&
339 ((src&f->src_mask.s_addr)==f->dst.s_addr
340 && (dst&f->dst_mask.s_addr)==f->src.s_addr))
341 {
342 rev=1;
343 goto addr_match;
344 }
345 continue;
346 addr_match:
347 frwl_proto=f->flags&IP_FW_F_KIND;
348 if (frwl_proto==IP_FW_F_ALL)
349 {
350
351 f->p_cnt++;
352
353
354
355
356
357 f->b_cnt+=ntohs(ip->tot_len);
358 }
359 else
360 {
361
362
363
364
365 if (!got_proto)
366 {
367
368
369
370
371 switch(ip->protocol)
372 {
373 case IPPROTO_TCP:
374
375
376
377 proto=IP_FW_F_TCP;
378 src_port=ntohs(portptr[0]);
379 dst_port=ntohs(portptr[1]);
380 break;
381 case IPPROTO_UDP:
382
383
384
385 proto = IP_FW_F_UDP;
386 src_port = ntohs(portptr[0]);
387 dst_port = ntohs(portptr[1]);
388 break;
389 case IPPROTO_ICMP:
390 proto=IP_FW_F_ICMP;
391 break;
392 default:
393 proto=IP_FW_F_ALL;
394 }
395 got_proto=1;
396 }
397
398
399
400
401 if (proto==frwl_proto)
402 {
403
404 if ((proto==IP_FW_F_ICMP ||
405 (port_match(&f->ports[0],f->n_src_p,src_port,
406 f->flags&IP_FW_F_SRNG) &&
407 port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
408 f->flags&IP_FW_F_DRNG)))
409 || ((rev)
410 && (port_match(&f->ports[0],f->n_src_p,dst_port,
411 f->flags&IP_FW_F_SRNG)
412 && port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port,
413 f->flags&IP_FW_F_DRNG))))
414 {
415 f->p_cnt++;
416
417
418
419 f->b_cnt+=ntohs(ip->tot_len);
420 }
421 }
422 }
423 }
424 }
425 #endif
426
427 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
428
429 static void zero_fw_chain(struct ip_fw *chainptr)
430 {
431 struct ip_fw *ctmp=chainptr;
432 while(ctmp)
433 {
434 ctmp->p_cnt=0l;
435 ctmp->b_cnt=0l;
436 ctmp=ctmp->next;
437 }
438 }
439
440 static void free_fw_chain(struct ip_fw *volatile* chainptr)
441 {
442 unsigned long flags;
443 save_flags(flags);
444 cli();
445 while ( *chainptr != NULL )
446 {
447 struct ip_fw *ftmp;
448 ftmp = *chainptr;
449 *chainptr = ftmp->next;
450 kfree_s(ftmp,sizeof(*ftmp));
451 }
452 restore_flags(flags);
453 }
454
455
456
457 static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
458 {
459 struct ip_fw *ftmp;
460 struct ip_fw *chtmp=NULL;
461 struct ip_fw *volatile chtmp_prev=NULL;
462 unsigned long flags;
463 unsigned long m_src_mask,m_dst_mask;
464 unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
465 unsigned short n_sr,n_dr,o_sr,o_dr;
466 unsigned short oldkind,newkind;
467 int addb4=0;
468 int n_o,n_n;
469
470 save_flags(flags);
471
472 ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
473 if ( ftmp == NULL )
474 {
475 #ifdef DEBUG_CONFIG_IP_FIREWALL
476 printf("ip_fw_ctl: malloc said no\n");
477 #endif
478 return( ENOSPC );
479 }
480
481 memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
482
483 ftmp->p_cnt=0L;
484 ftmp->b_cnt=0L;
485
486 ftmp->next = NULL;
487
488 cli();
489
490 if (*chainptr==NULL)
491 {
492 *chainptr=ftmp;
493 }
494 else
495 {
496 chtmp_prev=NULL;
497 for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->next)
498 {
499 addb4=0;
500 newkind=ftmp->flags & IP_FW_F_KIND;
501 oldkind=chtmp->flags & IP_FW_F_KIND;
502
503 if (newkind!=IP_FW_F_ALL
504 && oldkind!=IP_FW_F_ALL
505 && oldkind!=newkind)
506 {
507 chtmp_prev=chtmp;
508 continue;
509 }
510
511
512
513
514
515
516 n_sa=ntohl(ftmp->src.s_addr);
517 n_da=ntohl(ftmp->dst.s_addr);
518 n_sm=ntohl(ftmp->src_mask.s_addr);
519 n_dm=ntohl(ftmp->dst_mask.s_addr);
520
521 o_sa=ntohl(chtmp->src.s_addr);
522 o_da=ntohl(chtmp->dst.s_addr);
523 o_sm=ntohl(chtmp->src_mask.s_addr);
524 o_dm=ntohl(chtmp->dst_mask.s_addr);
525
526 m_src_mask = o_sm & n_sm;
527 m_dst_mask = o_dm & n_dm;
528
529 if ((o_sa & m_src_mask) == (n_sa & m_src_mask))
530 {
531 if (n_sm > o_sm)
532 addb4++;
533 if (n_sm < o_sm)
534 addb4--;
535 }
536
537 if ((o_da & m_dst_mask) == (n_da & m_dst_mask))
538 {
539 if (n_dm > o_dm)
540 addb4++;
541 if (n_dm < o_dm)
542 addb4--;
543 }
544
545 if (((o_da & o_dm) == (n_da & n_dm))
546 &&((o_sa & o_sm) == (n_sa & n_sm)))
547 {
548 if (newkind!=IP_FW_F_ALL &&
549 oldkind==IP_FW_F_ALL)
550 addb4++;
551 if (newkind==oldkind && (oldkind==IP_FW_F_TCP
552 || oldkind==IP_FW_F_UDP))
553 {
554
555
556
557
558
559
560
561
562
563
564
565
566 if (ftmp->flags & IP_FW_F_SRNG)
567 n_sr=ftmp->ports[1]-ftmp->ports[0];
568 else
569 n_sr=(ftmp->n_src_p)?ftmp->n_src_p : 0xFFFF;
570
571 if (chtmp->flags & IP_FW_F_SRNG)
572 o_sr=chtmp->ports[1]-chtmp->ports[0];
573 else
574 o_sr=(chtmp->n_src_p)?chtmp->n_src_p : 0xFFFF;
575
576 if (n_sr<o_sr)
577 addb4++;
578 if (n_sr>o_sr)
579 addb4--;
580
581 n_n=ftmp->n_src_p;
582 n_o=chtmp->n_src_p;
583
584
585
586
587
588
589
590 if ((n_n>(IP_FW_MAX_PORTS-2)) ||
591 (n_o>(IP_FW_MAX_PORTS-2)))
592 goto skip_check;
593
594 if (ftmp->flags & IP_FW_F_DRNG)
595 n_dr=ftmp->ports[n_n+1]-ftmp->ports[n_n];
596 else
597 n_dr=(ftmp->n_dst_p)? ftmp->n_dst_p : 0xFFFF;
598
599 if (chtmp->flags & IP_FW_F_DRNG)
600 o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o];
601 else
602 o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : 0xFFFF;
603 if (n_dr<o_dr)
604 addb4++;
605 if (n_dr>o_dr)
606 addb4--;
607 skip_check:
608 }
609 }
610 if (addb4>0)
611 {
612 if (chtmp_prev)
613 {
614 chtmp_prev->next=ftmp;
615 ftmp->next=chtmp;
616 }
617 else
618 {
619 *chainptr=ftmp;
620 ftmp->next=chtmp;
621 }
622 restore_flags(flags);
623 return 0;
624 }
625 chtmp_prev=chtmp;
626 }
627 }
628
629 if (chtmp_prev)
630 chtmp_prev->next=ftmp;
631 else
632 *chainptr=ftmp;
633 restore_flags(flags);
634 return(0);
635 }
636
637 static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
638 {
639 struct ip_fw *ftmp,*ltmp;
640 unsigned short tport1,tport2,tmpnum;
641 char matches,was_found;
642 unsigned long flags;
643
644 save_flags(flags);
645 cli();
646
647 ftmp=*chainptr;
648
649 if ( ftmp == NULL )
650 {
651 #ifdef DEBUG_CONFIG_IP_FIREWALL
652 printf("ip_fw_ctl: chain is empty\n");
653 #endif
654 restore_flags(flags);
655 return( EINVAL );
656 }
657
658 ltmp=NULL;
659 was_found=0;
660
661 while( ftmp != NULL )
662 {
663 matches=1;
664 if ((memcmp(&ftmp->src,&frwl->src,sizeof(struct in_addr)))
665 || (memcmp(&ftmp->src_mask,&frwl->src_mask,sizeof(struct in_addr)))
666 || (memcmp(&ftmp->dst,&frwl->dst,sizeof(struct in_addr)))
667 || (memcmp(&ftmp->dst_mask,&frwl->dst_mask,sizeof(struct in_addr)))
668 || (ftmp->flags!=frwl->flags))
669 matches=0;
670
671 tport1=ftmp->n_src_p+ftmp->n_dst_p;
672 tport2=frwl->n_src_p+frwl->n_dst_p;
673 if (tport1!=tport2)
674 matches=0;
675 else if (tport1!=0)
676 {
677 for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
678 if (ftmp->ports[tmpnum]!=frwl->ports[tmpnum])
679 matches=0;
680 }
681 if(matches)
682 {
683 was_found=1;
684 if (ltmp)
685 {
686 ltmp->next=ftmp->next;
687 kfree_s(ftmp,sizeof(*ftmp));
688 ftmp=ltmp->next;
689 }
690 else
691 {
692 *chainptr=ftmp->next;
693 kfree_s(ftmp,sizeof(*ftmp));
694 ftmp=*chainptr;
695 }
696 }
697 else
698 {
699 ltmp = ftmp;
700 ftmp = ftmp->next;
701 }
702 }
703 restore_flags(flags);
704 if (was_found)
705 return 0;
706 else
707 return(EINVAL);
708 }
709
710 #endif
711
712 struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
713 {
714
715 if ( len != sizeof(struct ip_fw) )
716 {
717 #ifdef DEBUG_CONFIG_IP_FIREWALL
718 printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,
719 sizeof(struct ip_fw));
720 #endif
721 return(NULL);
722 }
723
724 if ( (frwl->flags & ~IP_FW_F_MASK) != 0 )
725 {
726 #ifdef DEBUG_CONFIG_IP_FIREWALL
727 printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
728 frwl->flags);
729 #endif
730 return(NULL);
731 }
732
733 if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 )
734 {
735 #ifdef DEBUG_CONFIG_IP_FIREWALL
736 printf("ip_fw_ctl: src range set but n_src_p=%d\n",
737 frwl->n_src_p);
738 #endif
739 return(NULL);
740 }
741
742 if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 )
743 {
744 #ifdef DEBUG_CONFIG_IP_FIREWALL
745 printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",
746 frwl->n_dst_p);
747 #endif
748 return(NULL);
749 }
750
751 if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS )
752 {
753 #ifdef DEBUG_CONFIG_IP_FIREWALL
754 printf("ip_fw_ctl: too many ports (%d+%d)\n",
755 frwl->n_src_p,frwl->n_dst_p);
756 #endif
757 return(NULL);
758 }
759
760 return frwl;
761 }
762
763
764
765
766 #ifdef CONFIG_IP_ACCT
767 int ip_acct_ctl(int stage, void *m, int len)
768 {
769 if ( stage == IP_ACCT_FLUSH )
770 {
771 free_fw_chain(&ip_acct_chain);
772 return(0);
773 }
774 if ( stage == IP_ACCT_ZERO )
775 {
776 zero_fw_chain(ip_acct_chain);
777 return(0);
778 }
779 if ( stage == IP_ACCT_ADD
780 || stage == IP_ACCT_DEL
781 )
782 {
783 struct ip_fw *frwl;
784
785 if (!(frwl=check_ipfw_struct(m,len)))
786 return (EINVAL);
787
788 switch (stage)
789 {
790 case IP_ACCT_ADD:
791 return( add_to_chain(&ip_acct_chain,frwl));
792 case IP_ACCT_DEL:
793 return( del_from_chain(&ip_acct_chain,frwl));
794 default:
795
796
797
798 #ifdef DEBUG_CONFIG_IP_FIREWALL
799 printf("ip_acct_ctl: unknown request %d\n",stage);
800 #endif
801 return(EINVAL);
802 }
803 }
804 #ifdef DEBUG_CONFIG_IP_FIREWALL
805 printf("ip_acct_ctl: unknown request %d\n",stage);
806 #endif
807 return(EINVAL);
808 }
809 #endif
810
811 #ifdef CONFIG_IP_FIREWALL
812 int ip_fw_ctl(int stage, void *m, int len)
813 {
814 if ( stage == IP_FW_FLUSH_BLK )
815 {
816 free_fw_chain(&ip_fw_blk_chain);
817 return(0);
818 }
819
820 if ( stage == IP_FW_FLUSH_FWD )
821 {
822 free_fw_chain(&ip_fw_fwd_chain);
823 return(0);
824 }
825
826 if ( stage == IP_FW_ZERO_BLK )
827 {
828 zero_fw_chain(ip_fw_blk_chain);
829 return(0);
830 }
831
832 if ( stage == IP_FW_ZERO_FWD )
833 {
834 zero_fw_chain(ip_fw_fwd_chain);
835 return(0);
836 }
837
838 if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
839 {
840 int *tmp_policy_ptr;
841 tmp_policy_ptr=(int *)m;
842 if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
843 return (EINVAL);
844 if ( stage == IP_FW_POLICY_BLK )
845 ip_fw_blk_policy=*tmp_policy_ptr;
846 else
847 ip_fw_fwd_policy=*tmp_policy_ptr;
848 return 0;
849 }
850
851 if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
852 {
853 struct iphdr *ip;
854
855 if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) )
856 {
857 #ifdef DEBUG_CONFIG_IP_FIREWALL
858 printf("ip_fw_ctl: len=%d, want at least %d\n",
859 len,sizeof(struct ip) + 2 * sizeof(unsigned short));
860 #endif
861 return( EINVAL );
862 }
863
864 ip = (struct iphdr *)m;
865
866 if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
867 {
868 #ifdef DEBUG_CONFIG_IP_FIREWALL
869 printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
870 sizeof(struct ip)/sizeof(int));
871 #endif
872 return(EINVAL);
873 }
874
875 if ( ip_fw_chk(ip,
876 stage == IP_FW_CHK_BLK ?
877 ip_fw_blk_chain : ip_fw_fwd_chain,
878 stage == IP_FW_CHK_BLK ?
879 ip_fw_blk_policy : ip_fw_fwd_policy )
880 )
881 return(0);
882 else
883 return(EACCES);
884 }
885
886
887
888
889
890
891 if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
892 || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
893 )
894 {
895 struct ip_fw *frwl;
896 frwl=check_ipfw_struct(m,len);
897 if (frwl==NULL)
898 return (EINVAL);
899
900 switch (stage)
901 {
902 case IP_FW_ADD_BLK:
903 return(add_to_chain(&ip_fw_blk_chain,frwl));
904 case IP_FW_ADD_FWD:
905 return(add_to_chain(&ip_fw_fwd_chain,frwl));
906 case IP_FW_DEL_BLK:
907 return(del_from_chain(&ip_fw_blk_chain,frwl));
908 case IP_FW_DEL_FWD:
909 return(del_from_chain(&ip_fw_fwd_chain,frwl));
910 default:
911
912
913
914 #ifdef DEBUG_CONFIG_IP_FIREWALL
915 printf("ip_fw_ctl: unknown request %d\n",stage);
916 #endif
917 return(EINVAL);
918 }
919 }
920
921 #ifdef DEBUG_CONFIG_IP_FIREWALL
922 printf("ip_fw_ctl: unknown request %d\n",stage);
923 #endif
924 return(EINVAL);
925 }
926 #endif
927
928 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
929
930 static int ip_chain_procinfo(int stage, char *buffer, char **start,
931 off_t offset, int length, int reset)
932 {
933 off_t pos=0, begin=0;
934 struct ip_fw *i;
935 unsigned long flags;
936 int len;
937
938
939 switch(stage)
940 {
941 #ifdef CONFIG_IP_FIREWALL
942 case IP_INFO_BLK:
943 i = ip_fw_blk_chain;
944 len=sprintf(buffer, "IP firewall block rules, policy = %d\n",
945 ip_fw_blk_policy);
946 break;
947 case IP_INFO_FWD:
948 i = ip_fw_fwd_chain;
949 len=sprintf(buffer, "IP firewall forward rules, policy = %d\n",
950 ip_fw_fwd_policy);
951 break;
952 #endif
953 #ifdef CONFIG_IP_ACCT
954 case IP_INFO_ACCT:
955 i = ip_acct_chain;
956 len=sprintf(buffer,"IP accounting rules\n");
957 break;
958 #endif
959 default:
960
961 i = NULL;
962 len=0;
963 break;
964 }
965
966 save_flags(flags);
967 cli();
968
969 while(i!=NULL)
970 {
971 len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
972 ntohl(i->src.s_addr),ntohl(i->src_mask.s_addr),
973 ntohl(i->dst.s_addr),ntohl(i->dst_mask.s_addr),
974 i->flags);
975 len+=sprintf(buffer+len,"%u %u %lu %lu ",
976 i->n_src_p,i->n_dst_p, i->p_cnt,i->b_cnt);
977 len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n",
978 i->ports[0],i->ports[1],i->ports[2],i->ports[3],
979 i->ports[4],i->ports[5],i->ports[6],i->ports[7],
980 i->ports[8],i->ports[9]);
981 pos=begin+len;
982 if(pos<offset)
983 {
984 len=0;
985 begin=pos;
986 }
987 else if(reset)
988 {
989
990 i->p_cnt=0L;
991 i->b_cnt=0L;
992 }
993 if(pos>offset+length)
994 break;
995 i=i->next;
996 }
997 restore_flags(flags);
998 *start=buffer+(offset-begin);
999 len-=(offset-begin);
1000 if(len>length)
1001 len=length;
1002 return len;
1003 }
1004 #endif
1005
1006 #ifdef CONFIG_IP_ACCT
1007
1008 int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
1009 {
1010 return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,0);
1011 }
1012
1013 int ip_acct0_procinfo(char *buffer, char **start, off_t offset, int length)
1014 {
1015 return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,1);
1016 }
1017
1018 #endif
1019
1020 #ifdef CONFIG_IP_FIREWALL
1021
1022 int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length)
1023 {
1024 return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,0);
1025 }
1026
1027 int ip_fw_blk0_procinfo(char *buffer, char **start, off_t offset, int length)
1028 {
1029 return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,1);
1030 }
1031
1032 int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length)
1033 {
1034 return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,0);
1035 }
1036
1037 int ip_fw_fwd0_procinfo(char *buffer, char **start, off_t offset, int length)
1038 {
1039 return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,1);
1040 }
1041
1042 #endif