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

📄 ip6_fw.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
字号:
/* *	IPv6 Firewall *	Linux INET6 implementation * *	Authors: *	Pedro Roque		<roque@di.fc.ul.pt>	 * *	$Id: ip6_fw.c,v 1.16 2001/10/31 08:17:58 davem Exp $ * *	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. */#include <linux/config.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/string.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/net.h>#include <linux/route.h>#include <linux/netdevice.h>#include <linux/in6.h>#include <linux/udp.h>#include <linux/init.h>#include <net/ipv6.h>#include <net/ip6_route.h>#include <net/ip6_fw.h>#include <net/netlink.h>static unsigned long ip6_fw_rule_cnt;static struct ip6_fw_rule ip6_fw_rule_list = {	{0},	NULL, NULL,	{0},	IP6_FW_REJECT};static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args);struct flow_rule_ops ip6_fw_ops = {	ip6_fw_accept};static struct rt6_info ip6_fw_null_entry = {	{{NULL, 0, 0, NULL,	  0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL,	  ip6_pkt_discard, ip6_pkt_discard, NULL}},	NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL,	0, &ip6_fw_rule_list, {{{{0}}}, 128}, {{{{0}}}, 128}};static struct fib6_node ip6_fw_fib = {	NULL, NULL, NULL, NULL,	&ip6_fw_null_entry,	0, RTN_ROOT|RTN_TL_ROOT, 0};rwlock_t ip6_fw_lock = RW_LOCK_UNLOCKED;static void ip6_rule_add(struct ip6_fw_rule *rl){	struct ip6_fw_rule *next;	write_lock_bh(&ip6_fw_lock);	ip6_fw_rule_cnt++;	next = &ip6_fw_rule_list;	rl->next = next;	rl->prev = next->prev;	rl->prev->next = rl;	next->prev = rl;	write_unlock_bh(&ip6_fw_lock);}static void ip6_rule_del(struct ip6_fw_rule *rl){	struct ip6_fw_rule *next, *prev;	write_lock_bh(&ip6_fw_lock);	ip6_fw_rule_cnt--;	next = rl->next;	prev = rl->prev;	next->prev = prev;	prev->next = next;	write_unlock_bh(&ip6_fw_lock);}static __inline__ struct ip6_fw_rule * ip6_fwrule_alloc(void){	struct ip6_fw_rule *rl;	rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC);	if (rl)	{		memset(rl, 0, sizeof(struct ip6_fw_rule));		rl->flowr.ops = &ip6_fw_ops;	}	return rl;}static __inline__ void ip6_fwrule_free(struct ip6_fw_rule * rl){	kfree(rl);}static __inline__ int port_match(int rl_port, int fl_port){	int res = 0;	if (rl_port == 0 || (rl_port == fl_port))		res = 1;	return res;}static int ip6_fw_accept_trans(struct ip6_fw_rule *rl,			       struct fl_acc_args *args){	int res = FLOWR_NODECISION;	int proto = 0;	int sport = 0;	int dport = 0;	switch (args->type) {	case FL_ARG_FORWARD:	{		struct sk_buff *skb = args->fl_u.skb;		struct ipv6hdr *hdr = skb->nh.ipv6h;		int len;		len = skb->len - sizeof(struct ipv6hdr);		proto = hdr->nexthdr;		switch (proto) {		case IPPROTO_TCP:		{			struct tcphdr *th;			if (len < sizeof(struct tcphdr)) {				res = FLOWR_ERROR;				goto out;			}			th = (struct tcphdr *)(hdr + 1);			sport = th->source;			dport = th->dest;			break;		}		case IPPROTO_UDP:		{			struct udphdr *uh;			if (len < sizeof(struct udphdr)) {				res = FLOWR_ERROR;				goto out;			}			uh = (struct udphdr *)(hdr + 1);			sport = uh->source;			dport = uh->dest;			break;		}		default:			goto out;		};		break;	}	case FL_ARG_ORIGIN:	{		proto = args->fl_u.fl_o.flow->proto;		if (proto == IPPROTO_ICMPV6) {			goto out;		} else {			sport = args->fl_u.fl_o.flow->uli_u.ports.sport;			dport = args->fl_u.fl_o.flow->uli_u.ports.dport;		}		break;	}	if (proto == rl->info.proto &&	    port_match(args->fl_u.fl_o.flow->uli_u.ports.sport, sport) &&	    port_match(args->fl_u.fl_o.flow->uli_u.ports.dport, dport)) {		if (rl->policy & IP6_FW_REJECT)			res = FLOWR_SELECT;		else			res = FLOWR_CLEAR;	}	default:#if IP6_FW_DEBUG >= 1		printk(KERN_DEBUG "ip6_fw_accept: unknown arg type\n");#endif		goto out;	};out:	return res;}static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args){	struct rt6_info *rt;	struct ip6_fw_rule *rl;	int proto;	int res = FLOWR_NODECISION;	rt = (struct rt6_info *) dst;	rl = (struct ip6_fw_rule *) rt->rt6i_flowr;	proto = rl->info.proto;	switch (proto) {	case 0:		if (rl->policy & IP6_FW_REJECT)			res = FLOWR_SELECT;		else			res = FLOWR_CLEAR;		break;	case IPPROTO_TCP:	case IPPROTO_UDP:		res = ip6_fw_accept_trans(rl, args);		break;	case IPPROTO_ICMPV6:	};	return res;}static struct dst_entry * ip6_fw_dup(struct dst_entry *frule,				     struct dst_entry *rt,				     struct fl_acc_args *args){	struct ip6_fw_rule *rl;	struct rt6_info *nrt;	struct rt6_info *frt;	frt = (struct rt6_info *) frule;	rl = (struct ip6_fw_rule *) frt->rt6i_flowr;	nrt = ip6_rt_copy((struct rt6_info *) rt);	if (nrt) {		nrt->u.dst.input = frule->input;		nrt->u.dst.output = frule->output;		nrt->rt6i_flowr = flow_clone(frt->rt6i_flowr);		nrt->rt6i_flags |= RTF_CACHE;		nrt->rt6i_tstamp = jiffies;	}	return (struct dst_entry *) nrt;}int ip6_fw_reject(struct sk_buff *skb){#if IP6_FW_DEBUG >= 1	printk(KERN_DEBUG "packet rejected: \n");#endif	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0,		    skb->dev);	/*	 *	send it via netlink, as (rule, skb)	 */	kfree_skb(skb);	return 0;}int ip6_fw_discard(struct sk_buff *skb){	printk(KERN_DEBUG "ip6_fw: BUG fw_reject called\n");	kfree_skb(skb);	return 0;}int ip6_fw_msg_add(struct ip6_fw_msg *msg){	struct in6_rtmsg rtmsg;	struct ip6_fw_rule *rl;	struct rt6_info *rt;	int err;	ipv6_addr_copy(&rtmsg.rtmsg_dst, &msg->dst);	ipv6_addr_copy(&rtmsg.rtmsg_src, &msg->src);	rtmsg.rtmsg_dst_len = msg->dst_len;	rtmsg.rtmsg_src_len = msg->src_len;	rtmsg.rtmsg_metric = IP6_RT_PRIO_FW;	rl = ip6_fwrule_alloc();	if (rl == NULL)		return -ENOMEM;	rl->policy = msg->policy;	rl->info.proto = msg->proto;	rl->info.uli_u.data = msg->u.data;	rtmsg.rtmsg_flags = RTF_NONEXTHOP|RTF_POLICY;	err = ip6_route_add(&rtmsg);	if (err) {		ip6_fwrule_free(rl);		return err;	}	/* The rest will not work for now. --ABK (989725) */#ifndef notdef	ip6_fwrule_free(rl);	return -EPERM;#else	rt->u.dst.error = -EPERM;	if (msg->policy == IP6_FW_ACCEPT) {		/*		 *	Accept rules are never selected		 *	(i.e. packets use normal forwarding)		 */		rt->u.dst.input = ip6_fw_discard;		rt->u.dst.output = ip6_fw_discard;	} else {		rt->u.dst.input = ip6_fw_reject;		rt->u.dst.output = ip6_fw_reject;	}	ip6_rule_add(rl);	rt->rt6i_flowr = flow_clone((struct flow_rule *)rl);	return 0;#endif}static int ip6_fw_msgrcv(int unit, struct sk_buff *skb){	int count = 0;	while (skb->len) {		struct ip6_fw_msg *msg;		if (skb->len < sizeof(struct ip6_fw_msg)) {			count = -EINVAL;			break;		}		msg = (struct ip6_fw_msg *) skb->data;		skb_pull(skb, sizeof(struct ip6_fw_msg));		count += sizeof(struct ip6_fw_msg);		switch (msg->action) {		case IP6_FW_MSG_ADD:			ip6_fw_msg_add(msg);			break;		case IP6_FW_MSG_DEL:			break;		default:			return -EINVAL;		};	}	return count;}static void ip6_fw_destroy(struct flow_rule *rl){	ip6_fwrule_free((struct ip6_fw_rule *)rl);}#ifdef MODULE#define ip6_fw_init module_init#endifvoid __init ip6_fw_init(void){	netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv);}#ifdef MODULEvoid cleanup_module(void){	netlink_detach(NETLINK_IP6_FW);}#endif

⌨️ 快捷键说明

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