linux/net/ipv4/netfilter/nf_nat_snmp_basic.c
<<
>>
Prefs
   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
  59MODULE_LICENSE("GPL");
  60MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
  61MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
  62MODULE_ALIAS("ip_nat_snmp_basic");
  63
  64#define SNMP_PORT 161
  65#define SNMP_TRAP_PORT 162
  66#define NOCT1(n) (*(u8 *)(n))
  67
  68static int debug;
  69static 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 */
  76struct 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 */
 134struct 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 */
 145struct asn1_octstr
 146{
 147        unsigned char *data;
 148        unsigned int len;
 149};
 150
 151static 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
 161static 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
 171static 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
 187static 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
 208static 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
 245static 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
 271static 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
 301static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
 302{
 303        ctx->pointer = eoc;
 304        return 1;
 305}
 306
 307static 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
 335static 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
 364static 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
 393static 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, (unsigned char *)ptr++)) {
 409                        kfree(*octets);
 410                        *octets = NULL;
 411                        return 0;
 412                }
 413                (*len)++;
 414        }
 415        return 1;
 416}
 417
 418static 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
 435static 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
 573union 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
 581struct 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
 590struct snmp_request
 591{
 592        unsigned long id;
 593        unsigned int error_status;
 594        unsigned int error_index;
 595};
 596
 597struct 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
 620static inline void mangle_address(unsigned char *begin,
 621                                  unsigned char *addr,
 622                                  const struct oct1_map *map,
 623                                  __sum16 *check);
 624struct snmp_cnv
 625{
 626        unsigned int class;
 627        unsigned int tag;
 628        int syntax;
 629};
 630
 631static 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
 652static 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
 670static 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, (unsigned long **)&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
 829static 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 */
 869static 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 */
 896static 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
 922static 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
 985err_addr_free:
 986        kfree((unsigned long *)trap->ip_address);
 987
 988err_id_free:
 989        kfree(trap->id);
 990
 991        return 0;
 992}
 993
 994/*****************************************************************************
 995 *
 996 * Misc. routines
 997 *
 998 *****************************************************************************/
 999
1000static 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 */
1016static 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 */
1179static 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                if (net_ratelimit())
1210                        printk(KERN_WARNING "bsalg: parser failed\n");
1211                return NF_DROP;
1212        }
1213        return NF_ACCEPT;
1214}
1215
1216/* We don't actually set up expectations, just adjust internal IP
1217 * addresses if this is being NATted */
1218static int help(struct sk_buff *skb, unsigned int protoff,
1219                struct nf_conn *ct,
1220                enum ip_conntrack_info ctinfo)
1221{
1222        int dir = CTINFO2DIR(ctinfo);
1223        unsigned int ret;
1224        const struct iphdr *iph = ip_hdr(skb);
1225        const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1226
1227        /* SNMP replies and originating SNMP traps get mangled */
1228        if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
1229                return NF_ACCEPT;
1230        if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
1231                return NF_ACCEPT;
1232
1233        /* No NAT? */
1234        if (!(ct->status & IPS_NAT_MASK))
1235                return NF_ACCEPT;
1236
1237        /*
1238         * Make sure the packet length is ok.  So far, we were only guaranteed
1239         * to have a valid length IP header plus 8 bytes, which means we have
1240         * enough room for a UDP header.  Just verify the UDP length field so we
1241         * can mess around with the payload.
1242         */
1243        if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
1244                 if (net_ratelimit())
1245                         printk(KERN_WARNING "SNMP: dropping malformed packet src=%pI4 dst=%pI4\n",
1246                                &iph->saddr, &iph->daddr);
1247                 return NF_DROP;
1248        }
1249
1250        if (!skb_make_writable(skb, skb->len))
1251                return NF_DROP;
1252
1253        spin_lock_bh(&snmp_lock);
1254        ret = snmp_translate(ct, ctinfo, skb);
1255        spin_unlock_bh(&snmp_lock);
1256        return ret;
1257}
1258
1259static const struct nf_conntrack_expect_policy snmp_exp_policy = {
1260        .max_expected   = 0,
1261        .timeout        = 180,
1262};
1263
1264static struct nf_conntrack_helper snmp_helper __read_mostly = {
1265        .me                     = THIS_MODULE,
1266        .help                   = help,
1267        .expect_policy          = &snmp_exp_policy,
1268        .name                   = "snmp",
1269        .tuple.src.l3num        = AF_INET,
1270        .tuple.src.u.udp.port   = cpu_to_be16(SNMP_PORT),
1271        .tuple.dst.protonum     = IPPROTO_UDP,
1272};
1273
1274static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
1275        .me                     = THIS_MODULE,
1276        .help                   = help,
1277        .expect_policy          = &snmp_exp_policy,
1278        .name                   = "snmp_trap",
1279        .tuple.src.l3num        = AF_INET,
1280        .tuple.src.u.udp.port   = cpu_to_be16(SNMP_TRAP_PORT),
1281        .tuple.dst.protonum     = IPPROTO_UDP,
1282};
1283
1284/*****************************************************************************
1285 *
1286 * Module stuff.
1287 *
1288 *****************************************************************************/
1289
1290static int __init nf_nat_snmp_basic_init(void)
1291{
1292        int ret = 0;
1293
1294        BUG_ON(nf_nat_snmp_hook != NULL);
1295        RCU_INIT_POINTER(nf_nat_snmp_hook, help);
1296
1297        ret = nf_conntrack_helper_register(&snmp_trap_helper);
1298        if (ret < 0) {
1299                nf_conntrack_helper_unregister(&snmp_helper);
1300                return ret;
1301        }
1302        return ret;
1303}
1304
1305static void __exit nf_nat_snmp_basic_fini(void)
1306{
1307        RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
1308        nf_conntrack_helper_unregister(&snmp_trap_helper);
1309}
1310
1311module_init(nf_nat_snmp_basic_init);
1312module_exit(nf_nat_snmp_basic_fini);
1313
1314module_param(debug, int, 0600);
1315
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.