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/in.h>
47#include <linux/ip.h>
48#include <linux/udp.h>
49#include <net/checksum.h>
50#include <net/udp.h>
51
52#include <net/netfilter/nf_nat.h>
53#include <net/netfilter/nf_conntrack_helper.h>
54#include <net/netfilter/nf_nat_helper.h>
55
56MODULE_LICENSE("GPL");
57MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
58MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
59MODULE_ALIAS("ip_nat_snmp_basic");
60
61#define SNMP_PORT 161
62#define SNMP_TRAP_PORT 162
63#define NOCT1(n) (*(u8 *)n)
64
65static int debug;
66static DEFINE_SPINLOCK(snmp_lock);
67
68/*
69 * Application layer address mapping mimics the NAT mapping, but
70 * only for the first octet in this case (a more flexible system
71 * can be implemented if needed).
72 */
73struct oct1_map
74{
75	u_int8_t from;
76	u_int8_t to;
77};
78
79
80/*****************************************************************************
81 *
82 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
83 *
84 *****************************************************************************/
85
86/* Class */
87#define ASN1_UNI	0	/* Universal */
88#define ASN1_APL	1	/* Application */
89#define ASN1_CTX	2	/* Context */
90#define ASN1_PRV	3	/* Private */
91
92/* Tag */
93#define ASN1_EOC	0	/* End Of Contents */
94#define ASN1_BOL	1	/* Boolean */
95#define ASN1_INT	2	/* Integer */
96#define ASN1_BTS	3	/* Bit String */
97#define ASN1_OTS	4	/* Octet String */
98#define ASN1_NUL	5	/* Null */
99#define ASN1_OJI	6	/* Object Identifier  */
100#define ASN1_OJD	7	/* Object Description */
101#define ASN1_EXT	8	/* External */
102#define ASN1_SEQ	16	/* Sequence */
103#define ASN1_SET	17	/* Set */
104#define ASN1_NUMSTR	18	/* Numerical String */
105#define ASN1_PRNSTR	19	/* Printable String */
106#define ASN1_TEXSTR	20	/* Teletext String */
107#define ASN1_VIDSTR	21	/* Video String */
108#define ASN1_IA5STR	22	/* IA5 String */
109#define ASN1_UNITIM	23	/* Universal Time */
110#define ASN1_GENTIM	24	/* General Time */
111#define ASN1_GRASTR	25	/* Graphical String */
112#define ASN1_VISSTR	26	/* Visible String */
113#define ASN1_GENSTR	27	/* General String */
114
115/* Primitive / Constructed methods*/
116#define ASN1_PRI	0	/* Primitive */
117#define ASN1_CON	1	/* Constructed */
118
119/*
120 * Error codes.
121 */
122#define ASN1_ERR_NOERROR		0
123#define ASN1_ERR_DEC_EMPTY		2
124#define ASN1_ERR_DEC_EOC_MISMATCH	3
125#define ASN1_ERR_DEC_LENGTH_MISMATCH	4
126#define ASN1_ERR_DEC_BADVALUE		5
127
128/*
129 * ASN.1 context.
130 */
131struct asn1_ctx
132{
133	int error;			/* Error condition */
134	unsigned char *pointer;		/* Octet just to be decoded */
135	unsigned char *begin;		/* First octet */
136	unsigned char *end;		/* Octet after last octet */
137};
138
139/*
140 * Octet string (not null terminated)
141 */
142struct asn1_octstr
143{
144	unsigned char *data;
145	unsigned int len;
146};
147
148static void asn1_open(struct asn1_ctx *ctx,
149		      unsigned char *buf,
150		      unsigned int len)
151{
152	ctx->begin = buf;
153	ctx->end = buf + len;
154	ctx->pointer = buf;
155	ctx->error = ASN1_ERR_NOERROR;
156}
157
158static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
159{
160	if (ctx->pointer >= ctx->end) {
161		ctx->error = ASN1_ERR_DEC_EMPTY;
162		return 0;
163	}
164	*ch = *(ctx->pointer)++;
165	return 1;
166}
167
168static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
169{
170	unsigned char ch;
171
172	*tag = 0;
173
174	do
175	{
176		if (!asn1_octet_decode(ctx, &ch))
177			return 0;
178		*tag <<= 7;
179		*tag |= ch & 0x7F;
180	} while ((ch & 0x80) == 0x80);
181	return 1;
182}
183
184static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
185				    unsigned int *cls,
186				    unsigned int *con,
187				    unsigned int *tag)
188{
189	unsigned char ch;
190
191	if (!asn1_octet_decode(ctx, &ch))
192		return 0;
193
194	*cls = (ch & 0xC0) >> 6;
195	*con = (ch & 0x20) >> 5;
196	*tag = (ch & 0x1F);
197
198	if (*tag == 0x1F) {
199		if (!asn1_tag_decode(ctx, tag))
200			return 0;
201	}
202	return 1;
203}
204
205static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
206					unsigned int *def,
207					unsigned int *len)
208{
209	unsigned char ch, cnt;
210
211	if (!asn1_octet_decode(ctx, &ch))
212		return 0;
213
214	if (ch == 0x80)
215		*def = 0;
216	else {
217		*def = 1;
218
219		if (ch < 0x80)
220			*len = ch;
221		else {
222			cnt = (unsigned char) (ch & 0x7F);
223			*len = 0;
224
225			while (cnt > 0) {
226				if (!asn1_octet_decode(ctx, &ch))
227					return 0;
228				*len <<= 8;
229				*len |= ch;
230				cnt--;
231			}
232		}
233	}
234	return 1;
235}
236
237static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
238					unsigned char **eoc,
239					unsigned int *cls,
240					unsigned int *con,
241					unsigned int *tag)
242{
243	unsigned int def, len;
244
245	if (!asn1_id_decode(ctx, cls, con, tag))
246		return 0;
247
248	def = len = 0;
249	if (!asn1_length_decode(ctx, &def, &len))
250		return 0;
251
252	if (def)
253		*eoc = ctx->pointer + len;
254	else
255		*eoc = NULL;
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 inline void mangle_address(unsigned char *begin,
610				  unsigned char *addr,
611				  const struct oct1_map *map,
612				  __sum16 *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	type = 0;
699	if (!snmp_tag_cls2syntax(tag, cls, &type)) {
700		kfree(id);
701		return 0;
702	}
703
704	l = 0;
705	switch (type) {
706		case SNMP_INTEGER:
707			len = sizeof(long);
708			if (!asn1_long_decode(ctx, end, &l)) {
709				kfree(id);
710				return 0;
711			}
712			*obj = kmalloc(sizeof(struct snmp_object) + len,
713				       GFP_ATOMIC);
714			if (*obj == NULL) {
715				kfree(id);
716				if (net_ratelimit())
717					printk("OOM in bsalg (%d)\n", __LINE__);
718				return 0;
719			}
720			(*obj)->syntax.l[0] = l;
721			break;
722		case SNMP_OCTETSTR:
723		case SNMP_OPAQUE:
724			if (!asn1_octets_decode(ctx, end, &p, &len)) {
725				kfree(id);
726				return 0;
727			}
728			*obj = kmalloc(sizeof(struct snmp_object) + len,
729				       GFP_ATOMIC);
730			if (*obj == NULL) {
731				kfree(id);
732				if (net_ratelimit())
733					printk("OOM in bsalg (%d)\n", __LINE__);
734				return 0;
735			}
736			memcpy((*obj)->syntax.c, p, len);
737			kfree(p);
738			break;
739		case SNMP_NULL:
740		case SNMP_NOSUCHOBJECT:
741		case SNMP_NOSUCHINSTANCE:
742		case SNMP_ENDOFMIBVIEW:
743			len = 0;
744			*obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
745			if (*obj == NULL) {
746				kfree(id);
747				if (net_ratelimit())
748					printk("OOM in bsalg (%d)\n", __LINE__);
749				return 0;
750			}
751			if (!asn1_null_decode(ctx, end)) {
752				kfree(id);
753				kfree(*obj);
754				*obj = NULL;
755				return 0;
756			}
757			break;
758		case SNMP_OBJECTID:
759			if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
760				kfree(id);
761				return 0;
762			}
763			len *= sizeof(unsigned long);
764			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
765			if (*obj == NULL) {
766				kfree(lp);
767				kfree(id);
768				if (net_ratelimit())
769					printk("OOM in bsalg (%d)\n", __LINE__);
770				return 0;
771			}
772			memcpy((*obj)->syntax.ul, lp, len);
773			kfree(lp);
774			break;
775		case SNMP_IPADDR:
776			if (!asn1_octets_decode(ctx, end, &p, &len)) {
777				kfree(id);
778				return 0;
779			}
780			if (len != 4) {
781				kfree(p);
782				kfree(id);
783				return 0;
784			}
785			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
786			if (*obj == NULL) {
787				kfree(p);
788				kfree(id);
789				if (net_ratelimit())
790					printk("OOM in bsalg (%d)\n", __LINE__);
791				return 0;
792			}
793			memcpy((*obj)->syntax.uc, p, len);
794			kfree(p);
795			break;
796		case SNMP_COUNTER:
797		case SNMP_GAUGE:
798		case SNMP_TIMETICKS:
799			len = sizeof(unsigned long);
800			if (!asn1_ulong_decode(ctx, end, &ul)) {
801				kfree(id);
802				return 0;
803			}
804			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
805			if (*obj == NULL) {
806				kfree(id);
807				if (net_ratelimit())
808					printk("OOM in bsalg (%d)\n", __LINE__);
809				return 0;
810			}
811			(*obj)->syntax.ul[0] = ul;
812			break;
813		default:
814			kfree(id);
815			return 0;
816	}
817
818	(*obj)->syntax_len = len;
819	(*obj)->type = type;
820	(*obj)->id = id;
821	(*obj)->id_len = idlen;
822
823	if (!asn1_eoc_decode(ctx, eoc)) {
824		kfree(id);
825		kfree(*obj);
826		*obj = NULL;
827		return 0;
828	}
829	return 1;
830}
831
832static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
833					 struct snmp_request *request)
834{
835	unsigned int cls, con, tag;
836	unsigned char *end;
837
838	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
839		return 0;
840
841	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
842		return 0;
843
844	if (!asn1_ulong_decode(ctx, end, &request->id))
845		return 0;
846
847	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
848		return 0;
849
850	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
851		return 0;
852
853	if (!asn1_uint_decode(ctx, end, &request->error_status))
854		return 0;
855
856	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
857		return 0;
858
859	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
860		return 0;
861
862	if (!asn1_uint_decode(ctx, end, &request->error_index))
863		return 0;
864
865	return 1;
866}
867
868/*
869 * Fast checksum update for possibly oddly-aligned UDP byte, from the
870 * code example in the draft.
871 */
872static void fast_csum(__sum16 *csum,
873		      const unsigned char *optr,
874		      const unsigned char *nptr,
875		      int offset)
876{
877	unsigned char s[4];
878
879	if (offset & 1) {
880		s[0] = s[2] = 0;
881		s[1] = ~*optr;
882		s[3] = *nptr;
883	} else {
884		s[1] = s[3] = 0;
885		s[0] = ~*optr;
886		s[2] = *nptr;
887	}
888
889	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
890}
891
892/*
893 * Mangle IP address.
894 * 	- begin points to the start of the snmp messgae
895 *      - addr points to the start of the address
896 */
897static inline void mangle_address(unsigned char *begin,
898				  unsigned char *addr,
899				  const struct oct1_map *map,
900				  __sum16 *check)
901{
902	if (map->from == NOCT1(addr)) {
903		u_int32_t old;
904
905		if (debug)
906			memcpy(&old, (unsigned char *)addr, sizeof(old));
907
908		*addr = map->to;
909
910		/* Update UDP checksum if being used */
911		if (*check) {
912			fast_csum(check,
913				  &map->from, &map->to, addr - begin);
914
915		}
916
917		if (debug)
918			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
919			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
920	}
921}
922
923static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
924				      struct snmp_v1_trap *trap,
925				      const struct oct1_map *map,
926				      __sum16 *check)
927{
928	unsigned int cls, con, tag, len;
929	unsigned char *end;
930
931	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
932		return 0;
933
934	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
935		return 0;
936
937	if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
938		return 0;
939
940	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
941		goto err_id_free;
942
943	if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
944	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
945		goto err_id_free;
946
947	if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
948		goto err_id_free;
949
950	/* IPv4 only */
951	if (len != 4)
952		goto err_addr_free;
953
954	mangle_address(ctx->begin, ctx->pointer - 4, map, check);
955
956	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
957		goto err_addr_free;
958
959	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
960		goto err_addr_free;
961
962	if (!asn1_uint_decode(ctx, end, &trap->general))
963		goto err_addr_free;
964
965	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
966		goto err_addr_free;
967
968	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
969		goto err_addr_free;
970
971	if (!asn1_uint_decode(ctx, end, &trap->specific))
972		goto err_addr_free;
973
974	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
975		goto err_addr_free;
976
977	if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
978	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
979		goto err_addr_free;
980
981	if (!asn1_ulong_decode(ctx, end, &trap->time))
982		goto err_addr_free;
983
984	return 1;
985
986err_addr_free:
987	kfree((unsigned long *)trap->ip_address);
988
989err_id_free:
990	kfree(trap->id);
991
992	return 0;
993}
994
995/*****************************************************************************
996 *
997 * Misc. routines
998 *
999 *****************************************************************************/
1000
1001static void hex_dump(unsigned char *buf, size_t len)
1002{
1003	size_t i;
1004
1005	for (i = 0; i < len; i++) {
1006		if (i && !(i % 16))
1007			printk("\n");
1008		printk("%02x ", *(buf + i));
1009	}
1010	printk("\n");
1011}
1012
1013/*
1014 * Parse and mangle SNMP message according to mapping.
1015 * (And this is the fucking 'basic' method).
1016 */
1017static int snmp_parse_mangle(unsigned char *msg,
1018			     u_int16_t len,
1019			     const struct oct1_map *map,
1020			     __sum16 *check)
1021{
1022	unsigned char *eoc, *end;
1023	unsigned int cls, con, tag, vers, pdutype;
1024	struct asn1_ctx ctx;
1025	struct asn1_octstr comm;
1026	struct snmp_object **obj;
1027
1028	if (debug > 1)
1029		hex_dump(msg, len);
1030
1031	asn1_open(&ctx, msg, len);
1032
1033	/*
1034	 * Start of SNMP message.
1035	 */
1036	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1037		return 0;
1038	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1039		return 0;
1040
1041	/*
1042	 * Version 1 or 2 handled.
1043	 */
1044	if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
1045		return 0;
1046	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
1047		return 0;
1048	if (!asn1_uint_decode (&ctx, end, &vers))
1049		return 0;
1050	if (debug > 1)
1051		printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
1052	if (vers > 1)
1053		return 1;
1054
1055	/*
1056	 * Community.
1057	 */
1058	if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
1059		return 0;
1060	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1061		return 0;
1062	if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
1063		return 0;
1064	if (debug > 1) {
1065		unsigned int i;
1066
1067		printk(KERN_DEBUG "bsalg: community: ");
1068		for (i = 0; i < comm.len; i++)
1069			printk("%c", comm.data[i]);
1070		printk("\n");
1071	}
1072	kfree(comm.data);
1073
1074	/*
1075	 * PDU type
1076	 */
1077	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
1078		return 0;
1079	if (cls != ASN1_CTX || con != ASN1_CON)
1080		return 0;
1081	if (debug > 1) {
1082		unsigned char *pdus[] = {
1083			[SNMP_PDU_GET] = "get",
1084			[SNMP_PDU_NEXT] = "get-next",
1085			[SNMP_PDU_RESPONSE] = "response",
1086			[SNMP_PDU_SET] = "set",
1087			[SNMP_PDU_TRAP1] = "trapv1",
1088			[SNMP_PDU_BULK] = "bulk",
1089			[SNMP_PDU_INFORM] = "inform",
1090			[SNMP_PDU_TRAP2] = "trapv2"
1091		};
1092
1093		if (pdutype > SNMP_PDU_TRAP2)
1094			printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
1095		else
1096			printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);
1097	}
1098	if (pdutype != SNMP_PDU_RESPONSE &&
1099	    pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
1100		return 1;
1101
1102	/*
1103	 * Request header or v1 trap
1104	 */
1105	if (pdutype == SNMP_PDU_TRAP1) {
1106		struct snmp_v1_trap trap;
1107		unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
1108
1109		if (ret) {
1110			kfree(trap.id);
1111			kfree((unsigned long *)trap.ip_address);
1112		} else
1113			return ret;
1114
1115	} else {
1116		struct snmp_request req;
1117
1118		if (!snmp_request_decode(&ctx, &req))
1119			return 0;
1120
1121		if (debug > 1)
1122			printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
1123			"error_index=%u\n", req.id, req.error_status,
1124			req.error_index);
1125	}
1126
1127	/*
1128	 * Loop through objects, look for IP addresses to mangle.
1129	 */
1130	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1131		return 0;
1132
1133	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1134		return 0;
1135
1136	obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
1137	if (obj == NULL) {
1138		if (net_ratelimit())
1139			printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
1140		return 0;
1141	}
1142
1143	while (!asn1_eoc_decode(&ctx, eoc)) {
1144		unsigned int i;
1145
1146		if (!snmp_object_decode(&ctx, obj)) {
1147			if (*obj) {
1148				kfree((*obj)->id);
1149				kfree(*obj);
1150			}
1151			kfree(obj);
1152			return 0;
1153		}
1154
1155		if (debug > 1) {
1156			printk(KERN_DEBUG "bsalg: object: ");
1157			for (i = 0; i < (*obj)->id_len; i++) {
1158				if (i > 0)
1159					printk(".");
1160				printk("%lu", (*obj)->id[i]);
1161			}
1162			printk(": type=%u\n", (*obj)->type);
1163
1164		}
1165
1166		if ((*obj)->type == SNMP_IPADDR)
1167			mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
1168
1169		kfree((*obj)->id);
1170		kfree(*obj);
1171	}
1172	kfree(obj);
1173
1174	if (!asn1_eoc_decode(&ctx, eoc))
1175		return 0;
1176
1177	return 1;
1178}
1179
1180/*****************************************************************************
1181 *
1182 * NAT routines.
1183 *
1184 *****************************************************************************/
1185
1186/*
1187 * SNMP translation routine.
1188 */
1189static int snmp_translate(struct nf_conn *ct,
1190			  enum ip_conntrack_info ctinfo,
1191			  struct sk_buff **pskb)
1192{
1193	struct iphdr *iph = ip_hdr(*pskb);
1194	struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1195	u_int16_t udplen = ntohs(udph->len);
1196	u_int16_t paylen = udplen - sizeof(struct udphdr);
1197	int dir = CTINFO2DIR(ctinfo);
1198	struct oct1_map map;
1199
1200	/*
1201	 * Determine mappping for application layer addresses based
1202	 * on NAT manipulations for the packet.
1203	 */
1204	if (dir == IP_CT_DIR_ORIGINAL) {
1205		/* SNAT traps */
1206		map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
1207		map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
1208	} else {
1209		/* DNAT replies */
1210		map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
1211		map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
1212	}
1213
1214	if (map.from == map.to)
1215		return NF_ACCEPT;
1216
1217	if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
1218			       paylen, &map, &udph->check)) {
1219		if (net_ratelimit())
1220			printk(KERN_WARNING "bsalg: parser failed\n");
1221		return NF_DROP;
1222	}
1223	return NF_ACCEPT;
1224}
1225
1226/* We don't actually set up expectations, just adjust internal IP
1227 * addresses if this is being NATted */
1228static int help(struct sk_buff **pskb, unsigned int protoff,
1229		struct nf_conn *ct,
1230		enum ip_conntrack_info ctinfo)
1231{
1232	int dir = CTINFO2DIR(ctinfo);
1233	unsigned int ret;
1234	struct iphdr *iph = ip_hdr(*pskb);
1235	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
1236
1237	/* SNMP replies and originating SNMP traps get mangled */
1238	if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
1239		return NF_ACCEPT;
1240	if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
1241		return NF_ACCEPT;
1242
1243	/* No NAT? */
1244	if (!(ct->status & IPS_NAT_MASK))
1245		return NF_ACCEPT;
1246
1247	/*
1248	 * Make sure the packet length is ok.  So far, we were only guaranteed
1249	 * to have a valid length IP header plus 8 bytes, which means we have
1250	 * enough room for a UDP header.  Just verify the UDP length field so we
1251	 * can mess around with the payload.
1252	 */
1253	if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
1254		 if (net_ratelimit())
1255			 printk(KERN_WARNING "SNMP: dropping malformed packet "
1256				"src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
1257				NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1258		 return NF_DROP;
1259	}
1260
1261	if (!skb_make_writable(pskb, (*pskb)->len))
1262		return NF_DROP;
1263
1264	spin_lock_bh(&snmp_lock);
1265	ret = snmp_translate(ct, ctinfo, pskb);
1266	spin_unlock_bh(&snmp_lock);
1267	return ret;
1268}
1269
1270static struct nf_conntrack_helper snmp_helper __read_mostly = {
1271	.max_expected		= 0,
1272	.timeout		= 180,
1273	.me			= THIS_MODULE,
1274	.help			= help,
1275	.name			= "snmp",
1276	.tuple.src.l3num	= AF_INET,
1277	.tuple.src.u.udp.port	= __constant_htons(SNMP_PORT),
1278	.tuple.dst.protonum	= IPPROTO_UDP,
1279	.mask.src.l3num		= 0xFFFF,
1280	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
1281	.mask.dst.protonum	= 0xFF,
1282};
1283
1284static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
1285	.max_expected		= 0,
1286	.timeout		= 180,
1287	.me			= THIS_MODULE,
1288	.help			= help,
1289	.name			= "snmp_trap",
1290	.tuple.src.l3num	= AF_INET,
1291	.tuple.src.u.udp.port	= __constant_htons(SNMP_TRAP_PORT),
1292	.tuple.dst.protonum	= IPPROTO_UDP,
1293	.mask.src.l3num		= 0xFFFF,
1294	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
1295	.mask.dst.protonum	= 0xFF,
1296};
1297
1298/*****************************************************************************
1299 *
1300 * Module stuff.
1301 *
1302 *****************************************************************************/
1303
1304static int __init nf_nat_snmp_basic_init(void)
1305{
1306	int ret = 0;
1307
1308	ret = nf_conntrack_helper_register(&snmp_helper);
1309	if (ret < 0)
1310		return ret;
1311	ret = nf_conntrack_helper_register(&snmp_trap_helper);
1312	if (ret < 0) {
1313		nf_conntrack_helper_unregister(&snmp_helper);
1314		return ret;
1315	}
1316	return ret;
1317}
1318
1319static void __exit nf_nat_snmp_basic_fini(void)
1320{
1321	nf_conntrack_helper_unregister(&snmp_helper);
1322	nf_conntrack_helper_unregister(&snmp_trap_helper);
1323}
1324
1325module_init(nf_nat_snmp_basic_init);
1326module_exit(nf_nat_snmp_basic_fini);
1327
1328module_param(debug, int, 0600);
1329