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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [netfilter/] [ipfwadm_core.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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