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