⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nf_nat_snmp_basic.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * nf_nat_snmp_basic.c * * Basic SNMP Application Layer Gateway * * This IP NAT module is intended for use with SNMP network * discovery and monitoring applications where target networks use * conflicting private address realms. * * Static NAT is used to remap the networks from the view of the network * management system at the IP layer, and this module remaps some application * layer addresses to match. * * The simplest form of ALG is performed, where only tagged IP addresses * are modified.  The module does not need to be MIB aware and only scans * messages at the ASN.1/BER level. * * Currently, only SNMPv1 and SNMPv2 are supported. * * More information on ALG and associated issues can be found in * RFC 2962 * * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory * McLean & Jochen Friedrich, stripped down for use in the kernel. * * Copyright (c) 2000 RP Internet (www.rpi.net.au). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * * Author: James Morris <jmorris@intercode.com.au> */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/udp.h>#include <net/checksum.h>#include <net/udp.h>#include <net/netfilter/nf_nat.h>#include <net/netfilter/nf_conntrack_helper.h>#include <net/netfilter/nf_nat_helper.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");MODULE_ALIAS("ip_nat_snmp_basic");#define SNMP_PORT 161#define SNMP_TRAP_PORT 162#define NOCT1(n) (*(u8 *)n)static int debug;static DEFINE_SPINLOCK(snmp_lock);/* * Application layer address mapping mimics the NAT mapping, but * only for the first octet in this case (a more flexible system * can be implemented if needed). */struct oct1_map{	u_int8_t from;	u_int8_t to;};/***************************************************************************** * * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) * *****************************************************************************//* Class */#define ASN1_UNI	0	/* Universal */#define ASN1_APL	1	/* Application */#define ASN1_CTX	2	/* Context */#define ASN1_PRV	3	/* Private *//* Tag */#define ASN1_EOC	0	/* End Of Contents */#define ASN1_BOL	1	/* Boolean */#define ASN1_INT	2	/* Integer */#define ASN1_BTS	3	/* Bit String */#define ASN1_OTS	4	/* Octet String */#define ASN1_NUL	5	/* Null */#define ASN1_OJI	6	/* Object Identifier  */#define ASN1_OJD	7	/* Object Description */#define ASN1_EXT	8	/* External */#define ASN1_SEQ	16	/* Sequence */#define ASN1_SET	17	/* Set */#define ASN1_NUMSTR	18	/* Numerical String */#define ASN1_PRNSTR	19	/* Printable String */#define ASN1_TEXSTR	20	/* Teletext String */#define ASN1_VIDSTR	21	/* Video String */#define ASN1_IA5STR	22	/* IA5 String */#define ASN1_UNITIM	23	/* Universal Time */#define ASN1_GENTIM	24	/* General Time */#define ASN1_GRASTR	25	/* Graphical String */#define ASN1_VISSTR	26	/* Visible String */#define ASN1_GENSTR	27	/* General String *//* Primitive / Constructed methods*/#define ASN1_PRI	0	/* Primitive */#define ASN1_CON	1	/* Constructed *//* * Error codes. */#define ASN1_ERR_NOERROR		0#define ASN1_ERR_DEC_EMPTY		2#define ASN1_ERR_DEC_EOC_MISMATCH	3#define ASN1_ERR_DEC_LENGTH_MISMATCH	4#define ASN1_ERR_DEC_BADVALUE		5/* * ASN.1 context. */struct asn1_ctx{	int error;			/* Error condition */	unsigned char *pointer;		/* Octet just to be decoded */	unsigned char *begin;		/* First octet */	unsigned char *end;		/* Octet after last octet */};/* * Octet string (not null terminated) */struct asn1_octstr{	unsigned char *data;	unsigned int len;};static void asn1_open(struct asn1_ctx *ctx,		      unsigned char *buf,		      unsigned int len){	ctx->begin = buf;	ctx->end = buf + len;	ctx->pointer = buf;	ctx->error = ASN1_ERR_NOERROR;}static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch){	if (ctx->pointer >= ctx->end) {		ctx->error = ASN1_ERR_DEC_EMPTY;		return 0;	}	*ch = *(ctx->pointer)++;	return 1;}static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag){	unsigned char ch;	*tag = 0;	do	{		if (!asn1_octet_decode(ctx, &ch))			return 0;		*tag <<= 7;		*tag |= ch & 0x7F;	} while ((ch & 0x80) == 0x80);	return 1;}static unsigned char asn1_id_decode(struct asn1_ctx *ctx,				    unsigned int *cls,				    unsigned int *con,				    unsigned int *tag){	unsigned char ch;	if (!asn1_octet_decode(ctx, &ch))		return 0;	*cls = (ch & 0xC0) >> 6;	*con = (ch & 0x20) >> 5;	*tag = (ch & 0x1F);	if (*tag == 0x1F) {		if (!asn1_tag_decode(ctx, tag))			return 0;	}	return 1;}static unsigned char asn1_length_decode(struct asn1_ctx *ctx,					unsigned int *def,					unsigned int *len){	unsigned char ch, cnt;	if (!asn1_octet_decode(ctx, &ch))		return 0;	if (ch == 0x80)		*def = 0;	else {		*def = 1;		if (ch < 0x80)			*len = ch;		else {			cnt = (unsigned char) (ch & 0x7F);			*len = 0;			while (cnt > 0) {				if (!asn1_octet_decode(ctx, &ch))					return 0;				*len <<= 8;				*len |= ch;				cnt--;			}		}	}	return 1;}static unsigned char asn1_header_decode(struct asn1_ctx *ctx,					unsigned char **eoc,					unsigned int *cls,					unsigned int *con,					unsigned int *tag){	unsigned int def, len;	if (!asn1_id_decode(ctx, cls, con, tag))		return 0;	def = len = 0;	if (!asn1_length_decode(ctx, &def, &len))		return 0;	if (def)		*eoc = ctx->pointer + len;	else		*eoc = NULL;	return 1;}static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc){	unsigned char ch;	if (eoc == 0) {		if (!asn1_octet_decode(ctx, &ch))			return 0;		if (ch != 0x00) {			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;			return 0;		}		if (!asn1_octet_decode(ctx, &ch))			return 0;		if (ch != 0x00) {			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;			return 0;		}		return 1;	} else {		if (ctx->pointer != eoc) {			ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;			return 0;		}		return 1;	}}static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc){	ctx->pointer = eoc;	return 1;}static unsigned char asn1_long_decode(struct asn1_ctx *ctx,				      unsigned char *eoc,				      long *integer){	unsigned char ch;	unsigned int  len;	if (!asn1_octet_decode(ctx, &ch))		return 0;	*integer = (signed char) ch;	len = 1;	while (ctx->pointer < eoc) {		if (++len > sizeof (long)) {			ctx->error = ASN1_ERR_DEC_BADVALUE;			return 0;		}		if (!asn1_octet_decode(ctx, &ch))			return 0;		*integer <<= 8;		*integer |= ch;	}	return 1;}static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,				      unsigned char *eoc,				      unsigned int *integer){	unsigned char ch;	unsigned int  len;	if (!asn1_octet_decode(ctx, &ch))		return 0;	*integer = ch;	if (ch == 0) len = 0;	else len = 1;	while (ctx->pointer < eoc) {		if (++len > sizeof (unsigned int)) {			ctx->error = ASN1_ERR_DEC_BADVALUE;			return 0;		}		if (!asn1_octet_decode(ctx, &ch))			return 0;		*integer <<= 8;		*integer |= ch;	}	return 1;}static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,				       unsigned char *eoc,				       unsigned long *integer){	unsigned char ch;	unsigned int  len;	if (!asn1_octet_decode(ctx, &ch))		return 0;	*integer = ch;	if (ch == 0) len = 0;	else len = 1;	while (ctx->pointer < eoc) {		if (++len > sizeof (unsigned long)) {			ctx->error = ASN1_ERR_DEC_BADVALUE;			return 0;		}		if (!asn1_octet_decode(ctx, &ch))			return 0;		*integer <<= 8;		*integer |= ch;	}	return 1;}static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,					unsigned char *eoc,					unsigned char **octets,					unsigned int *len){	unsigned char *ptr;	*len = 0;	*octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);	if (*octets == NULL) {		if (net_ratelimit())			printk("OOM in bsalg (%d)\n", __LINE__);		return 0;	}	ptr = *octets;	while (ctx->pointer < eoc) {		if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {			kfree(*octets);			*octets = NULL;			return 0;		}		(*len)++;	}	return 1;}static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,				       unsigned long *subid){	unsigned char ch;	*subid = 0;	do {		if (!asn1_octet_decode(ctx, &ch))			return 0;		*subid <<= 7;		*subid |= ch & 0x7F;	} while ((ch & 0x80) == 0x80);	return 1;}static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,				     unsigned char *eoc,				     unsigned long **oid,				     unsigned int *len){	unsigned long subid;	unsigned int  size;	unsigned long *optr;	size = eoc - ctx->pointer + 1;	*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);	if (*oid == NULL) {		if (net_ratelimit())			printk("OOM in bsalg (%d)\n", __LINE__);		return 0;	}	optr = *oid;	if (!asn1_subid_decode(ctx, &subid)) {		kfree(*oid);		*oid = NULL;		return 0;	}	if (subid < 40) {		optr [0] = 0;		optr [1] = subid;	} else if (subid < 80) {		optr [0] = 1;		optr [1] = subid - 40;	} else {		optr [0] = 2;		optr [1] = subid - 80;	}	*len = 2;	optr += 2;	while (ctx->pointer < eoc) {		if (++(*len) > size) {			ctx->error = ASN1_ERR_DEC_BADVALUE;			kfree(*oid);			*oid = NULL;			return 0;		}		if (!asn1_subid_decode(ctx, optr++)) {			kfree(*oid);			*oid = NULL;			return 0;		}	}	return 1;}/***************************************************************************** * * SNMP decoding routines (gxsnmp author Dirk Wisse) * *****************************************************************************//* SNMP Versions */#define SNMP_V1				0#define SNMP_V2C			1#define SNMP_V2				2#define SNMP_V3				3/* Default Sizes */#define SNMP_SIZE_COMM			256#define SNMP_SIZE_OBJECTID		128#define SNMP_SIZE_BUFCHR		256#define SNMP_SIZE_BUFINT		128#define SNMP_SIZE_SMALLOBJECTID		16/* Requests */#define SNMP_PDU_GET			0#define SNMP_PDU_NEXT			1#define SNMP_PDU_RESPONSE		2#define SNMP_PDU_SET			3#define SNMP_PDU_TRAP1			4#define SNMP_PDU_BULK			5#define SNMP_PDU_INFORM			6#define SNMP_PDU_TRAP2			7/* Errors */#define SNMP_NOERROR			0#define SNMP_TOOBIG			1#define SNMP_NOSUCHNAME			2#define SNMP_BADVALUE			3#define SNMP_READONLY			4#define SNMP_GENERROR			5#define SNMP_NOACCESS			6#define SNMP_WRONGTYPE			7#define SNMP_WRONGLENGTH		8#define SNMP_WRONGENCODING		9#define SNMP_WRONGVALUE			10#define SNMP_NOCREATION			11#define SNMP_INCONSISTENTVALUE		12#define SNMP_RESOURCEUNAVAILABLE	13#define SNMP_COMMITFAILED		14#define SNMP_UNDOFAILED			15#define SNMP_AUTHORIZATIONERROR		16#define SNMP_NOTWRITABLE		17#define SNMP_INCONSISTENTNAME		18/* General SNMP V1 Traps */#define SNMP_TRAP_COLDSTART		0#define SNMP_TRAP_WARMSTART		1#define SNMP_TRAP_LINKDOWN		2#define SNMP_TRAP_LINKUP		3#define SNMP_TRAP_AUTFAILURE		4#define SNMP_TRAP_EQPNEIGHBORLOSS	5#define SNMP_TRAP_ENTSPECIFIC		6/* SNMPv1 Types */#define SNMP_NULL                0#define SNMP_INTEGER             1    /* l  */#define SNMP_OCTETSTR            2    /* c  */#define SNMP_DISPLAYSTR          2    /* c  */#define SNMP_OBJECTID            3    /* ul */#define SNMP_IPADDR              4    /* uc */#define SNMP_COUNTER             5    /* ul */#define SNMP_GAUGE               6    /* ul */#define SNMP_TIMETICKS           7    /* ul */#define SNMP_OPAQUE              8    /* c  *//* Additional SNMPv2 Types */#define SNMP_UINTEGER            5    /* ul */#define SNMP_BITSTR              9    /* uc */#define SNMP_NSAP               10    /* uc */#define SNMP_COUNTER64          11    /* ul */#define SNMP_NOSUCHOBJECT       12#define SNMP_NOSUCHINSTANCE     13#define SNMP_ENDOFMIBVIEW       14union snmp_syntax{	unsigned char uc[0];	/* 8 bit unsigned */	char c[0];		/* 8 bit signed */	unsigned long ul[0];	/* 32 bit unsigned */	long l[0];		/* 32 bit signed */};struct snmp_object{	unsigned long *id;	unsigned int id_len;	unsigned short type;	unsigned int syntax_len;	union snmp_syntax syntax;};struct snmp_request{	unsigned long id;	unsigned int error_status;	unsigned int error_index;};struct snmp_v1_trap{	unsigned long *id;	unsigned int id_len;	unsigned long ip_address;	/* pointer  */	unsigned int general;	unsigned int specific;	unsigned long time;};/* SNMP types */#define SNMP_IPA    0#define SNMP_CNT    1#define SNMP_GGE    2#define SNMP_TIT    3#define SNMP_OPQ    4#define SNMP_C64    6/* SNMP errors */#define SERR_NSO    0#define SERR_NSI    1#define SERR_EOM    2static inline void mangle_address(unsigned char *begin,				  unsigned char *addr,				  const struct oct1_map *map,				  __sum16 *check);struct snmp_cnv{	unsigned int class;	unsigned int tag;	int syntax;};static struct snmp_cnv snmp_conv [] ={	{ASN1_UNI, ASN1_NUL, SNMP_NULL},	{ASN1_UNI, ASN1_INT, SNMP_INTEGER},	{ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},	{ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},	{ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},	{ASN1_APL, SNMP_IPA, SNMP_IPADDR},	{ASN1_APL, SNMP_CNT, SNMP_COUNTER},	/* Counter32 */	{ASN1_APL, SNMP_GGE, SNMP_GAUGE},	/* Gauge32 == Unsigned32  */	{ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},	{ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},	/* SNMPv2 data types and errors */	{ASN1_UNI, ASN1_BTS, SNMP_BITSTR},	{ASN1_APL, SNMP_C64, SNMP_COUNTER64},	{ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},	{ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},	{ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},	{0,       0,       -1}};static unsigned char snmp_tag_cls2syntax(unsigned int tag,					 unsigned int cls,					 unsigned short *syntax){	struct snmp_cnv *cnv;	cnv = snmp_conv;	while (cnv->syntax != -1) {		if (cnv->tag == tag && cnv->class == cls) {			*syntax = cnv->syntax;			return 1;		}		cnv++;	}	return 0;}static unsigned char snmp_object_decode(struct asn1_ctx *ctx,					struct snmp_object **obj){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -