~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv4/netfilter/nf_nat_snmp_basic.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.15 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.73 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.144 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.193 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.193 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp