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