OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [net/] [ipv4/] [ip_fw.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1629 jcastillo
/*
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
 *      ICMP type printk, IP_FW_F_APPEND
28
 *              Bernd Eckenfels 1996-01-31
29
 *      Split blocking chain into input and output chains, add new "insert" and
30
 *      "append" commands to replace semi-intelligent "add" command, let "delete".
31
 *      only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP
32
 *      types) when counting packets being 2nd and further fragments.
33
 *              Jos Vos <jos@xos.nl> 8/2/1996.
34
 *      Add support for matching on device names.
35
 *              Jos Vos <jos@xos.nl> 15/2/1996.
36
 *      Transparent proxying support.
37
 *              Willy Konynenberg <willy@xos.nl> 10/5/96.
38
 *      Make separate accounting on incoming and outgoing packets possible.
39
 *              Jos Vos <jos@xos.nl> 18/5/1996.
40
 *      Add timeout reprieve for idle control channels.
41
 *              Keith Owens <kaos@audio.apana.org.au> 05/07/1996.
42
 *
43
 *
44
 * Masquerading functionality
45
 *
46
 * Copyright (c) 1994 Pauline Middelink
47
 *
48
 * The pieces which added masquerading functionality are totally
49
 * my responsibility and have nothing to with the original authors
50
 * copyright or doing.
51
 *
52
 * Parts distributed under GPL.
53
 *
54
 * Fixes:
55
 *      Pauline Middelink       :       Added masquerading.
56
 *      Alan Cox                :       Fixed an error in the merge.
57
 *      Thomas Quinot           :       Fixed port spoofing.
58
 *      Alan Cox                :       Cleaned up retransmits in spoofing.
59
 *      Alan Cox                :       Cleaned up length setting.
60
 *      Wouter Gadeyne          :       Fixed masquerading support of ftp PORT commands
61
 *
62
 *      Juan Jose Ciarlante     :       Masquerading code moved to ip_masq.c
63
 *
64
 *      All the real work was done by .....
65
 *
66
 */
67
 
68
 
69
/*
70
 * Copyright (c) 1993 Daniel Boulet
71
 * Copyright (c) 1994 Ugen J.S.Antsilevich
72
 *
73
 * Redistribution and use in source forms, with and without modification,
74
 * are permitted provided that this entire comment appears intact.
75
 *
76
 * Redistribution in binary form may occur without any restrictions.
77
 * Obviously, it would be nice if you gave credit where credit is due
78
 * but requiring it would be too onerous.
79
 *
80
 * This software is provided ``AS IS'' without any warranties of any kind.
81
 */
82
 
83
#include <linux/config.h>
84
#include <asm/segment.h>
85
#include <asm/system.h>
86
#include <linux/types.h>
87
#include <linux/kernel.h>
88
#include <linux/sched.h>
89
#include <linux/string.h>
90
#include <linux/errno.h>
91
#include <linux/config.h>
92
 
93
#include <linux/socket.h>
94
#include <linux/sockios.h>
95
#include <linux/in.h>
96
#include <linux/inet.h>
97
#include <linux/netdevice.h>
98
#include <linux/icmp.h>
99
#include <linux/udp.h>
100
#include <net/ip.h>
101
#include <net/protocol.h>
102
#include <net/route.h>
103
#include <net/tcp.h>
104
#include <net/udp.h>
105
#include <net/sock.h>
106
#include <net/icmp.h>
107
#include <linux/firewall.h>
108
#include <linux/ip_fw.h>
109
 
110
#ifdef CONFIG_IP_MASQUERADE
111
#include <net/ip_masq.h>
112
#endif
113
 
114
#include <net/checksum.h>
115
#include <linux/proc_fs.h>
116
#include <linux/stat.h>
117
 
118
/*
119
 *      Implement IP packet firewall
120
 */
121
 
122
#ifdef DEBUG_IP_FIREWALL 
123
#define dprintf1(a)             printk(a)
124
#define dprintf2(a1,a2)         printk(a1,a2)
125
#define dprintf3(a1,a2,a3)      printk(a1,a2,a3)
126
#define dprintf4(a1,a2,a3,a4)   printk(a1,a2,a3,a4)
127
#else
128
#define dprintf1(a)     
129
#define dprintf2(a1,a2)
130
#define dprintf3(a1,a2,a3)
131
#define dprintf4(a1,a2,a3,a4)
132
#endif
133
 
134
#define print_ip(a)      printk("%ld.%ld.%ld.%ld",(ntohl(a)>>24)&0xFF,\
135
                                              (ntohl(a)>>16)&0xFF,\
136
                                              (ntohl(a)>>8)&0xFF,\
137
                                              (ntohl(a))&0xFF);
138
 
139
#ifdef DEBUG_IP_FIREWALL
140
#define dprint_ip(a)    print_ip(a)
141
#else
142
#define dprint_ip(a)    
143
#endif
144
 
145
#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
146
 
147
struct ip_fw *ip_fw_fwd_chain;
148
struct ip_fw *ip_fw_in_chain;
149
struct ip_fw *ip_fw_out_chain;
150
struct ip_fw *ip_acct_chain;
151
 
152
static struct ip_fw **chains[] =
153
        {&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain};
154
 
155
int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
156
int ip_fw_in_policy=IP_FW_F_ACCEPT;
157
int ip_fw_out_policy=IP_FW_F_ACCEPT;
158
 
159
static int *policies[] =
160
        {&ip_fw_fwd_policy, &ip_fw_in_policy, &ip_fw_out_policy};
161
 
162
#endif
163
 
164
/*
165
 *      Returns 1 if the port is matched by the vector, 0 otherwise
166
 */
167
 
168
extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
169
{
170
        if (!nports)
171
                return 1;
172
        if ( range_flag )
173
        {
174
                if ( portptr[0] <= port && port <= portptr[1] )
175
                {
176
                        return( 1 );
177
                }
178
                nports -= 2;
179
                portptr += 2;
180
        }
181
        while ( nports-- > 0 )
182
        {
183
                if ( *portptr++ == port )
184
                {
185
                        return( 1 );
186
                }
187
        }
188
        return(0);
189
}
190
 
191
#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
192
 
193
 
194
/*
195
 *      Returns one of the generic firewall policies, like FW_ACCEPT.
196
 *      Also does accounting so you can feed it the accounting chain.
197
 *
198
 *      The modes is either IP_FW_MODE_FW (normal firewall mode),
199
 *      IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode,
200
 *      steps through the entire chain and handles fragments
201
 *      differently), or IP_FW_MODE_CHK (handles user-level check,
202
 *      counters are not updated).
203
 */
204
 
205
 
206
int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_fw *chain, int policy, int mode)
207
{
208
        struct ip_fw *f;
209
        struct tcphdr           *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
210
        struct udphdr           *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
211
        struct icmphdr          *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl);
212
        __u32                   src, dst;
213
        __u16                   src_port=0xFFFF, dst_port=0xFFFF, icmp_type=0xFF;
214
        unsigned short          f_prt=0, prt;
215
        char                    notcpsyn=0, notcpack=0, match;
216
        unsigned short          offset;
217
        int                     answer;
218
        unsigned char           tosand, tosxor;
219
 
220
        /*
221
         *      If the chain is empty follow policy. The BSD one
222
         *      accepts anything giving you a time window while
223
         *      flushing and rebuilding the tables.
224
         */
225
 
226
        src = ip->saddr;
227
        dst = ip->daddr;
228
 
229
        /*
230
         *      This way we handle fragmented packets.
231
         *      we ignore all fragments but the first one
232
         *      so the whole packet can't be reassembled.
233
         *      This way we relay on the full info which
234
         *      stored only in first packet.
235
         *
236
         *      Note that this theoretically allows partial packet
237
         *      spoofing. Not very dangerous but paranoid people may
238
         *      wish to play with this. It also allows the so called
239
         *      "fragment bomb" denial of service attack on some types
240
         *      of system.
241
         */
242
 
243
        offset = ntohs(ip->frag_off) & IP_OFFSET;
244
 
245
        /*
246
         *      Don't allow a fragment of TCP 8 bytes in. Nobody
247
         *      normal causes this. Its a cracker trying to break
248
         *      in by doing a flag overwrite to pass the direction
249
         *      checks.
250
         */
251
 
252
        if (offset == 1 && ip->protocol == IPPROTO_TCP)
253
                return FW_BLOCK;
254
 
255
        if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&
256
                (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ||
257
                        ip->protocol == IPPROTO_ICMP))
258
                return FW_ACCEPT;
259
 
260
        /*
261
         *       Header fragment for TCP is too small to check the bits.
262
         */
263
 
264
        if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))
265
                return FW_BLOCK;
266
 
267
        /*
268
         *      Too short.
269
         *
270
         *      But only too short for a packet with ports...
271
         */
272
 
273
        else if((ntohs(ip->tot_len)<8+(ip->ihl<<2))&&(ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP))
274
                return FW_BLOCK;
275
 
276
        src = ip->saddr;
277
        dst = ip->daddr;
278
 
279
        /*
280
         *      If we got interface from which packet came
281
         *      we can use the address directly. This is unlike
282
         *      4.4BSD derived systems that have an address chain
283
         *      per device. We have a device per address with dummy
284
         *      devices instead.
285
         */
286
 
287
        dprintf1("Packet ");
288
        switch(ip->protocol)
289
        {
290
                case IPPROTO_TCP:
291
                        dprintf1("TCP ");
292
                        /* ports stay 0xFFFF if it is not the first fragment */
293
                        if (!offset) {
294
                                src_port=ntohs(tcp->source);
295
                                dst_port=ntohs(tcp->dest);
296
                                if(!tcp->ack && !tcp->rst)
297
                                        /* We do NOT have ACK, value TRUE */
298
                                        notcpack=1;
299
                                if(!tcp->syn || !notcpack)
300
                                        /* We do NOT have SYN, value TRUE */
301
                                        notcpsyn=1;
302
                        }
303
                        prt=IP_FW_F_TCP;
304
                        break;
305
                case IPPROTO_UDP:
306
                        dprintf1("UDP ");
307
                        /* ports stay 0xFFFF if it is not the first fragment */
308
                        if (!offset) {
309
                                src_port=ntohs(udp->source);
310
                                dst_port=ntohs(udp->dest);
311
                        }
312
                        prt=IP_FW_F_UDP;
313
                        break;
314
                case IPPROTO_ICMP:
315
                        /* icmp_type stays 255 if it is not the first fragment */
316
                        if (!offset)
317
                                icmp_type=(__u16)(icmp->type);
318
                        dprintf2("ICMP:%d ",icmp_type);
319
                        prt=IP_FW_F_ICMP;
320
                        break;
321
                default:
322
                        dprintf2("p=%d ",ip->protocol);
323
                        prt=IP_FW_F_ALL;
324
                        break;
325
        }
326
#ifdef DEBUG_IP_FIREWALL
327
        dprint_ip(ip->saddr);
328
 
329
        if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
330
                /* This will print 65535 when it is not the first fragment! */
331
                dprintf2(":%d ", src_port);
332
        dprint_ip(ip->daddr);
333
        if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
334
                /* This will print 65535 when it is not the first fragment! */
335
                dprintf2(":%d ",dst_port);
336
        dprintf1("\n");
337
#endif  
338
 
339
        for (f=chain;f;f=f->fw_next)
340
        {
341
                /*
342
                 *      This is a bit simpler as we don't have to walk
343
                 *      an interface chain as you do in BSD - same logic
344
                 *      however.
345
                 */
346
 
347
                /*
348
                 *      Match can become 0x01 (a "normal" match was found),
349
                 *      0x02 (a reverse match was found), and 0x03 (the
350
                 *      IP addresses match in both directions).
351
                 *      Now we know in which direction(s) we should look
352
                 *      for a match for the TCP/UDP ports.  Both directions
353
                 *      might match (e.g., when both addresses are on the
354
                 *      same network for which an address/mask is given), but
355
                 *      the ports might only match in one direction.
356
                 *      This was obviously wrong in the original BSD code.
357
                 */
358
                match = 0x00;
359
 
360
                if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
361
                &&  (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
362
                        /* normal direction */
363
                        match |= 0x01;
364
 
365
                if ((f->fw_flg & IP_FW_F_BIDIR) &&
366
                    (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
367
                &&  (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
368
                        /* reverse direction */
369
                        match |= 0x02;
370
 
371
                if (!match)
372
                        continue;
373
 
374
                /*
375
                 *      Look for a VIA address match
376
                 */
377
                if(f->fw_via.s_addr && rif)
378
                {
379
                        if(rif->pa_addr!=f->fw_via.s_addr)
380
                                continue;       /* Mismatch */
381
                }
382
 
383
                /*
384
                 *      Look for a VIA device match
385
                 */
386
                if(f->fw_viadev)
387
                {
388
                        if(rif!=f->fw_viadev)
389
                                continue;       /* Mismatch */
390
                }
391
 
392
                /*
393
                 *      Ok the chain addresses match.
394
                 */
395
 
396
#ifdef CONFIG_IP_ACCT
397
                /*
398
                 *      See if we're in accounting mode and only want to
399
                 *      count incoming or outgoing packets.
400
                 */
401
 
402
                if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
403
                   ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
404
                    (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
405
                        continue;
406
 
407
#endif
408
                /*
409
                 * For all non-TCP packets and/or non-first fragments,
410
                 * notcpsyn and notcpack will always be FALSE,
411
                 * so the IP_FW_F_TCPSYN and IP_FW_F_TCPACK flags
412
                 * are actually ignored for these packets.
413
                 */
414
 
415
                if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
416
                        continue;
417
 
418
                if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
419
                        continue;
420
 
421
                f_prt=f->fw_flg&IP_FW_F_KIND;
422
                if (f_prt!=IP_FW_F_ALL)
423
                {
424
                        /*
425
                         *      Specific firewall - packet's protocol
426
                         *      must match firewall's.
427
                         */
428
 
429
                        if(prt!=f_prt)
430
                                continue;
431
 
432
                        if((prt==IP_FW_F_ICMP &&
433
                                ! port_match(&f->fw_pts[0], f->fw_nsp,
434
                                        icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
435
                            !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
436
                                port_match(&f->fw_pts[0], f->fw_nsp, src_port,
437
                                        f->fw_flg&IP_FW_F_SRNG) &&
438
                                port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
439
                                        f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
440
                                port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
441
                                        f->fw_flg&IP_FW_F_SRNG) &&
442
                                port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
443
                                        f->fw_flg&IP_FW_F_DRNG))))
444
                        {
445
                                continue;
446
                        }
447
                }
448
 
449
#ifdef CONFIG_IP_FIREWALL_VERBOSE
450
                /*
451
                 * VERY ugly piece of code which actually
452
                 * makes kernel printf for matching packets...
453
                 */
454
 
455
                if (f->fw_flg & IP_FW_F_PRN)
456
                {
457
                        __u32 *opt = (__u32 *) (ip + 1);
458
                        int opti;
459
 
460
                        if(mode == IP_FW_MODE_ACCT_IN)
461
                                printk(KERN_INFO "IP acct in ");
462
                        else if(mode == IP_FW_MODE_ACCT_OUT)
463
                                printk(KERN_INFO "IP acct out ");
464
                        else {
465
                                if(chain == ip_fw_fwd_chain)
466
                                        printk(KERN_INFO "IP fw-fwd ");
467
                                else if(chain == ip_fw_in_chain)
468
                                        printk(KERN_INFO "IP fw-in ");
469
                                else
470
                                        printk(KERN_INFO "IP fw-out ");
471
                                if(f->fw_flg&IP_FW_F_ACCEPT) {
472
                                        if(f->fw_flg&IP_FW_F_REDIR)
473
                                                printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
474
                                        else if(f->fw_flg&IP_FW_F_MASQ)
475
                                                printk("acc/masq ");
476
                                        else
477
                                                printk("acc ");
478
                                } else if(f->fw_flg&IP_FW_F_ICMPRPL)
479
                                        printk("rej ");
480
                                else
481
                                        printk("deny ");
482
                        }
483
                        printk(rif ? rif->name : "-");
484
                        switch(ip->protocol)
485
                        {
486
                                case IPPROTO_TCP:
487
                                        printk(" TCP ");
488
                                        break;
489
                                case IPPROTO_UDP:
490
                                        printk(" UDP ");
491
                                        break;
492
                                case IPPROTO_ICMP:
493
                                        printk(" ICMP/%d ", icmp_type);
494
                                        break;
495
                                default:
496
                                        printk(" PROTO=%d ", ip->protocol);
497
                                        break;
498
                        }
499
                        print_ip(ip->saddr);
500
                        if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
501
                                printk(":%hu", src_port);
502
                        printk(" ");
503
                        print_ip(ip->daddr);
504
                        if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
505
                                printk(":%hu", dst_port);
506
                        printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
507
                                ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
508
                                ip->frag_off, ip->ttl);
509
                        for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
510
                                printk(" O=0x%8.8X", *opt++);
511
                        printk("\n");
512
                }
513
#endif          
514
                if (mode != IP_FW_MODE_CHK) {
515
                        f->fw_bcnt+=ntohs(ip->tot_len);
516
                        f->fw_pcnt++;
517
                }
518
                if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
519
                        break;
520
        } /* Loop */
521
 
522
        if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
523
 
524
                /*
525
                 * We rely on policy defined in the rejecting entry or, if no match
526
                 * was found, we rely on the general policy variable for this type
527
                 * of firewall.
528
                 */
529
 
530
                if (f!=NULL) {
531
                        policy=f->fw_flg;
532
                        tosand=f->fw_tosand;
533
                        tosxor=f->fw_tosxor;
534
                } else {
535
                        tosand=0xFF;
536
                        tosxor=0x00;
537
                }
538
 
539
                if (policy&IP_FW_F_ACCEPT) {
540
                        /* Adjust priority and recompute checksum */
541
                        __u8 old_tos = ip->tos;
542
                        ip->tos = (old_tos & tosand) ^ tosxor;
543
                        if (ip->tos != old_tos)
544
                                ip_send_check(ip);
545
#ifdef CONFIG_IP_TRANSPARENT_PROXY
546
                        if (policy&IP_FW_F_REDIR) {
547
                                if (redirport)
548
                                        if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) {
549
                                                /* Wildcard redirection.
550
                                                 * Note that redirport will become
551
                                                 * 0xFFFF for non-TCP/UDP packets.
552
                                                 */
553
                                                *redirport = htons(dst_port);
554
                                        }
555
                                answer = FW_REDIRECT;
556
                        } else
557
#endif
558
#ifdef CONFIG_IP_MASQUERADE
559
                        if (policy&IP_FW_F_MASQ)
560
                                answer = FW_MASQUERADE;
561
                        else
562
#endif
563
                                answer = FW_ACCEPT;
564
 
565
                } else if(policy&IP_FW_F_ICMPRPL)
566
                        answer = FW_REJECT;
567
                else
568
                        answer = FW_BLOCK;
569
 
570
                return answer;
571
        } else
572
                /* we're doing accounting, always ok */
573
                return 0;
574
}
575
 
576
 
577
static void zero_fw_chain(struct ip_fw *chainptr)
578
{
579
        struct ip_fw *ctmp=chainptr;
580
        while(ctmp)
581
        {
582
                ctmp->fw_pcnt=0L;
583
                ctmp->fw_bcnt=0L;
584
                ctmp=ctmp->fw_next;
585
        }
586
}
587
 
588
static void free_fw_chain(struct ip_fw *volatile* chainptr)
589
{
590
        unsigned long flags;
591
        save_flags(flags);
592
        cli();
593
        while ( *chainptr != NULL )
594
        {
595
                struct ip_fw *ftmp;
596
                ftmp = *chainptr;
597
                *chainptr = ftmp->fw_next;
598
                kfree_s(ftmp,sizeof(*ftmp));
599
        }
600
        restore_flags(flags);
601
}
602
 
603
/* Volatiles to keep some of the compiler versions amused */
604
 
605
static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
606
{
607
        struct ip_fw *ftmp;
608
        unsigned long flags;
609
 
610
        save_flags(flags);
611
 
612
        ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
613
        if ( ftmp == NULL )
614
        {
615
#ifdef DEBUG_IP_FIREWALL
616
                printk("ip_fw_ctl:  malloc said no\n");
617
#endif
618
                return( ENOMEM );
619
        }
620
 
621
        memcpy(ftmp, frwl, len);
622
        /*
623
         *      Allow the more recent "minimise cost" flag to be
624
         *      set. [Rob van Nieuwkerk]
625
         */
626
        ftmp->fw_tosand |= 0x01;
627
        ftmp->fw_tosxor &= 0xFE;
628
        ftmp->fw_pcnt=0L;
629
        ftmp->fw_bcnt=0L;
630
 
631
        cli();
632
 
633
        if ((ftmp->fw_vianame)[0]) {
634
                if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame)))
635
                        ftmp->fw_viadev = (struct device *) -1;
636
        } else
637
                ftmp->fw_viadev = NULL;
638
 
639
        ftmp->fw_next = *chainptr;
640
        *chainptr=ftmp;
641
        restore_flags(flags);
642
        return(0);
643
}
644
 
645
static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
646
{
647
        struct ip_fw *ftmp;
648
        struct ip_fw *chtmp=NULL;
649
        struct ip_fw *volatile chtmp_prev=NULL;
650
        unsigned long flags;
651
 
652
        save_flags(flags);
653
 
654
        ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
655
        if ( ftmp == NULL )
656
        {
657
#ifdef DEBUG_IP_FIREWALL
658
                printk("ip_fw_ctl:  malloc said no\n");
659
#endif
660
                return( ENOMEM );
661
        }
662
 
663
        memcpy(ftmp, frwl, len);
664
        /*
665
         *      Allow the more recent "minimise cost" flag to be
666
         *      set. [Rob van Nieuwkerk]
667
         */
668
        ftmp->fw_tosand |= 0x01;
669
        ftmp->fw_tosxor &= 0xFE;
670
        ftmp->fw_pcnt=0L;
671
        ftmp->fw_bcnt=0L;
672
 
673
        ftmp->fw_next = NULL;
674
 
675
        cli();
676
 
677
        if ((ftmp->fw_vianame)[0]) {
678
                if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame)))
679
                        ftmp->fw_viadev = (struct device *) -1;
680
        } else
681
                ftmp->fw_viadev = NULL;
682
 
683
        chtmp_prev=NULL;
684
        for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
685
                chtmp_prev=chtmp;
686
 
687
        if (chtmp_prev)
688
                chtmp_prev->fw_next=ftmp;
689
        else
690
                *chainptr=ftmp;
691
        restore_flags(flags);
692
        return(0);
693
}
694
 
695
static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
696
{
697
        struct ip_fw    *ftmp,*ltmp;
698
        unsigned short  tport1,tport2,tmpnum;
699
        char            matches,was_found;
700
        unsigned long   flags;
701
 
702
        save_flags(flags);
703
        cli();
704
 
705
        ftmp=*chainptr;
706
 
707
        if ( ftmp == NULL )
708
        {
709
#ifdef DEBUG_IP_FIREWALL
710
                printk("ip_fw_ctl:  chain is empty\n");
711
#endif
712
                restore_flags(flags);
713
                return( EINVAL );
714
        }
715
 
716
        ltmp=NULL;
717
        was_found=0;
718
 
719
        while( !was_found && ftmp != NULL )
720
        {
721
                matches=1;
722
                if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
723
                     ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
724
                     ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
725
                     ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
726
                     ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
727
                     ||  ftmp->fw_flg!=frwl->fw_flg)
728
                        matches=0;
729
 
730
                tport1=ftmp->fw_nsp+ftmp->fw_ndp;
731
                tport2=frwl->fw_nsp+frwl->fw_ndp;
732
                if (tport1!=tport2)
733
                        matches=0;
734
                else if (tport1!=0)
735
                {
736
                        for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
737
                        if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
738
                                matches=0;
739
                }
740
                if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
741
                        matches=0;
742
                if(matches)
743
                {
744
                        was_found=1;
745
                        if (ltmp)
746
                        {
747
                                ltmp->fw_next=ftmp->fw_next;
748
                                kfree_s(ftmp,sizeof(*ftmp));
749
                                ftmp=ltmp->fw_next;
750
                        }
751
                        else
752
                        {
753
                                *chainptr=ftmp->fw_next;
754
                                kfree_s(ftmp,sizeof(*ftmp));
755
                                ftmp=*chainptr;
756
                        }
757
                }
758
                else
759
                {
760
                        ltmp = ftmp;
761
                        ftmp = ftmp->fw_next;
762
                 }
763
        }
764
        restore_flags(flags);
765
        if (was_found)
766
                return 0;
767
        else
768
                return(EINVAL);
769
}
770
 
771
#endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
772
 
773
struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
774
{
775
 
776
        if ( len != sizeof(struct ip_fw) )
777
        {
778
#ifdef DEBUG_IP_FIREWALL
779
                printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw));
780
#endif
781
                return(NULL);
782
        }
783
 
784
        if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
785
        {
786
#ifdef DEBUG_IP_FIREWALL
787
                printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
788
                        frwl->fw_flg);
789
#endif
790
                return(NULL);
791
        }
792
 
793
#ifndef CONFIG_IP_TRANSPARENT_PROXY
794
        if (frwl->fw_flg & IP_FW_F_REDIR) {
795
#ifdef DEBUG_IP_FIREWALL
796
                printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n");
797
#endif
798
                return(NULL);
799
        }
800
#endif
801
 
802
#ifndef CONFIG_IP_MASQUERADE
803
        if (frwl->fw_flg & IP_FW_F_MASQ) {
804
#ifdef DEBUG_IP_FIREWALL
805
                printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n");
806
#endif
807
                return(NULL);
808
        }
809
#endif
810
 
811
        if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
812
        {
813
#ifdef DEBUG_IP_FIREWALL
814
                printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
815
                        frwl->fw_nsp);
816
#endif
817
                return(NULL);
818
        }
819
 
820
        if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
821
        {
822
#ifdef DEBUG_IP_FIREWALL
823
                printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
824
                        frwl->fw_ndp);
825
#endif
826
                return(NULL);
827
        }
828
 
829
        if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
830
        {
831
#ifdef DEBUG_IP_FIREWALL
832
                printk("ip_fw_ctl: too many ports (%d+%d)\n",
833
                        frwl->fw_nsp,frwl->fw_ndp);
834
#endif
835
                return(NULL);
836
        }
837
 
838
        return frwl;
839
}
840
 
841
 
842
 
843
 
844
#ifdef CONFIG_IP_ACCT
845
 
846
int ip_acct_ctl(int stage, void *m, int len)
847
{
848
        if ( stage == IP_ACCT_FLUSH )
849
        {
850
                free_fw_chain(&ip_acct_chain);
851
                return(0);
852
        }
853
        if ( stage == IP_ACCT_ZERO )
854
        {
855
                zero_fw_chain(ip_acct_chain);
856
                return(0);
857
        }
858
        if ( stage == IP_ACCT_INSERT || stage == IP_ACCT_APPEND ||
859
                                        stage == IP_ACCT_DELETE )
860
        {
861
                struct ip_fw *frwl;
862
 
863
                if (!(frwl=check_ipfw_struct(m,len)))
864
                        return (EINVAL);
865
 
866
                switch (stage)
867
                {
868
                        case IP_ACCT_INSERT:
869
                                return( insert_in_chain(&ip_acct_chain,frwl,len));
870
                        case IP_ACCT_APPEND:
871
                                return( append_to_chain(&ip_acct_chain,frwl,len));
872
                        case IP_ACCT_DELETE:
873
                                return( del_from_chain(&ip_acct_chain,frwl));
874
                        default:
875
                                /*
876
                                 *      Should be panic but... (Why ??? - AC)
877
                                 */
878
#ifdef DEBUG_IP_FIREWALL
879
                                printk("ip_acct_ctl:  unknown request %d\n",stage);
880
#endif
881
                                return(EINVAL);
882
                }
883
        }
884
#ifdef DEBUG_IP_FIREWALL
885
        printk("ip_acct_ctl:  unknown request %d\n",stage);
886
#endif
887
        return(EINVAL);
888
}
889
#endif
890
 
891
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
892
 
893
int ip_autofw_add(struct ip_autofw * af)
894
{
895
        struct ip_autofw * newaf;
896
        init_timer(&af->timer);
897
        newaf = kmalloc( sizeof(struct ip_autofw), GFP_ATOMIC );
898
        if ( newaf == NULL )
899
        {
900
#ifdef DEBUG_IP_FIREWALL
901
                printk("ip_autofw_add:  malloc said no\n");
902
#endif
903
                return( ENOMEM );
904
        }
905
 
906
        memcpy(newaf, af, sizeof(struct ip_autofw));
907
        newaf->timer.data = (unsigned long) newaf;
908
        newaf->timer.function = ip_autofw_expire;
909
        newaf->timer.expires = 0;
910
        newaf->lastcontact=0;
911
        newaf->next=ip_autofw_hosts;
912
        ip_autofw_hosts=newaf;
913
        return(0);
914
}
915
 
916
int ip_autofw_del(struct ip_autofw * af)
917
{
918
        struct ip_autofw * prev, * curr;
919
        prev=NULL;
920
        curr=ip_autofw_hosts;
921
        while (curr)
922
        {
923
                if (af->type     == curr->type &&
924
                    af->low      == curr->low &&
925
                    af->high     == curr->high &&
926
                    af->hidden   == curr->hidden &&
927
                    af->visible  == curr->visible &&
928
                    af->protocol == curr->protocol &&
929
                    af->where    == curr->where &&
930
                    af->ctlproto == curr->ctlproto &&
931
                    af->ctlport  == curr->ctlport)
932
                {
933
                        if (prev)
934
                        {
935
                                prev->next=curr->next;
936
                                kfree_s(curr,sizeof(struct ip_autofw));
937
                                return(0);
938
                        }
939
                        else
940
                        {
941
                                kfree_s(ip_autofw_hosts,sizeof(struct ip_autofw));
942
                                ip_autofw_hosts=curr->next;
943
                                return(0);
944
                        }
945
                }
946
                prev=curr;
947
                curr=curr->next;
948
        }
949
        return(EINVAL);
950
}
951
 
952
int ip_autofw_flush(void)
953
{
954
        struct ip_autofw * af;
955
        while (ip_autofw_hosts)
956
        {
957
                af=ip_autofw_hosts;
958
                ip_autofw_hosts=ip_autofw_hosts->next;
959
                kfree_s(af,sizeof(struct ip_autofw));
960
        }
961
        return(0);
962
}
963
 
964
int ip_autofw_ctl(int stage, void *m, int len)
965
{
966
        if (stage == IP_AUTOFW_ADD)
967
                return (ip_autofw_add((struct ip_autofw *) m));
968
 
969
        if (stage == IP_AUTOFW_DEL)
970
                return (ip_autofw_del((struct ip_autofw *) m));
971
 
972
        if (stage == IP_AUTOFW_FLUSH)
973
                return (ip_autofw_flush());
974
 
975
        return(EINVAL);
976
}
977
 
978
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
979
 
980
#ifdef CONFIG_IP_MASQUERADE_IPPORTFW
981
extern struct ip_portfw *ipportfw_lst[2];
982
 
983
int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr)
984
{
985
        int prot = (protocol==IPPROTO_TCP);
986
        struct ip_portfw *n = ipportfw_lst[prot];
987
        struct ip_portfw *ntmp;
988
 
989
        if (!n) return 1;
990
 
991
        if (n->lport == lport && n->laddr == laddr) {
992
                ipportfw_lst[prot] = n->next;
993
                kfree_s(n, sizeof(*n));
994
                return 0;
995
        }
996
        for ( ; n->next ; n = n->next)
997
                if (n->next->lport == lport && n->next->laddr == laddr) {
998
                        ntmp = n->next;
999
                        n->next = n->next->next;
1000
                        kfree_s(ntmp, sizeof(*ntmp));
1001
                        return 0;
1002
                }
1003
 
1004
        /* Entry not found so return an error */
1005
        return 1;
1006
}
1007
 
1008
void ip_portfw_flush(void)
1009
{
1010
        int prot;
1011
        struct ip_portfw *c, *n;
1012
 
1013
        for (prot = 0; prot < 2; prot++) {
1014
                c = ipportfw_lst[prot];
1015
                ipportfw_lst[prot] = NULL;
1016
                for ( ; c; c = n) {
1017
                        n = c->next;
1018
                        kfree_s(c, size(*c));
1019
                }
1020
        }
1021
}
1022
 
1023
int ip_portfw_add(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)
1024
{
1025
        struct ip_portfw  *newportfw;
1026
        int prot = (protocol==IPPROTO_TCP);
1027
 
1028
        newportfw = (struct ip_portfw*)
1029
                kmalloc(sizeof(struct ip_portfw), GFP_ATOMIC);
1030
 
1031
        if (!newportfw)
1032
                return 1;
1033
 
1034
        newportfw->laddr = laddr;
1035
        newportfw->lport = lport;
1036
        newportfw->rport = rport;
1037
        newportfw->raddr = raddr;
1038
        newportfw->next = ipportfw_lst[prot];
1039
        ipportfw_lst[prot] = newportfw;
1040
 
1041
        return 0;
1042
}
1043
 
1044
int ip_portfw_ctl(int cmd, void *m, int len)
1045
{
1046
        unsigned long   flags;
1047
        int failed;
1048
        struct ip_portfw_edits *mm = (struct ip_portfw_edits *) m;
1049
 
1050
        /* Don't trust the lusers - plenty of error checking! */
1051
        if (cmd != IP_PORTFW_ADD && cmd != IP_PORTFW_DEL
1052
            && cmd != IP_PORTFW_FLUSH)
1053
                return (EINVAL);
1054
 
1055
        if (cmd != IP_PORTFW_FLUSH) {
1056
                if (mm->lport < IP_PORTFW_PORT_MIN || mm->lport > IP_PORTFW_PORT_MAX)
1057
                        return (EINVAL);
1058
 
1059
                if (mm->protocol!=IPPROTO_TCP && mm->protocol!=IPPROTO_UDP)
1060
                        return (EINVAL);
1061
        }
1062
 
1063
        if (cmd == IP_PORTFW_ADD) {
1064
                save_flags(flags); cli();
1065
                ip_portfw_del(mm->protocol, htons(mm->lport), htonl(mm->laddr));
1066
                failed = ip_portfw_add(mm->protocol,
1067
                          htons(mm->lport), htonl(mm->laddr),
1068
                          htons(mm->rport), htonl(mm->raddr));
1069
                restore_flags(flags);
1070
                return (failed ? ENOMEM : 0);
1071
        }
1072
        else if (cmd == IP_PORTFW_DEL) {
1073
                save_flags(flags); cli();
1074
                failed = ip_portfw_del(mm->protocol, htons(mm->lport),
1075
                           htonl(mm->laddr));
1076
                restore_flags(flags);
1077
                return (failed ? EINVAL : 0);
1078
        }
1079
        else if (cmd == IP_PORTFW_FLUSH) {
1080
                save_flags(flags); cli();
1081
                ip_portfw_flush();
1082
                restore_flags(flags);
1083
                return 0;
1084
        }
1085
        else
1086
                return (EINVAL);        /* This should have avoided in ip_sockglue.c */
1087
}
1088
#endif /* CONFIG_IP_MASQUERADE_IPPORTFW */
1089
 
1090
#ifdef CONFIG_IP_FIREWALL
1091
int ip_fw_ctl(int stage, void *m, int len)
1092
{
1093
        int cmd, fwtype;
1094
 
1095
        cmd = stage & IP_FW_COMMAND;
1096
        fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1097
 
1098
        if ( cmd == IP_FW_FLUSH )
1099
        {
1100
                free_fw_chain(chains[fwtype]);
1101
                return(0);
1102
        }
1103
 
1104
        if ( cmd == IP_FW_ZERO )
1105
        {
1106
                zero_fw_chain(*chains[fwtype]);
1107
                return(0);
1108
        }
1109
 
1110
        if ( cmd == IP_FW_POLICY )
1111
        {
1112
                int *tmp_policy_ptr;
1113
                tmp_policy_ptr=(int *)m;
1114
                *policies[fwtype] = *tmp_policy_ptr;
1115
                return 0;
1116
        }
1117
 
1118
        if ( cmd == IP_FW_CHECK )
1119
        {
1120
                struct device *viadev;
1121
                struct ip_fwpkt *ipfwp;
1122
                struct iphdr *ip;
1123
 
1124
                if ( len != sizeof(struct ip_fwpkt) )
1125
                {
1126
#ifdef DEBUG_IP_FIREWALL
1127
                        printk("ip_fw_ctl: length=%d, expected %d\n",
1128
                                len, sizeof(struct ip_fwpkt));
1129
#endif
1130
                        return( EINVAL );
1131
                }
1132
 
1133
                ipfwp = (struct ip_fwpkt *)m;
1134
                ip = &(ipfwp->fwp_iph);
1135
 
1136
                if ( !(viadev = dev_get(ipfwp->fwp_vianame)) ) {
1137
#ifdef DEBUG_IP_FIREWALL
1138
                        printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame);
1139
#endif
1140
                        return(EINVAL);
1141
                } else if ( viadev->pa_addr != ipfwp->fwp_via.s_addr ) {
1142
#ifdef DEBUG_IP_FIREWALL
1143
                        printk("ip_fw_ctl: device \"%s\" has another IP address\n",
1144
                                ipfwp->fwp_vianame);
1145
#endif
1146
                        return(EINVAL);
1147
                } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
1148
#ifdef DEBUG_IP_FIREWALL
1149
                        printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
1150
                                        sizeof(struct iphdr)/sizeof(int));
1151
#endif
1152
                        return(EINVAL);
1153
                }
1154
 
1155
                switch (ip_fw_chk(ip, viadev, NULL, *chains[fwtype],
1156
                                *policies[fwtype], IP_FW_MODE_CHK))
1157
                {
1158
                        case FW_ACCEPT:
1159
                                return(0);
1160
                        case FW_REDIRECT:
1161
                                return(ECONNABORTED);
1162
                        case FW_MASQUERADE:
1163
                                return(ECONNRESET);
1164
                        case FW_REJECT:
1165
                                return(ECONNREFUSED);
1166
                        default: /* FW_BLOCK */
1167
                                return(ETIMEDOUT);
1168
                }
1169
        }
1170
 
1171
        if ( cmd == IP_FW_MASQ_TIMEOUTS )
1172
        {
1173
#ifdef CONFIG_IP_MASQUERADE
1174
                struct ip_fw_masq *masq;
1175
 
1176
                if ( len != sizeof(struct ip_fw_masq) )
1177
                {
1178
#ifdef DEBUG_IP_FIREWALL
1179
                        printk("ip_fw_ctl (masq): length %d, expected %d\n",
1180
                                len, sizeof(struct ip_fw_masq));
1181
 
1182
#endif
1183
                        return( EINVAL );
1184
                }
1185
 
1186
                masq = (struct ip_fw_masq *) m;
1187
 
1188
                if (masq->tcp_timeout)
1189
                {
1190
                        ip_masq_expire->tcp_timeout = masq->tcp_timeout;
1191
                }
1192
 
1193
                if (masq->tcp_fin_timeout)
1194
                {
1195
                        ip_masq_expire->tcp_fin_timeout = masq->tcp_fin_timeout;
1196
                }
1197
 
1198
                if (masq->udp_timeout)
1199
                {
1200
                        ip_masq_expire->udp_timeout = masq->udp_timeout;
1201
                }
1202
 
1203
                return 0;
1204
#else
1205
                return( EINVAL );
1206
#endif
1207
        }
1208
 
1209
/*
1210
 *      Here we really working hard-adding new elements
1211
 *      to blocking/forwarding chains or deleting 'em
1212
 */
1213
 
1214
        if ( cmd == IP_FW_INSERT || cmd == IP_FW_APPEND || cmd == IP_FW_DELETE )
1215
        {
1216
                struct ip_fw *frwl;
1217
                int fwtype;
1218
 
1219
                frwl=check_ipfw_struct(m,len);
1220
                if (frwl==NULL)
1221
                        return (EINVAL);
1222
                fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
1223
 
1224
                switch (cmd)
1225
                {
1226
                        case IP_FW_INSERT:
1227
                                return(insert_in_chain(chains[fwtype],frwl,len));
1228
                        case IP_FW_APPEND:
1229
                                return(append_to_chain(chains[fwtype],frwl,len));
1230
                        case IP_FW_DELETE:
1231
                                return(del_from_chain(chains[fwtype],frwl));
1232
                        default:
1233
                        /*
1234
                         *      Should be panic but... (Why are BSD people panic obsessed ??)
1235
                         */
1236
#ifdef DEBUG_IP_FIREWALL
1237
                                printk("ip_fw_ctl:  unknown request %d\n",stage);
1238
#endif
1239
                                return(EINVAL);
1240
                }
1241
        }
1242
 
1243
#ifdef DEBUG_IP_FIREWALL
1244
        printk("ip_fw_ctl:  unknown request %d\n",stage);
1245
#endif
1246
        return(EINVAL);
1247
}
1248
#endif /* CONFIG_IP_FIREWALL */
1249
 
1250
#if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
1251
 
1252
static int ip_chain_procinfo(int stage, char *buffer, char **start,
1253
                             off_t offset, int length, int reset)
1254
{
1255
        off_t pos=0, begin=0;
1256
        struct ip_fw *i;
1257
        unsigned long flags;
1258
        int len, p;
1259
        int last_len = 0;
1260
 
1261
 
1262
        switch(stage)
1263
        {
1264
#ifdef CONFIG_IP_FIREWALL
1265
                case IP_FW_IN:
1266
                        i = ip_fw_in_chain;
1267
                        len=sprintf(buffer, "IP firewall input rules, default %d\n",
1268
                                ip_fw_in_policy);
1269
                        break;
1270
                case IP_FW_OUT:
1271
                        i = ip_fw_out_chain;
1272
                        len=sprintf(buffer, "IP firewall output rules, default %d\n",
1273
                                ip_fw_out_policy);
1274
                        break;
1275
                case IP_FW_FWD:
1276
                        i = ip_fw_fwd_chain;
1277
                        len=sprintf(buffer, "IP firewall forward rules, default %d\n",
1278
                                ip_fw_fwd_policy);
1279
                        break;
1280
#endif
1281
#ifdef CONFIG_IP_ACCT
1282
                case IP_FW_ACCT:
1283
                        i = ip_acct_chain;
1284
                        len=sprintf(buffer,"IP accounting rules\n");
1285
                        break;
1286
#endif
1287
                default:
1288
                        /* this should never be reached, but safety first... */
1289
                        i = NULL;
1290
                        len=0;
1291
                        break;
1292
        }
1293
 
1294
        save_flags(flags);
1295
        cli();
1296
 
1297
        while(i!=NULL)
1298
        {
1299
                len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %.16s %08lX %X ",
1300
                        ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
1301
                        ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
1302
                        (i->fw_vianame)[0] ? i->fw_vianame : "-",
1303
                        ntohl(i->fw_via.s_addr),i->fw_flg);
1304
                len+=sprintf(buffer+len,"%u %u %-10lu %-10lu",
1305
                        i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
1306
                for (p = 0; p < IP_FW_MAX_PORTS; p++)
1307
                        len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
1308
                len+=sprintf(buffer+len, " A%02X X%02X", i->fw_tosand, i->fw_tosxor);
1309
                buffer[len++]='\n';
1310
                buffer[len]='\0';
1311
                pos=begin+len;
1312
                if(pos<offset)
1313
                {
1314
                        len=0;
1315
                        begin=pos;
1316
                }
1317
                else if(pos>offset+length)
1318
                {
1319
                        len = last_len;
1320
                        break;
1321
                }
1322
                else if(reset)
1323
                {
1324
                        /* This needs to be done at this specific place! */
1325
                        i->fw_pcnt=0L;
1326
                        i->fw_bcnt=0L;
1327
                }
1328
                last_len = len;
1329
                i=i->fw_next;
1330
        }
1331
        restore_flags(flags);
1332
        *start=buffer+(offset-begin);
1333
        len-=(offset-begin);
1334
        if(len>length)
1335
                len=length;
1336
        return len;
1337
}
1338
#endif
1339
 
1340
#ifdef CONFIG_IP_ACCT
1341
 
1342
static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
1343
                            int length, int reset)
1344
{
1345
        return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length,
1346
                                 reset);
1347
}
1348
 
1349
#endif
1350
 
1351
#ifdef CONFIG_IP_FIREWALL
1352
 
1353
static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
1354
                              int length, int reset)
1355
{
1356
        return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length,
1357
                                 reset);
1358
}
1359
 
1360
static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
1361
                              int length, int reset)
1362
{
1363
        return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length,
1364
                                 reset);
1365
}
1366
 
1367
static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
1368
                              int length, int reset)
1369
{
1370
        return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length,
1371
                                 reset);
1372
}
1373
#endif
1374
 
1375
 
1376
#ifdef CONFIG_IP_FIREWALL
1377
/*
1378
 *      Interface to the generic firewall chains.
1379
 */
1380
 
1381
int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
1382
{
1383
        return ip_fw_chk(phdr, dev, arg, ip_fw_in_chain, ip_fw_in_policy, IP_FW_MODE_FW);
1384
}
1385
 
1386
int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
1387
{
1388
        return ip_fw_chk(phdr, dev, arg, ip_fw_out_chain, ip_fw_out_policy, IP_FW_MODE_FW);
1389
}
1390
 
1391
int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
1392
{
1393
        return ip_fw_chk(phdr, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy, IP_FW_MODE_FW);
1394
}
1395
 
1396
struct firewall_ops ipfw_ops=
1397
{
1398
        NULL,
1399
        ipfw_forward_check,
1400
        ipfw_input_check,
1401
        ipfw_output_check,
1402
        PF_INET,
1403
 
1404
};
1405
 
1406
#endif
1407
 
1408
#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
1409
 
1410
int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
1411
{
1412
        struct device *dev=ptr;
1413
        char *devname = dev->name;
1414
        unsigned long flags;
1415
        struct ip_fw *fw;
1416
        int chn;
1417
 
1418
        save_flags(flags);
1419
        cli();
1420
 
1421
        if (event == NETDEV_UP) {
1422
                for (chn = 0; chn < IP_FW_CHAINS; chn++)
1423
                        for (fw = *chains[chn]; fw; fw = fw->fw_next)
1424
                                if ((fw->fw_vianame)[0] && !strncmp(devname,
1425
                                                fw->fw_vianame, IFNAMSIZ))
1426
                                        fw->fw_viadev = dev;
1427
        } else if (event == NETDEV_DOWN) {
1428
                for (chn = 0; chn < IP_FW_CHAINS; chn++)
1429
                        for (fw = *chains[chn]; fw; fw = fw->fw_next)
1430
                                /* we could compare just the pointers ... */
1431
                                if ((fw->fw_vianame)[0] && !strncmp(devname,
1432
                                                fw->fw_vianame, IFNAMSIZ))
1433
                                        fw->fw_viadev = (struct device *) -1;
1434
        }
1435
 
1436
        restore_flags(flags);
1437
        return NOTIFY_DONE;
1438
}
1439
 
1440
static struct notifier_block ipfw_dev_notifier={
1441
        ipfw_device_event,
1442
        NULL,
1443
 
1444
};
1445
 
1446
#endif
1447
 
1448
#ifdef CONFIG_PROC_FS
1449
#ifdef CONFIG_IP_ACCT
1450
static struct proc_dir_entry pde1 = {
1451
                PROC_NET_IPACCT, 7, "ip_acct",
1452
                S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1453
                0, &proc_net_inode_operations,
1454
                ip_acct_procinfo
1455
        };
1456
#endif
1457
#ifdef CONFIG_IP_FIREWALL
1458
static struct proc_dir_entry pde2 = {
1459
                PROC_NET_IPFWIN, 8, "ip_input",
1460
                S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1461
                0, &proc_net_inode_operations,
1462
                ip_fw_in_procinfo
1463
        };
1464
static struct proc_dir_entry pde3 = {
1465
                PROC_NET_IPFWOUT, 9, "ip_output",
1466
                S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1467
                0, &proc_net_inode_operations,
1468
                ip_fw_out_procinfo
1469
        };
1470
static struct proc_dir_entry pde4 = {
1471
                PROC_NET_IPFWFWD, 10, "ip_forward",
1472
                S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
1473
                0, &proc_net_inode_operations,
1474
                ip_fw_fwd_procinfo
1475
        };
1476
#endif
1477
#endif
1478
 
1479
void ip_fw_init(void)
1480
{
1481
#ifdef CONFIG_PROC_FS
1482
#ifdef CONFIG_IP_ACCT
1483
        proc_net_register(&pde1);
1484
#endif
1485
#endif
1486
#ifdef CONFIG_IP_FIREWALL
1487
 
1488
        if(register_firewall(PF_INET,&ipfw_ops)<0)
1489
                panic("Unable to register IP firewall.\n");
1490
 
1491
#ifdef CONFIG_PROC_FS           
1492
        proc_net_register(&pde2);
1493
        proc_net_register(&pde3);
1494
        proc_net_register(&pde4);
1495
#endif
1496
#endif
1497
#ifdef CONFIG_IP_MASQUERADE
1498
 
1499
        /*
1500
         *      Initialize masquerading.
1501
         */
1502
 
1503
        ip_masq_init();
1504
#endif
1505
 
1506
#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
1507
        /* Register for device up/down reports */
1508
        register_netdevice_notifier(&ipfw_dev_notifier);
1509
#endif
1510
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.