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