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

📄 ip_nat_snmp_basic.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		x =~ x & 0xFFFF;	csum[0] = x / 256;	csum[1] = x & 0xFF;}/*  * Mangle IP address. * 	- begin points to the start of the snmp messgae *      - addr points to the start of the address */static inline void mangle_address(unsigned char *begin,                                  unsigned char *addr,                                  const struct oct1_map *map,                                  u_int16_t *check){	if (map->from == NOCT1(*addr)) {		u_int32_t old;				if (debug)			memcpy(&old, (unsigned char *)addr, sizeof(old));					*addr = map->to;				/* Update UDP checksum if being used */		if (*check) {			unsigned char odd = !((addr - begin) % 2);						fast_csum((unsigned char *)check,			          &map->from, &map->to, odd);			          		}				if (debug)			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));	}}static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,                                      struct snmp_v1_trap *trap,                                      const struct oct1_map *map,                                      u_int16_t *check){	unsigned int cls, con, tag, len;	unsigned char *end;	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))		return 0;			if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)		return 0;		if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))		return 0;			if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))		goto err_id_free;	if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))		goto err_id_free;		if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))		goto err_id_free;		/* IPv4 only */	if (len != 4)		goto err_addr_free;		mangle_address(ctx->begin, ctx->pointer - 4, map, check);		if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))		goto err_addr_free;			if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)		goto err_addr_free;			if (!asn1_uint_decode(ctx, end, &trap->general))		goto err_addr_free;			if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))		goto err_addr_free;		if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)		goto err_addr_free;			if (!asn1_uint_decode(ctx, end, &trap->specific))		goto err_addr_free;			if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))		goto err_addr_free;			if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))		goto err_addr_free;			if (!asn1_ulong_decode(ctx, end, &trap->time))		goto err_addr_free;			return 1;err_id_free:	kfree(trap->id);err_addr_free:	kfree((unsigned long *)trap->ip_address);		return 0;}/***************************************************************************** * * Misc. routines * *****************************************************************************/static void hex_dump(unsigned char *buf, size_t len){	size_t i;		for (i = 0; i < len; i++) {		if (i && !(i % 16))			printk("\n");		printk("%02x ", *(buf + i));	}	printk("\n");}/* * Parse and mangle SNMP message according to mapping. * (And this is the fucking 'basic' method). */static int snmp_parse_mangle(unsigned char *msg,                             u_int16_t len,                             const struct oct1_map *map,                             u_int16_t *check){	unsigned char *eoc, *end;	unsigned int cls, con, tag, vers, pdutype;	struct asn1_ctx ctx;	struct asn1_octstr comm;	struct snmp_object **obj;		if (debug > 1)		hex_dump(msg, len);	asn1_open(&ctx, msg, len);		/* 	 * Start of SNMP message.	 */	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))		return 0;	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)		return 0;		/* 	 * Version 1 or 2 handled.	 */	if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))		return 0;	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)		return 0;	if (!asn1_uint_decode (&ctx, end, &vers))		return 0;	if (debug > 1)		printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);	if (vers > 1)		return 1;		/*	 * Community.	 */	if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))		return 0;	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)		return 0;	if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))		return 0;	if (debug > 1) {		unsigned int i;				printk(KERN_DEBUG "bsalg: community: ");		for (i = 0; i < comm.len; i++)			printk("%c", comm.data[i]);		printk("\n");	}	kfree(comm.data);		/*	 * PDU type	 */	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))		return 0;	if (cls != ASN1_CTX || con != ASN1_CON)		return 0;	if (debug > 1) {		unsigned char *pdus[] = {			[SNMP_PDU_GET] = "get",			[SNMP_PDU_NEXT] = "get-next",			[SNMP_PDU_RESPONSE] = "response",			[SNMP_PDU_SET] = "set",			[SNMP_PDU_TRAP1] = "trapv1",			[SNMP_PDU_BULK] = "bulk",			[SNMP_PDU_INFORM] = "inform",			[SNMP_PDU_TRAP2] = "trapv2"		};				if (pdutype > SNMP_PDU_TRAP2)			printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);		else			printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);	}	if (pdutype != SNMP_PDU_RESPONSE &&	    pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)		return 1;		/*	 * Request header or v1 trap	 */	if (pdutype == SNMP_PDU_TRAP1) {		struct snmp_v1_trap trap;		unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);				/* Discard trap allocations regardless */		kfree(trap.id);		kfree((unsigned long *)trap.ip_address);				if (!ret)			return ret;			} else {		struct snmp_request req;				if (!snmp_request_decode(&ctx, &req))			return 0;					if (debug > 1)			printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "			"error_index=%u\n", req.id, req.error_status,			req.error_index);	}		/*	 * Loop through objects, look for IP addresses to mangle.	 */	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))		return 0;			if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)		return 0;		obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);	if (obj == NULL) {		if (net_ratelimit())			printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);		return 0;		}	while (!asn1_eoc_decode(&ctx, eoc)) {		unsigned int i;				if (!snmp_object_decode(&ctx, obj)) {			if (*obj) {				kfree((*obj)->id);				kfree(*obj);			}				kfree(obj);			return 0;		}		if (debug > 1) {			printk(KERN_DEBUG "bsalg: object: ");			for (i = 0; i < (*obj)->id_len; i++) {				if (i > 0)					printk(".");				printk("%lu", (*obj)->id[i]);			}			printk(": type=%u\n", (*obj)->type);					}		if ((*obj)->type == SNMP_IPADDR)			mangle_address(ctx.begin, ctx.pointer - 4 , map, check);				kfree((*obj)->id);		kfree(*obj);	}	kfree(obj);		if (!asn1_eoc_decode(&ctx, eoc))		return 0;			return 1;}/***************************************************************************** * * NAT routines. * *****************************************************************************//*  * SNMP translation routine. */static int snmp_translate(struct ip_conntrack *ct,                          enum ip_conntrack_info ctinfo,                          struct sk_buff **pskb){	struct iphdr *iph = (*pskb)->nh.iph;	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);	u_int16_t udplen = ntohs(udph->len);	u_int16_t paylen = udplen - sizeof(struct udphdr);	int dir = CTINFO2DIR(ctinfo);	struct oct1_map map;	/*	 * Determine mappping for application layer addresses based	 * on NAT manipulations for the packet.	 */	if (dir == IP_CT_DIR_ORIGINAL) {		/* SNAT traps */		map.from = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);		map.to = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);	} else {		/* DNAT replies */		map.from = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);		map.to = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);	}		if (map.from == map.to)		return NF_ACCEPT;		if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),	                       paylen, &map, &udph->check)) {		if (net_ratelimit())			printk(KERN_WARNING "bsalg: parser failed\n");		return NF_DROP;	}	return NF_ACCEPT;}/* We don't actually set up expectations, just adjust internal IP * addresses if this is being NATted */static int help(struct sk_buff **pskb,		struct ip_conntrack *ct,		enum ip_conntrack_info ctinfo){	int dir = CTINFO2DIR(ctinfo);	unsigned int ret;	struct iphdr *iph = (*pskb)->nh.iph;	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);	/* SNMP replies and originating SNMP traps get mangled */	if (udph->source == ntohs(SNMP_PORT) && dir != IP_CT_DIR_REPLY)		return NF_ACCEPT;	if (udph->dest == ntohs(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)		return NF_ACCEPT;	/* No NAT? */	if (!(ct->status & IPS_NAT_MASK))		return NF_ACCEPT;	/* 	 * Make sure the packet length is ok.  So far, we were only guaranteed	 * to have a valid length IP header plus 8 bytes, which means we have	 * enough room for a UDP header.  Just verify the UDP length field so we	 * can mess around with the payload.	 */	if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {		 if (net_ratelimit())			 printk(KERN_WARNING "SNMP: dropping malformed packet "				"src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",				NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));		 return NF_DROP;	}	if (!skb_make_writable(pskb, (*pskb)->len))		return NF_DROP;	spin_lock_bh(&snmp_lock);	ret = snmp_translate(ct, ctinfo, pskb);	spin_unlock_bh(&snmp_lock);	return ret;}static struct ip_conntrack_helper snmp_helper = {	.max_expected = 0,	.timeout = 180,	.me = THIS_MODULE,	.help = help,	.name = "snmp",	.tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } },		   .dst = { .protonum = IPPROTO_UDP },	},	.mask = { .src = { .u = { 0xFFFF } },		 .dst = { .protonum = 0xFF },	},};static struct ip_conntrack_helper snmp_trap_helper = {	.max_expected = 0,	.timeout = 180,	.me = THIS_MODULE,	.help = help,	.name = "snmp_trap",	.tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } },		   .dst = { .protonum = IPPROTO_UDP },	},	.mask = { .src = { .u = { 0xFFFF } },		 .dst = { .protonum = 0xFF },	},};/***************************************************************************** * * Module stuff. * *****************************************************************************/ static int __init init(void){	int ret = 0;	ret = ip_conntrack_helper_register(&snmp_helper);	if (ret < 0)		return ret;	ret = ip_conntrack_helper_register(&snmp_trap_helper);	if (ret < 0) {		ip_conntrack_helper_unregister(&snmp_helper);		return ret;	}	return ret;}static void __exit fini(void){	ip_conntrack_helper_unregister(&snmp_helper);	ip_conntrack_helper_unregister(&snmp_trap_helper);}module_init(init);module_exit(fini);module_param(debug, bool, 0600);

⌨️ 快捷键说明

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