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

📄 ip_nat_snmp_basic.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                                  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) {				if ((*obj)->id)					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,                          struct ip_nat_info *info,                          enum ip_conntrack_info ctinfo,                          unsigned int hooknum,                          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)) {		printk(KERN_WARNING "bsalg: parser failed\n");		return NF_DROP;	}	return NF_ACCEPT;}/*  * NAT helper function, packets arrive here from NAT code. */static unsigned int nat_help(struct ip_conntrack *ct,			     struct ip_conntrack_expect *exp,                             struct ip_nat_info *info,                             enum ip_conntrack_info ctinfo,                             unsigned int hooknum,                             struct sk_buff **pskb){	int dir = CTINFO2DIR(ctinfo);	struct iphdr *iph = (*pskb)->nh.iph;	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);	spin_lock_bh(&snmp_lock);		/*	 * Translate snmp replies on pre-routing (DNAT) and snmp traps	 * on post routing (SNAT).	 */	if (!((dir == IP_CT_DIR_REPLY && hooknum == NF_IP_PRE_ROUTING &&			udph->source == ntohs(SNMP_PORT)) ||	      (dir == IP_CT_DIR_ORIGINAL && hooknum == NF_IP_POST_ROUTING &&	      		udph->dest == ntohs(SNMP_TRAP_PORT)))) {		spin_unlock_bh(&snmp_lock);		return NF_ACCEPT;	}	if (debug > 1) {		printk(KERN_DEBUG "bsalg: dir=%s hook=%d manip=%s len=%d "		       "src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u "		       "osrc=%u.%u.%u.%u odst=%u.%u.%u.%u "		       "rsrc=%u.%u.%u.%u rdst=%u.%u.%u.%u "		       "\n", 		       dir == IP_CT_DIR_REPLY ? "reply" : "orig", hooknum, 		       HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? "snat" :		       "dnat", (*pskb)->len,		       NIPQUAD(iph->saddr), ntohs(udph->source),		       NIPQUAD(iph->daddr), ntohs(udph->dest),		       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),		       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),		       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),		       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip));	}		/* 	 * 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)) {	 	int ret = snmp_translate(ct, info, ctinfo, hooknum, pskb);	 	spin_unlock_bh(&snmp_lock);	 	return ret;	}		if (net_ratelimit())		printk(KERN_WARNING "bsalg: dropping malformed packet "		       "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",		       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));	spin_unlock_bh(&snmp_lock);	return NF_DROP;}static struct ip_nat_helper snmp = { 	{ NULL, NULL },	"snmp",	IP_NAT_HELPER_F_STANDALONE,	THIS_MODULE,	{ { 0, { .udp = { __constant_htons(SNMP_PORT) } } },	  { 0, { 0 }, IPPROTO_UDP } },	{ { 0, { .udp = { 0xFFFF } } },	  { 0, { 0 }, 0xFFFF } },	nat_help, NULL }; static struct ip_nat_helper snmp_trap = { 	{ NULL, NULL },	"snmp_trap",	IP_NAT_HELPER_F_STANDALONE,	THIS_MODULE,	{ { 0, { .udp = { __constant_htons(SNMP_TRAP_PORT) } } },	  { 0, { 0 }, IPPROTO_UDP } },	{ { 0, { .udp = { 0xFFFF } } },	  { 0, { 0 }, 0xFFFF } },	nat_help, NULL };/***************************************************************************** * * Module stuff. * *****************************************************************************/ static int __init init(void){	int ret = 0;	ret = ip_nat_helper_register(&snmp);	if (ret < 0)		return ret;	ret = ip_nat_helper_register(&snmp_trap);	if (ret < 0) {		ip_nat_helper_unregister(&snmp);		return ret;	}	return ret;}static void __exit fini(void){	ip_nat_helper_unregister(&snmp);	ip_nat_helper_unregister(&snmp_trap);	br_write_lock_bh(BR_NETPROTO_LOCK);	br_write_unlock_bh(BR_NETPROTO_LOCK);}module_init(init);module_exit(fini);MODULE_PARM(debug, "i");MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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