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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * ip_nat_snmp_basic.c
3
 *
4
 * Basic SNMP Application Layer Gateway
5
 *
6
 * This IP NAT module is intended for use with SNMP network
7
 * discovery and monitoring applications where target networks use
8
 * conflicting private address realms.
9
 *
10
 * Static NAT is used to remap the networks from the view of the network
11
 * management system at the IP layer, and this module remaps some application
12
 * layer addresses to match.
13
 *
14
 * The simplest form of ALG is performed, where only tagged IP addresses
15
 * are modified.  The module does not need to be MIB aware and only scans
16
 * messages at the ASN.1/BER level.
17
 *
18
 * Currently, only SNMPv1 and SNMPv2 are supported.
19
 *
20
 * More information on ALG and associated issues can be found in
21
 * RFC 2962
22
 *
23
 * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
24
 * McLean & Jochen Friedrich, stripped down for use in the kernel.
25
 *
26
 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
27
 *
28
 * This program is free software; you can redistribute it and/or modify
29
 * it under the terms of the GNU General Public License as published by
30
 * the Free Software Foundation; either version 2 of the License, or
31
 * (at your option) any later version.
32
 * This program is distributed in the hope that it will be useful,
33
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35
 * GNU General Public License for more details.
36
 * You should have received a copy of the GNU General Public License
37
 * along with this program; if not, write to the Free Software
38
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
39
 *
40
 * Author: James Morris <jmorris@intercode.com.au>
41
 *
42
 * Updates:
43
 * 2000-08-06: Convert to new helper API (Harald Welte).
44
 *
45
 */
46
#include <linux/config.h>
47
#include <linux/module.h>
48
#include <linux/types.h>
49
#include <linux/kernel.h>
50
#include <linux/netfilter_ipv4.h>
51
#include <linux/netfilter_ipv4/ip_nat.h>
52
#include <linux/netfilter_ipv4/ip_nat_helper.h>
53
#include <linux/brlock.h>
54
#include <linux/types.h>
55
#include <linux/ip.h>
56
#include <net/checksum.h>
57
#include <net/udp.h>
58
#include <asm/uaccess.h>
59
 
60
 
61
 
62
#define SNMP_PORT 161
63
#define SNMP_TRAP_PORT 162
64
#define NOCT1(n) (u_int8_t )((n) & 0xff)
65
 
66
static int debug = 0;
67
static spinlock_t snmp_lock = SPIN_LOCK_UNLOCKED;
68
 
69
/*
70
 * Application layer address mapping mimics the NAT mapping, but
71
 * only for the first octet in this case (a more flexible system
72
 * can be implemented if needed).
73
 */
74
struct oct1_map
75
{
76
        u_int8_t from;
77
        u_int8_t to;
78
};
79
 
80
 
81
/*****************************************************************************
82
 *
83
 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
84
 *
85
 *****************************************************************************/
86
 
87
/* Class */
88
#define ASN1_UNI        0        /* Universal */
89
#define ASN1_APL        1       /* Application */
90
#define ASN1_CTX        2       /* Context */
91
#define ASN1_PRV        3       /* Private */
92
 
93
/* Tag */
94
#define ASN1_EOC        0        /* End Of Contents */
95
#define ASN1_BOL        1       /* Boolean */
96
#define ASN1_INT        2       /* Integer */
97
#define ASN1_BTS        3       /* Bit String */
98
#define ASN1_OTS        4       /* Octet String */
99
#define ASN1_NUL        5       /* Null */
100
#define ASN1_OJI        6       /* Object Identifier  */
101
#define ASN1_OJD        7       /* Object Description */
102
#define ASN1_EXT        8       /* External */
103
#define ASN1_SEQ        16      /* Sequence */
104
#define ASN1_SET        17      /* Set */
105
#define ASN1_NUMSTR     18      /* Numerical String */
106
#define ASN1_PRNSTR     19      /* Printable String */
107
#define ASN1_TEXSTR     20      /* Teletext String */
108
#define ASN1_VIDSTR     21      /* Video String */
109
#define ASN1_IA5STR     22      /* IA5 String */
110
#define ASN1_UNITIM     23      /* Universal Time */
111
#define ASN1_GENTIM     24      /* General Time */
112
#define ASN1_GRASTR     25      /* Graphical String */
113
#define ASN1_VISSTR     26      /* Visible String */
114
#define ASN1_GENSTR     27      /* General String */
115
 
116
/* Primitive / Constructed methods*/
117
#define ASN1_PRI        0        /* Primitive */
118
#define ASN1_CON        1       /* Constructed */
119
 
120
/*
121
 * Error codes.
122
 */
123
#define ASN1_ERR_NOERROR                0
124
#define ASN1_ERR_DEC_EMPTY              2
125
#define ASN1_ERR_DEC_EOC_MISMATCH       3
126
#define ASN1_ERR_DEC_LENGTH_MISMATCH    4
127
#define ASN1_ERR_DEC_BADVALUE           5
128
 
129
/*
130
 * ASN.1 context.
131
 */
132
struct asn1_ctx
133
{
134
        int error;                      /* Error condition */
135
        unsigned char *pointer;         /* Octet just to be decoded */
136
        unsigned char *begin;           /* First octet */
137
        unsigned char *end;             /* Octet after last octet */
138
};
139
 
140
/*
141
 * Octet string (not null terminated)
142
 */
143
struct asn1_octstr
144
{
145
        unsigned char *data;
146
        unsigned int len;
147
};
148
 
149
static void asn1_open(struct asn1_ctx *ctx,
150
                      unsigned char *buf,
151
                      unsigned int len)
152
{
153
        ctx->begin = buf;
154
        ctx->end = buf + len;
155
        ctx->pointer = buf;
156
        ctx->error = ASN1_ERR_NOERROR;
157
}
158
 
159
static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
160
{
161
        if (ctx->pointer >= ctx->end) {
162
                ctx->error = ASN1_ERR_DEC_EMPTY;
163
                return 0;
164
        }
165
        *ch = *(ctx->pointer)++;
166
        return 1;
167
}
168
 
169
static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
170
{
171
        unsigned char ch;
172
 
173
        *tag = 0;
174
 
175
        do
176
        {
177
                if (!asn1_octet_decode(ctx, &ch))
178
                        return 0;
179
                *tag <<= 7;
180
                *tag |= ch & 0x7F;
181
        } while ((ch & 0x80) == 0x80);
182
        return 1;
183
}
184
 
185
static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
186
                                    unsigned int *cls,
187
                                    unsigned int *con,
188
                                    unsigned int *tag)
189
{
190
        unsigned char ch;
191
 
192
        if (!asn1_octet_decode(ctx, &ch))
193
                return 0;
194
 
195
        *cls = (ch & 0xC0) >> 6;
196
        *con = (ch & 0x20) >> 5;
197
        *tag = (ch & 0x1F);
198
 
199
        if (*tag == 0x1F) {
200
                if (!asn1_tag_decode(ctx, tag))
201
                        return 0;
202
        }
203
        return 1;
204
}
205
 
206
static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
207
                                        unsigned int *def,
208
                                        unsigned int *len)
209
{
210
        unsigned char ch, cnt;
211
 
212
        if (!asn1_octet_decode(ctx, &ch))
213
                return 0;
214
 
215
        if (ch == 0x80)
216
                *def = 0;
217
        else {
218
                *def = 1;
219
 
220
                if (ch < 0x80)
221
                        *len = ch;
222
                else {
223
                        cnt = (unsigned char) (ch & 0x7F);
224
                        *len = 0;
225
 
226
                        while (cnt > 0) {
227
                                if (!asn1_octet_decode(ctx, &ch))
228
                                        return 0;
229
                                *len <<= 8;
230
                                *len |= ch;
231
                                cnt--;
232
                        }
233
                }
234
        }
235
        return 1;
236
}
237
 
238
static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
239
                                        unsigned char **eoc,
240
                                        unsigned int *cls,
241
                                        unsigned int *con,
242
                                        unsigned int *tag)
243
{
244
        unsigned int def, len;
245
 
246
        if (!asn1_id_decode(ctx, cls, con, tag))
247
                return 0;
248
 
249
        if (!asn1_length_decode(ctx, &def, &len))
250
                return 0;
251
 
252
        if (def)
253
                *eoc = ctx->pointer + len;
254
        else
255
                *eoc = 0;
256
        return 1;
257
}
258
 
259
static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
260
{
261
        unsigned char ch;
262
 
263
        if (eoc == 0) {
264
                if (!asn1_octet_decode(ctx, &ch))
265
                        return 0;
266
 
267
                if (ch != 0x00) {
268
                        ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
269
                        return 0;
270
                }
271
 
272
                if (!asn1_octet_decode(ctx, &ch))
273
                        return 0;
274
 
275
                if (ch != 0x00) {
276
                        ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
277
                        return 0;
278
                }
279
                return 1;
280
        } else {
281
                if (ctx->pointer != eoc) {
282
                        ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
283
                        return 0;
284
                }
285
                return 1;
286
        }
287
}
288
 
289
static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
290
{
291
        ctx->pointer = eoc;
292
        return 1;
293
}
294
 
295
static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
296
                                      unsigned char *eoc,
297
                                      long *integer)
298
{
299
        unsigned char ch;
300
        unsigned int  len;
301
 
302
        if (!asn1_octet_decode(ctx, &ch))
303
                return 0;
304
 
305
        *integer = (signed char) ch;
306
        len = 1;
307
 
308
        while (ctx->pointer < eoc) {
309
                if (++len > sizeof (long)) {
310
                        ctx->error = ASN1_ERR_DEC_BADVALUE;
311
                        return 0;
312
                }
313
 
314
                if (!asn1_octet_decode(ctx, &ch))
315
                        return 0;
316
 
317
                *integer <<= 8;
318
                *integer |= ch;
319
        }
320
        return 1;
321
}
322
 
323
static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
324
                                      unsigned char *eoc,
325
                                      unsigned int *integer)
326
{
327
        unsigned char ch;
328
        unsigned int  len;
329
 
330
        if (!asn1_octet_decode(ctx, &ch))
331
                return 0;
332
 
333
        *integer = ch;
334
        if (ch == 0) len = 0;
335
        else len = 1;
336
 
337
        while (ctx->pointer < eoc) {
338
                if (++len > sizeof (unsigned int)) {
339
                        ctx->error = ASN1_ERR_DEC_BADVALUE;
340
                        return 0;
341
                }
342
 
343
                if (!asn1_octet_decode(ctx, &ch))
344
                        return 0;
345
 
346
                *integer <<= 8;
347
                *integer |= ch;
348
        }
349
        return 1;
350
}
351
 
352
static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
353
                                       unsigned char *eoc,
354
                                       unsigned long *integer)
355
{
356
        unsigned char ch;
357
        unsigned int  len;
358
 
359
        if (!asn1_octet_decode(ctx, &ch))
360
                return 0;
361
 
362
        *integer = ch;
363
        if (ch == 0) len = 0;
364
        else len = 1;
365
 
366
        while (ctx->pointer < eoc) {
367
                if (++len > sizeof (unsigned long)) {
368
                        ctx->error = ASN1_ERR_DEC_BADVALUE;
369
                        return 0;
370
                }
371
 
372
                if (!asn1_octet_decode(ctx, &ch))
373
                        return 0;
374
 
375
                *integer <<= 8;
376
                *integer |= ch;
377
        }
378
        return 1;
379
}
380
 
381
static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
382
                                        unsigned char *eoc,
383
                                        unsigned char **octets,
384
                                        unsigned int *len)
385
{
386
        unsigned char *ptr;
387
 
388
        *len = 0;
389
 
390
        *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
391
        if (*octets == NULL) {
392
                if (net_ratelimit())
393
                        printk("OOM in bsalg (%d)\n", __LINE__);
394
                return 0;
395
        }
396
 
397
        ptr = *octets;
398
        while (ctx->pointer < eoc) {
399
                if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {
400
                        kfree(*octets);
401
                        *octets = NULL;
402
                        return 0;
403
                }
404
                (*len)++;
405
        }
406
        return 1;
407
}
408
 
409
static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
410
                                       unsigned long *subid)
411
{
412
        unsigned char ch;
413
 
414
        *subid = 0;
415
 
416
        do {
417
                if (!asn1_octet_decode(ctx, &ch))
418
                        return 0;
419
 
420
                *subid <<= 7;
421
                *subid |= ch & 0x7F;
422
        } while ((ch & 0x80) == 0x80);
423
        return 1;
424
}
425
 
426
static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
427
                                     unsigned char *eoc,
428
                                     unsigned long **oid,
429
                                     unsigned int *len)
430
{
431
        unsigned long subid;
432
        unsigned int  size;
433
        unsigned long *optr;
434
 
435
        size = eoc - ctx->pointer + 1;
436
        *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
437
        if (*oid == NULL) {
438
                if (net_ratelimit())
439
                        printk("OOM in bsalg (%d)\n", __LINE__);
440
                return 0;
441
        }
442
 
443
        optr = *oid;
444
 
445
        if (!asn1_subid_decode(ctx, &subid)) {
446
                kfree(*oid);
447
                *oid = NULL;
448
                return 0;
449
        }
450
 
451
        if (subid < 40) {
452
                optr [0] = 0;
453
                optr [1] = subid;
454
        } else if (subid < 80) {
455
                optr [0] = 1;
456
                optr [1] = subid - 40;
457
        } else {
458
                optr [0] = 2;
459
                optr [1] = subid - 80;
460
        }
461
 
462
        *len = 2;
463
        optr += 2;
464
 
465
        while (ctx->pointer < eoc) {
466
                if (++(*len) > size) {
467
                        ctx->error = ASN1_ERR_DEC_BADVALUE;
468
                        kfree(*oid);
469
                        *oid = NULL;
470
                        return 0;
471
                }
472
 
473
                if (!asn1_subid_decode(ctx, optr++)) {
474
                        kfree(*oid);
475
                        *oid = NULL;
476
                        return 0;
477
                }
478
        }
479
        return 1;
480
}
481
 
482
/*****************************************************************************
483
 *
484
 * SNMP decoding routines (gxsnmp author Dirk Wisse)
485
 *
486
 *****************************************************************************/
487
 
488
/* SNMP Versions */
489
#define SNMP_V1                         0
490
#define SNMP_V2C                        1
491
#define SNMP_V2                         2
492
#define SNMP_V3                         3
493
 
494
/* Default Sizes */
495
#define SNMP_SIZE_COMM                  256
496
#define SNMP_SIZE_OBJECTID              128
497
#define SNMP_SIZE_BUFCHR                256
498
#define SNMP_SIZE_BUFINT                128
499
#define SNMP_SIZE_SMALLOBJECTID         16
500
 
501
/* Requests */
502
#define SNMP_PDU_GET                    0
503
#define SNMP_PDU_NEXT                   1
504
#define SNMP_PDU_RESPONSE               2
505
#define SNMP_PDU_SET                    3
506
#define SNMP_PDU_TRAP1                  4
507
#define SNMP_PDU_BULK                   5
508
#define SNMP_PDU_INFORM                 6
509
#define SNMP_PDU_TRAP2                  7
510
 
511
/* Errors */
512
#define SNMP_NOERROR                    0
513
#define SNMP_TOOBIG                     1
514
#define SNMP_NOSUCHNAME                 2
515
#define SNMP_BADVALUE                   3
516
#define SNMP_READONLY                   4
517
#define SNMP_GENERROR                   5
518
#define SNMP_NOACCESS                   6
519
#define SNMP_WRONGTYPE                  7
520
#define SNMP_WRONGLENGTH                8
521
#define SNMP_WRONGENCODING              9
522
#define SNMP_WRONGVALUE                 10
523
#define SNMP_NOCREATION                 11
524
#define SNMP_INCONSISTENTVALUE          12
525
#define SNMP_RESOURCEUNAVAILABLE        13
526
#define SNMP_COMMITFAILED               14
527
#define SNMP_UNDOFAILED                 15
528
#define SNMP_AUTHORIZATIONERROR         16
529
#define SNMP_NOTWRITABLE                17
530
#define SNMP_INCONSISTENTNAME           18
531
 
532
/* General SNMP V1 Traps */
533
#define SNMP_TRAP_COLDSTART             0
534
#define SNMP_TRAP_WARMSTART             1
535
#define SNMP_TRAP_LINKDOWN              2
536
#define SNMP_TRAP_LINKUP                3
537
#define SNMP_TRAP_AUTFAILURE            4
538
#define SNMP_TRAP_EQPNEIGHBORLOSS       5
539
#define SNMP_TRAP_ENTSPECIFIC           6
540
 
541
/* SNMPv1 Types */
542
#define SNMP_NULL                0
543
#define SNMP_INTEGER             1    /* l  */
544
#define SNMP_OCTETSTR            2    /* c  */
545
#define SNMP_DISPLAYSTR          2    /* c  */
546
#define SNMP_OBJECTID            3    /* ul */
547
#define SNMP_IPADDR              4    /* uc */
548
#define SNMP_COUNTER             5    /* ul */
549
#define SNMP_GAUGE               6    /* ul */
550
#define SNMP_TIMETICKS           7    /* ul */
551
#define SNMP_OPAQUE              8    /* c  */
552
 
553
/* Additional SNMPv2 Types */
554
#define SNMP_UINTEGER            5    /* ul */
555
#define SNMP_BITSTR              9    /* uc */
556
#define SNMP_NSAP               10    /* uc */
557
#define SNMP_COUNTER64          11    /* ul */
558
#define SNMP_NOSUCHOBJECT       12
559
#define SNMP_NOSUCHINSTANCE     13
560
#define SNMP_ENDOFMIBVIEW       14
561
 
562
union snmp_syntax
563
{
564
        unsigned char uc[0];     /* 8 bit unsigned */
565
        char c[0];               /* 8 bit signed */
566
        unsigned long ul[0];     /* 32 bit unsigned */
567
        long l[0];               /* 32 bit signed */
568
};
569
 
570
struct snmp_object
571
{
572
        unsigned long *id;
573
        unsigned int id_len;
574
        unsigned short type;
575
        unsigned int syntax_len;
576
        union snmp_syntax syntax;
577
};
578
 
579
struct snmp_request
580
{
581
        unsigned long id;
582
        unsigned int error_status;
583
        unsigned int error_index;
584
};
585
 
586
struct snmp_v1_trap
587
{
588
        unsigned long *id;
589
        unsigned int id_len;
590
        unsigned long ip_address;       /* pointer  */
591
        unsigned int general;
592
        unsigned int specific;
593
        unsigned long time;
594
};
595
 
596
/* SNMP types */
597
#define SNMP_IPA    0
598
#define SNMP_CNT    1
599
#define SNMP_GGE    2
600
#define SNMP_TIT    3
601
#define SNMP_OPQ    4
602
#define SNMP_C64    6
603
 
604
/* SNMP errors */
605
#define SERR_NSO    0
606
#define SERR_NSI    1
607
#define SERR_EOM    2
608
 
609
static void inline mangle_address(unsigned char *begin,
610
                                  unsigned char *addr,
611
                                  const struct oct1_map *map,
612
                                  u_int16_t *check);
613
struct snmp_cnv
614
{
615
        unsigned int class;
616
        unsigned int tag;
617
        int syntax;
618
};
619
 
620
static struct snmp_cnv snmp_conv [] =
621
{
622
        {ASN1_UNI, ASN1_NUL, SNMP_NULL},
623
        {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
624
        {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
625
        {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},
626
        {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},
627
        {ASN1_APL, SNMP_IPA, SNMP_IPADDR},
628
        {ASN1_APL, SNMP_CNT, SNMP_COUNTER},     /* Counter32 */
629
        {ASN1_APL, SNMP_GGE, SNMP_GAUGE},       /* Gauge32 == Unsigned32  */
630
        {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
631
        {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
632
 
633
        /* SNMPv2 data types and errors */
634
        {ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
635
        {ASN1_APL, SNMP_C64, SNMP_COUNTER64},
636
        {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},
637
        {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},
638
        {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},
639
        {0,       0,       -1}
640
};
641
 
642
static unsigned char snmp_tag_cls2syntax(unsigned int tag,
643
                                         unsigned int cls,
644
                                         unsigned short *syntax)
645
{
646
        struct snmp_cnv *cnv;
647
 
648
        cnv = snmp_conv;
649
 
650
        while (cnv->syntax != -1) {
651
                if (cnv->tag == tag && cnv->class == cls) {
652
                        *syntax = cnv->syntax;
653
                        return 1;
654
                }
655
                cnv++;
656
        }
657
        return 0;
658
}
659
 
660
static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
661
                                        struct snmp_object **obj)
662
{
663
        unsigned int cls, con, tag, len, idlen;
664
        unsigned short type;
665
        unsigned char *eoc, *end, *p;
666
        unsigned long *lp, *id;
667
        unsigned long ul;
668
        long  l;
669
 
670
        *obj = NULL;
671
        id = NULL;
672
 
673
        if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
674
                return 0;
675
 
676
        if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
677
                return 0;
678
 
679
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
680
                return 0;
681
 
682
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
683
                return 0;
684
 
685
        if (!asn1_oid_decode(ctx, end, &id, &idlen))
686
                return 0;
687
 
688
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
689
                kfree(id);
690
                return 0;
691
        }
692
 
693
        if (con != ASN1_PRI) {
694
                kfree(id);
695
                return 0;
696
        }
697
 
698
        if (!snmp_tag_cls2syntax(tag, cls, &type)) {
699
                kfree(id);
700
                return 0;
701
        }
702
 
703
        switch (type) {
704
                case SNMP_INTEGER:
705
                        len = sizeof(long);
706
                        if (!asn1_long_decode(ctx, end, &l)) {
707
                                kfree(id);
708
                                return 0;
709
                        }
710
                        *obj = kmalloc(sizeof(struct snmp_object) + len,
711
                                       GFP_ATOMIC);
712
                        if (*obj == NULL) {
713
                                kfree(id);
714
                                if (net_ratelimit())
715
                                        printk("OOM in bsalg (%d)\n", __LINE__);
716
                                return 0;
717
                        }
718
                        (*obj)->syntax.l[0] = l;
719
                        break;
720
                case SNMP_OCTETSTR:
721
                case SNMP_OPAQUE:
722
                        if (!asn1_octets_decode(ctx, end, &p, &len)) {
723
                                kfree(id);
724
                                return 0;
725
                        }
726
                        *obj = kmalloc(sizeof(struct snmp_object) + len,
727
                                       GFP_ATOMIC);
728
                        if (*obj == NULL) {
729
                                kfree(id);
730
                                if (net_ratelimit())
731
                                        printk("OOM in bsalg (%d)\n", __LINE__);
732
                                return 0;
733
                        }
734
                        memcpy((*obj)->syntax.c, p, len);
735
                        kfree(p);
736
                        break;
737
                case SNMP_NULL:
738
                case SNMP_NOSUCHOBJECT:
739
                case SNMP_NOSUCHINSTANCE:
740
                case SNMP_ENDOFMIBVIEW:
741
                        len = 0;
742
                        *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
743
                        if (*obj == NULL) {
744
                                kfree(id);
745
                                if (net_ratelimit())
746
                                        printk("OOM in bsalg (%d)\n", __LINE__);
747
                                return 0;
748
                        }
749
                        if (!asn1_null_decode(ctx, end)) {
750
                                kfree(id);
751
                                kfree(*obj);
752
                                *obj = NULL;
753
                                return 0;
754
                        }
755
                        break;
756
                case SNMP_OBJECTID:
757
                        if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
758
                                kfree(id);
759
                                return 0;
760
                        }
761
                        len *= sizeof(unsigned long);
762
                        *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
763
                        if (*obj == NULL) {
764
                                kfree(id);
765
                                if (net_ratelimit())
766
                                        printk("OOM in bsalg (%d)\n", __LINE__);
767
                                return 0;
768
                        }
769
                        memcpy((*obj)->syntax.ul, lp, len);
770
                        kfree(lp);
771
                        break;
772
                case SNMP_IPADDR:
773
                        if (!asn1_octets_decode(ctx, end, &p, &len)) {
774
                                kfree(id);
775
                                return 0;
776
                        }
777
                        if (len != 4) {
778
                                kfree(p);
779
                                kfree(id);
780
                                return 0;
781
                        }
782
                        *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
783
                        if (*obj == NULL) {
784
                                kfree(p);
785
                                kfree(id);
786
                                if (net_ratelimit())
787
                                        printk("OOM in bsalg (%d)\n", __LINE__);
788
                                return 0;
789
                        }
790
                        memcpy((*obj)->syntax.uc, p, len);
791
                        kfree(p);
792
                        break;
793
                case SNMP_COUNTER:
794
                case SNMP_GAUGE:
795
                case SNMP_TIMETICKS:
796
                        len = sizeof(unsigned long);
797
                        if (!asn1_ulong_decode(ctx, end, &ul)) {
798
                                kfree(id);
799
                                return 0;
800
                        }
801
                        *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
802
                        if (*obj == NULL) {
803
                                kfree(id);
804
                                if (net_ratelimit())
805
                                        printk("OOM in bsalg (%d)\n", __LINE__);
806
                                return 0;
807
                        }
808
                        (*obj)->syntax.ul[0] = ul;
809
                        break;
810
                default:
811
                        kfree(id);
812
                        return 0;
813
        }
814
 
815
        (*obj)->syntax_len = len;
816
        (*obj)->type = type;
817
        (*obj)->id = id;
818
        (*obj)->id_len = idlen;
819
 
820
        if (!asn1_eoc_decode(ctx, eoc)) {
821
                kfree(id);
822
                kfree(*obj);
823
                *obj = NULL;
824
                return 0;
825
        }
826
        return 1;
827
}
828
 
829
static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
830
                                         struct snmp_request *request)
831
{
832
        unsigned int cls, con, tag;
833
        unsigned char *end;
834
 
835
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
836
                return 0;
837
 
838
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
839
                return 0;
840
 
841
        if (!asn1_ulong_decode(ctx, end, &request->id))
842
                return 0;
843
 
844
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
845
                return 0;
846
 
847
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
848
                return 0;
849
 
850
        if (!asn1_uint_decode(ctx, end, &request->error_status))
851
                return 0;
852
 
853
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
854
                return 0;
855
 
856
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
857
                return 0;
858
 
859
        if (!asn1_uint_decode(ctx, end, &request->error_index))
860
                return 0;
861
 
862
        return 1;
863
}
864
 
865
static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
866
                                      struct snmp_v1_trap *trap,
867
                                      const struct oct1_map *map,
868
                                      u_int16_t *check)
869
{
870
        unsigned int cls, con, tag, len;
871
        unsigned char *end;
872
 
873
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
874
                return 0;
875
 
876
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
877
                return 0;
878
 
879
        if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
880
                return 0;
881
 
882
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
883
                goto err_id_free;
884
 
885
        if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
886
              (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
887
                goto err_id_free;
888
 
889
        if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
890
                goto err_id_free;
891
 
892
        /* IPv4 only */
893
        if (len != 4)
894
                goto err_addr_free;
895
 
896
        mangle_address(ctx->begin, ctx->pointer - 4, map, check);
897
 
898
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
899
                goto err_addr_free;
900
 
901
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
902
                goto err_addr_free;;
903
 
904
        if (!asn1_uint_decode(ctx, end, &trap->general))
905
                goto err_addr_free;;
906
 
907
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
908
                goto err_addr_free;
909
 
910
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
911
                goto err_addr_free;
912
 
913
        if (!asn1_uint_decode(ctx, end, &trap->specific))
914
                goto err_addr_free;
915
 
916
        if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
917
                goto err_addr_free;
918
 
919
        if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
920
              (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
921
                goto err_addr_free;
922
 
923
        if (!asn1_ulong_decode(ctx, end, &trap->time))
924
                goto err_addr_free;
925
 
926
        return 1;
927
 
928
err_id_free:
929
        kfree(trap->id);
930
 
931
err_addr_free:
932
        kfree((unsigned long *)trap->ip_address);
933
 
934
        return 0;
935
}
936
 
937
/*****************************************************************************
938
 *
939
 * Misc. routines
940
 *
941
 *****************************************************************************/
942
 
943
static void hex_dump(unsigned char *buf, size_t len)
944
{
945
        size_t i;
946
 
947
        for (i = 0; i < len; i++) {
948
                if (i && !(i % 16))
949
                        printk("\n");
950
                printk("%02x ", *(buf + i));
951
        }
952
        printk("\n");
953
}
954
 
955
/*
956
 * Fast checksum update for possibly oddly-aligned UDP byte, from the
957
 * code example in the draft.
958
 */
959
static void fast_csum(unsigned char *csum,
960
                      const unsigned char *optr,
961
                      const unsigned char *nptr,
962
                      int odd)
963
{
964
        long x, old, new;
965
 
966
        x = csum[0] * 256 + csum[1];
967
 
968
        x =~ x & 0xFFFF;
969
 
970
        if (odd) old = optr[0] * 256;
971
        else old = optr[0];
972
 
973
        x -= old & 0xFFFF;
974
        if (x <= 0) {
975
                x--;
976
                x &= 0xFFFF;
977
        }
978
 
979
        if (odd) new = nptr[0] * 256;
980
        else new = nptr[0];
981
 
982
        x += new & 0xFFFF;
983
        if (x & 0x10000) {
984
                x++;
985
                x &= 0xFFFF;
986
        }
987
 
988
        x =~ x & 0xFFFF;
989
        csum[0] = x / 256;
990
        csum[1] = x & 0xFF;
991
}
992
 
993
/*
994
 * Mangle IP address.
995
 *      - begin points to the start of the snmp messgae
996
 *      - addr points to the start of the address
997
 */
998
static void inline mangle_address(unsigned char *begin,
999
                                  unsigned char *addr,
1000
                                  const struct oct1_map *map,
1001
                                  u_int16_t *check)
1002
{
1003
        if (map->from == NOCT1(*addr)) {
1004
                u_int32_t old;
1005
 
1006
                if (debug)
1007
                        memcpy(&old, (unsigned char *)addr, sizeof(old));
1008
 
1009
                *addr = map->to;
1010
 
1011
                /* Update UDP checksum if being used */
1012
                if (*check) {
1013
                        unsigned char odd = !((addr - begin) % 2);
1014
 
1015
                        fast_csum((unsigned char *)check,
1016
                                  &map->from, &map->to, odd);
1017
 
1018
                }
1019
 
1020
                if (debug)
1021
                        printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
1022
                               "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
1023
        }
1024
}
1025
 
1026
/*
1027
 * Parse and mangle SNMP message according to mapping.
1028
 * (And this is the fucking 'basic' method).
1029
 */
1030
static int snmp_parse_mangle(unsigned char *msg,
1031
                             u_int16_t len,
1032
                             const struct oct1_map *map,
1033
                             u_int16_t *check)
1034
{
1035
        unsigned char *eoc, *end;
1036
        unsigned int cls, con, tag, vers, pdutype;
1037
        struct asn1_ctx ctx;
1038
        struct asn1_octstr comm;
1039
        struct snmp_object **obj;
1040
 
1041
        if (debug > 1)
1042
                hex_dump(msg, len);
1043
 
1044
        asn1_open(&ctx, msg, len);
1045
 
1046
        /*
1047
         * Start of SNMP message.
1048
         */
1049
        if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1050
                return 0;
1051
        if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1052
                return 0;
1053
 
1054
        /*
1055
         * Version 1 or 2 handled.
1056
         */
1057
        if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
1058
                return 0;
1059
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
1060
                return 0;
1061
        if (!asn1_uint_decode (&ctx, end, &vers))
1062
                return 0;
1063
        if (debug > 1)
1064
                printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
1065
        if (vers > 1)
1066
                return 1;
1067
 
1068
        /*
1069
         * Community.
1070
         */
1071
        if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
1072
                return 0;
1073
        if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1074
                return 0;
1075
        if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
1076
                return 0;
1077
        if (debug > 1) {
1078
                unsigned int i;
1079
 
1080
                printk(KERN_DEBUG "bsalg: community: ");
1081
                for (i = 0; i < comm.len; i++)
1082
                        printk("%c", comm.data[i]);
1083
                printk("\n");
1084
        }
1085
        kfree(comm.data);
1086
 
1087
        /*
1088
         * PDU type
1089
         */
1090
        if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
1091
                return 0;
1092
        if (cls != ASN1_CTX || con != ASN1_CON)
1093
                return 0;
1094
        if (debug > 1) {
1095
                unsigned char *pdus[] = {
1096
                        [SNMP_PDU_GET] = "get",
1097
                        [SNMP_PDU_NEXT] = "get-next",
1098
                        [SNMP_PDU_RESPONSE] = "response",
1099
                        [SNMP_PDU_SET] = "set",
1100
                        [SNMP_PDU_TRAP1] = "trapv1",
1101
                        [SNMP_PDU_BULK] = "bulk",
1102
                        [SNMP_PDU_INFORM] = "inform",
1103
                        [SNMP_PDU_TRAP2] = "trapv2"
1104
                };
1105
 
1106
                if (pdutype > SNMP_PDU_TRAP2)
1107
                        printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
1108
                else
1109
                        printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);
1110
        }
1111
        if (pdutype != SNMP_PDU_RESPONSE &&
1112
            pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
1113
                return 1;
1114
 
1115
        /*
1116
         * Request header or v1 trap
1117
         */
1118
        if (pdutype == SNMP_PDU_TRAP1) {
1119
                struct snmp_v1_trap trap;
1120
                unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
1121
 
1122
                /* Discard trap allocations regardless */
1123
                kfree(trap.id);
1124
                kfree((unsigned long *)trap.ip_address);
1125
 
1126
                if (!ret)
1127
                        return ret;
1128
 
1129
        } else {
1130
                struct snmp_request req;
1131
 
1132
                if (!snmp_request_decode(&ctx, &req))
1133
                        return 0;
1134
 
1135
                if (debug > 1)
1136
                        printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
1137
                        "error_index=%u\n", req.id, req.error_status,
1138
                        req.error_index);
1139
        }
1140
 
1141
        /*
1142
         * Loop through objects, look for IP addresses to mangle.
1143
         */
1144
        if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1145
                return 0;
1146
 
1147
        if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1148
                return 0;
1149
 
1150
        obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
1151
        if (obj == NULL) {
1152
                if (net_ratelimit())
1153
                        printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
1154
                return 0;
1155
        }
1156
 
1157
        while (!asn1_eoc_decode(&ctx, eoc)) {
1158
                unsigned int i;
1159
 
1160
                if (!snmp_object_decode(&ctx, obj)) {
1161
                        if (*obj) {
1162
                                if ((*obj)->id)
1163
                                        kfree((*obj)->id);
1164
                                kfree(*obj);
1165
                        }
1166
                        kfree(obj);
1167
                        return 0;
1168
                }
1169
 
1170
                if (debug > 1) {
1171
                        printk(KERN_DEBUG "bsalg: object: ");
1172
                        for (i = 0; i < (*obj)->id_len; i++) {
1173
                                if (i > 0)
1174
                                        printk(".");
1175
                                printk("%lu", (*obj)->id[i]);
1176
                        }
1177
                        printk(": type=%u\n", (*obj)->type);
1178
 
1179
                }
1180
 
1181
                if ((*obj)->type == SNMP_IPADDR)
1182
                        mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
1183
 
1184
                kfree((*obj)->id);
1185
                kfree(*obj);
1186
        }
1187
        kfree(obj);
1188
 
1189
        if (!asn1_eoc_decode(&ctx, eoc))
1190
                return 0;
1191
 
1192
        return 1;
1193
}
1194
 
1195
/*****************************************************************************
1196
 *
1197
 * NAT routines.
1198
 *
1199
 *****************************************************************************/
1200
 
1201
/*
1202
 * SNMP translation routine.
1203
 */
1204
static int snmp_translate(struct ip_conntrack *ct,
1205
                          struct ip_nat_info *info,
1206
                          enum ip_conntrack_info ctinfo,
1207
                          unsigned int hooknum,
1208
                          struct sk_buff **pskb)
1209
{
1210
        struct iphdr *iph = (*pskb)->nh.iph;
1211
        struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
1212
        u_int16_t udplen = ntohs(udph->len);
1213
        u_int16_t paylen = udplen - sizeof(struct udphdr);
1214
        int dir = CTINFO2DIR(ctinfo);
1215
        struct oct1_map map;
1216
 
1217
        /*
1218
         * Determine mappping for application layer addresses based
1219
         * on NAT manipulations for the packet.
1220
         */
1221
        if (dir == IP_CT_DIR_ORIGINAL) {
1222
                /* SNAT traps */
1223
                map.from = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);
1224
                map.to = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);
1225
        } else {
1226
                /* DNAT replies */
1227
                map.from = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
1228
                map.to = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
1229
        }
1230
 
1231
        if (map.from == map.to)
1232
                return NF_ACCEPT;
1233
 
1234
        if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
1235
                               paylen, &map, &udph->check)) {
1236
                printk(KERN_WARNING "bsalg: parser failed\n");
1237
                return NF_DROP;
1238
        }
1239
        return NF_ACCEPT;
1240
}
1241
 
1242
/*
1243
 * NAT helper function, packets arrive here from NAT code.
1244
 */
1245
static unsigned int nat_help(struct ip_conntrack *ct,
1246
                             struct ip_conntrack_expect *exp,
1247
                             struct ip_nat_info *info,
1248
                             enum ip_conntrack_info ctinfo,
1249
                             unsigned int hooknum,
1250
                             struct sk_buff **pskb)
1251
{
1252
        int dir = CTINFO2DIR(ctinfo);
1253
        struct iphdr *iph = (*pskb)->nh.iph;
1254
        struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
1255
 
1256
        spin_lock_bh(&snmp_lock);
1257
 
1258
        /*
1259
         * Translate snmp replies on pre-routing (DNAT) and snmp traps
1260
         * on post routing (SNAT).
1261
         */
1262
        if (!((dir == IP_CT_DIR_REPLY && hooknum == NF_IP_PRE_ROUTING &&
1263
                        udph->source == ntohs(SNMP_PORT)) ||
1264
              (dir == IP_CT_DIR_ORIGINAL && hooknum == NF_IP_POST_ROUTING &&
1265
                        udph->dest == ntohs(SNMP_TRAP_PORT)))) {
1266
                spin_unlock_bh(&snmp_lock);
1267
                return NF_ACCEPT;
1268
        }
1269
 
1270
        if (debug > 1) {
1271
                printk(KERN_DEBUG "bsalg: dir=%s hook=%d manip=%s len=%d "
1272
                       "src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u "
1273
                       "osrc=%u.%u.%u.%u odst=%u.%u.%u.%u "
1274
                       "rsrc=%u.%u.%u.%u rdst=%u.%u.%u.%u "
1275
                       "\n",
1276
                       dir == IP_CT_DIR_REPLY ? "reply" : "orig", hooknum,
1277
                       HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? "snat" :
1278
                       "dnat", (*pskb)->len,
1279
                       NIPQUAD(iph->saddr), ntohs(udph->source),
1280
                       NIPQUAD(iph->daddr), ntohs(udph->dest),
1281
                       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
1282
                       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
1283
                       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
1284
                       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip));
1285
        }
1286
 
1287
        /*
1288
         * Make sure the packet length is ok.  So far, we were only guaranteed
1289
         * to have a valid length IP header plus 8 bytes, which means we have
1290
         * enough room for a UDP header.  Just verify the UDP length field so we
1291
         * can mess around with the payload.
1292
         */
1293
         if (ntohs(udph->len) == (*pskb)->len - (iph->ihl << 2)) {
1294
                int ret = snmp_translate(ct, info, ctinfo, hooknum, pskb);
1295
                spin_unlock_bh(&snmp_lock);
1296
                return ret;
1297
        }
1298
 
1299
        if (net_ratelimit())
1300
                printk(KERN_WARNING "bsalg: dropping malformed packet "
1301
                       "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
1302
                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1303
        spin_unlock_bh(&snmp_lock);
1304
        return NF_DROP;
1305
}
1306
 
1307
static struct ip_nat_helper snmp = {
1308
        { NULL, NULL },
1309
        "snmp",
1310
        IP_NAT_HELPER_F_STANDALONE,
1311
        THIS_MODULE,
1312
        { { 0, { .udp = { __constant_htons(SNMP_PORT) } } },
1313
          { 0, { 0 }, IPPROTO_UDP } },
1314
        { { 0, { .udp = { 0xFFFF } } },
1315
          { 0, { 0 }, 0xFFFF } },
1316
        nat_help, NULL };
1317
 
1318
static struct ip_nat_helper snmp_trap = {
1319
        { NULL, NULL },
1320
        "snmp_trap",
1321
        IP_NAT_HELPER_F_STANDALONE,
1322
        THIS_MODULE,
1323
        { { 0, { .udp = { __constant_htons(SNMP_TRAP_PORT) } } },
1324
          { 0, { 0 }, IPPROTO_UDP } },
1325
        { { 0, { .udp = { 0xFFFF } } },
1326
          { 0, { 0 }, 0xFFFF } },
1327
        nat_help, NULL };
1328
 
1329
/*****************************************************************************
1330
 *
1331
 * Module stuff.
1332
 *
1333
 *****************************************************************************/
1334
 
1335
static int __init init(void)
1336
{
1337
        int ret = 0;
1338
 
1339
        ret = ip_nat_helper_register(&snmp);
1340
        if (ret < 0)
1341
                return ret;
1342
        ret = ip_nat_helper_register(&snmp_trap);
1343
        if (ret < 0) {
1344
                ip_nat_helper_unregister(&snmp);
1345
                return ret;
1346
        }
1347
        return ret;
1348
}
1349
 
1350
static void __exit fini(void)
1351
{
1352
        ip_nat_helper_unregister(&snmp);
1353
        ip_nat_helper_unregister(&snmp_trap);
1354
        br_write_lock_bh(BR_NETPROTO_LOCK);
1355
        br_write_unlock_bh(BR_NETPROTO_LOCK);
1356
}
1357
 
1358
module_init(init);
1359
module_exit(fini);
1360
 
1361
MODULE_PARM(debug, "i");
1362
MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
1363
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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