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

📄 iptcrdr.c

📁 miniupnpd可以在嵌入式linux中实现upnp功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: iptcrdr.c,v 1.27 2008/03/03 01:37:43 nanard Exp $ *//* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2008 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <sys/errno.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <dlfcn.h>#include <libiptc/libiptc.h>#include <iptables.h>#include <linux/version.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)#include <linux/netfilter_ipv4/ip_nat.h>#else#include <linux/netfilter/nf_nat.h>/*#define ip_nat_multi_range	nf_nat_multi_range#define ip_nat_range		nf_nat_range*/#endif#include "iptcrdr.h"/* dummy init and shutdown functions */int init_redirect(void){	return 0;}void shutdown_redirect(void){	return;}/* chain name to use, both in the nat table * and the filter table */static const char miniupnpd_chain[] = "MINIUPNPD";/* convert an ip address to string */static int snprintip(char * dst, size_t size, uint32_t ip){	return snprintf(dst, size,	       "%u.%u.%u.%u", ip >> 24, (ip >> 16) & 0xff,	       (ip >> 8) & 0xff, ip & 0xff);}/* netfilter cannot store redirection descriptions, so we use our * own structure to store them */struct rdr_desc {	struct rdr_desc * next;	unsigned short eport;	short proto;	char str[];};/* pointer to the chained list where descriptions are stored */static struct rdr_desc * rdr_desc_list = 0;static voidadd_redirect_desc(unsigned short eport, int proto, const char * desc){	struct rdr_desc * p;	size_t l;	if(desc)	{		l = strlen(desc) + 1;		p = malloc(sizeof(struct rdr_desc) + l);		if(p)		{			p->next = rdr_desc_list;			p->eport = eport;			p->proto = (short)proto;			memcpy(p->str, desc, l);			rdr_desc_list = p;		}	}}static voiddel_redirect_desc(unsigned short eport, int proto){	struct rdr_desc * p, * last;	p = rdr_desc_list;	last = 0;	while(p)	{		if(p->eport == eport && p->proto == proto)		{			if(!last)				rdr_desc_list = p->next;			else				last->next = p->next;			free(p);			return;		}		last = p;		p = p->next;	}}static voidget_redirect_desc(unsigned short eport, int proto,                  char * desc, int desclen){	struct rdr_desc * p;	if(!desc || (desclen == 0))		return;	for(p = rdr_desc_list; p; p = p->next)	{		if(p->eport == eport && p->proto == (short)proto)		{			strncpy(desc, p->str, desclen);			return;		}	}	/* if no description was found, return miniupnpd as default */	strncpy(desc, "miniupnpd", desclen);}/* add_redirect_rule2() */intadd_redirect_rule2(const char * ifname, unsigned short eport,                   const char * iaddr, unsigned short iport, int proto,				   const char * desc){	int r = addnatrule(proto, eport, iaddr, iport);	if(r >= 0)		add_redirect_desc(eport, proto, desc);	return r;}intadd_filter_rule2(const char * ifname, const char * iaddr,                 unsigned short eport, unsigned short iport,                 int proto, const char * desc){	return add_filter_rule(proto, iaddr, iport);}/* get_redirect_rule()  * returns -1 if the rule is not found */intget_redirect_rule(const char * ifname, unsigned short eport, int proto,                  char * iaddr, int iaddrlen, unsigned short * iport,                  char * desc, int desclen,                  u_int64_t * packets, u_int64_t * bytes){	int r = -1;	iptc_handle_t h;	const struct ipt_entry * e;	const struct ipt_entry_target * target;	const struct ip_nat_multi_range * mr;	const struct ipt_entry_match *match;	h = iptc_init("nat");	if(!h)	{		syslog(LOG_ERR, "get_redirect_rule() : "		                "iptc_init() failed : %s",		       iptc_strerror(errno));		return -1;	}	if(!iptc_is_chain(miniupnpd_chain, h))	{		syslog(LOG_ERR, "chain %s not found", miniupnpd_chain);	}	else	{		for(e = iptc_first_rule(miniupnpd_chain, &h);		    e;			e = iptc_next_rule(e, &h))		{			if(proto==e->ip.proto)			{				match = (const struct ipt_entry_match *)&e->elems;				if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))				{					const struct ipt_tcp * info;					info = (const struct ipt_tcp *)match->data;					if(eport != info->dpts[0])						continue;				}				else				{					const struct ipt_udp * info;					info = (const struct ipt_udp *)match->data;					if(eport != info->dpts[0])						continue;				}				target = (void *)e + e->target_offset;				mr = (const struct ip_nat_multi_range *)&target->data[0];				snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip));				*iport = ntohs(mr->range[0].min.all);				/*if(desc)					strncpy(desc, "miniupnpd", desclen);*/				get_redirect_desc(eport, proto, desc, desclen);				if(packets)					*packets = e->counters.pcnt;				if(bytes)					*bytes = e->counters.bcnt;				r = 0;				break;			}		}	}	iptc_free(&h);	return r;}/* get_redirect_rule_by_index()  * return -1 when the rule was not found */intget_redirect_rule_by_index(int index,                           char * ifname, unsigned short * eport,                           char * iaddr, int iaddrlen, unsigned short * iport,                           int * proto, char * desc, int desclen,                           u_int64_t * packets, u_int64_t * bytes){	int r = -1;	int i = 0;	iptc_handle_t h;	const struct ipt_entry * e;	const struct ipt_entry_target * target;	const struct ip_nat_multi_range * mr;	const struct ipt_entry_match *match;	h = iptc_init("nat");	if(!h)	{		syslog(LOG_ERR, "get_redirect_rule_by_index() : "		                "iptc_init() failed : %s",		       iptc_strerror(errno));		return -1;	}	if(!iptc_is_chain(miniupnpd_chain, h))	{		syslog(LOG_ERR, "chain %s not found", miniupnpd_chain);	}	else	{		for(e = iptc_first_rule(miniupnpd_chain, &h);		    e;			e = iptc_next_rule(e, &h))		{			if(i==index)			{				*proto = e->ip.proto;				match = (const struct ipt_entry_match *)&e->elems;				if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))				{					const struct ipt_tcp * info;					info = (const struct ipt_tcp *)match->data;					*eport = info->dpts[0];				}				else				{					const struct ipt_udp * info;					info = (const struct ipt_udp *)match->data;					*eport = info->dpts[0];				}				target = (void *)e + e->target_offset;				mr = (const struct ip_nat_multi_range *)&target->data[0];				snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip));				*iport = ntohs(mr->range[0].min.all);                /*if(desc)				    strncpy(desc, "miniupnpd", desclen);*/				get_redirect_desc(*eport, *proto, desc, desclen);				if(packets)					*packets = e->counters.pcnt;				if(bytes)					*bytes = e->counters.bcnt;				r = 0;				break;			}			i++;		}	}	iptc_free(&h);	return r;}/* delete_rule_and_commit() : * subfunction used in delete_redirect_and_filter_rules() */static intdelete_rule_and_commit(unsigned int index, iptc_handle_t *h,                       const char * logcaller){	int r = 0;	if(!iptc_delete_num_entry(miniupnpd_chain, index, h))	{		syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n",	    	   logcaller, iptc_strerror(errno));		r = -1;	}	else if(!iptc_commit(h))	{		syslog(LOG_ERR, "%s() : iptc_commit(): %s\n",	    	   logcaller, iptc_strerror(errno));		r = -1;	}	return r;}/* delete_redirect_and_filter_rules() */intdelete_redirect_and_filter_rules(unsigned short eport, int proto){	int r = -1;	unsigned index = 0;	unsigned i = 0;	iptc_handle_t h;	const struct ipt_entry * e;	const struct ipt_entry_match *match;	h = iptc_init("nat");	if(!h)	{		syslog(LOG_ERR, "delete_redirect_and_filter_rules() : "		                "iptc_init() failed : %s",		       iptc_strerror(errno));		return -1;	}	if(!iptc_is_chain(miniupnpd_chain, h))	{		syslog(LOG_ERR, "chain %s not found", miniupnpd_chain);	}	else	{		for(e = iptc_first_rule(miniupnpd_chain, &h);		    e;			e = iptc_next_rule(e, &h), i++)		{			if(proto==e->ip.proto)			{				match = (const struct ipt_entry_match *)&e->elems;				if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))				{					const struct ipt_tcp * info;					info = (const struct ipt_tcp *)match->data;					if(eport != info->dpts[0])						continue;				}

⌨️ 快捷键说明

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