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

📄 ipv4.c

📁 openswan
💻 C
📖 第 1 页 / 共 2 页
字号:
/*Copyright (c) 2003,2004 Jeremy Kerr & Rusty RussellThis file is part of nfsim.nfsim is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.nfsim is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with nfsim; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include "ipv4.h"#include "utils.h"#include <core.h>#include <field.h>#if 0#include <linux/netfilter_ipv4.h>#endifint route(struct sk_buff *skb);LIST_HEAD(routes);static struct notifier_block *inetaddr_chain;static int __ip_route_output_key(struct rtable **rp, struct flowi *flp);static int destroy_route(void *r){	struct ipv4_route *route = r;	list_del(&route->entry);	return 0;}void add_route_for_device(struct in_device *indev){	struct ipv4_route *route;	route = talloc(indev, struct ipv4_route);	talloc_set_destructor(route, destroy_route);	route->netmask = indev->ifa_list->ifa_mask;	route->network = indev->ifa_list->ifa_address & indev->ifa_list->ifa_mask;	route->interface = indev->dev;	route->gateway = indev->ifa_list->ifa_address;	list_add_tail(&route->entry, &routes);}struct rtable *rcache;static int destroy_rtable(void *r){	struct rtable *rt = r, **p;	/* Remove from cache if it's there (it should be, currently) */	for (p = &rcache; *p; p = &(*p)->u.rt_next) {		if (*p == rt) {			*p = rt->u.rt_next;			break;		}	}	return 0;}#if 0/* need the following:    - interfaces    - routes */static void init(void){	/* name our hooks */	nf_hooknames[PF_INET][0] = "NF_IP_PRE_ROUTING";	nf_hooknames[PF_INET][1] = "NF_IP_LOCAL_IN";	nf_hooknames[PF_INET][2] = "NF_IP_FORWARD";	nf_hooknames[PF_INET][3] = "NF_IP_LOCAL_OUT";	nf_hooknames[PF_INET][4] = "NF_IP_POST_ROUTING";}init_call(init);#endifint register_inetaddr_notifier(struct notifier_block *nb){	return notifier_chain_register(&inetaddr_chain, nb);}int unregister_inetaddr_notifier(struct notifier_block *nb){	return notifier_chain_unregister(&inetaddr_chain, nb);}int __call_inetaddr_notifier(unsigned long val, struct in_ifaddr *ifa){	struct notifier_block *nb = inetaddr_chain;	return notifier_call_chain(&nb, val, ifa);}#if 0static int ip_rcv_finish(struct sk_buff *skb){	if (!skb->dst &&	    ip_route_input(skb, skb->nh.iph->daddr, skb->nh.iph->saddr,			   skb->nh.iph->tos, skb->dev)) {		kfree_skb(skb);		return -1;	}			return dst_input(skb);}#endifint ip_rcv(struct sk_buff *skb){#if 0	skb->dev->stats.rxpackets++;	skb->dev->stats.rxbytes += skb->len;	/* pull data to the start of the ip header */	skb_pull(skb, skb->nh.raw - skb->data);	log_packet(skb, "rcv:%s", skb->dev->name);	return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,	               ip_rcv_finish);#else	return 0;#endif}int ip_rcv_local(struct sk_buff *skb){	struct rtable *rt;	struct flowi fl;	log_packet(skb, "rcv_local");	/* pull data to the start of the ip header */	skb_pull(skb, skb->nh.raw - skb->data);	rt = (struct rtable *)skb->dst;	if (rt)		goto routed;	memset(&fl, 0, sizeof(fl));		fl.fl4_dst    = skb->nh.iph->daddr;	fl.fl4_src    = skb->nh.iph->saddr;	fl.fl4_tos    = skb->nh.iph->tos;#ifdef CONFIG_IP_ROUTE_FWMARK	fl.fl4_fwmark = skb->nfmark;#endif	if (__ip_route_output_key(&rt, &fl)) {		log_route(skb, "no route");		kfree_skb(skb);		return 1;	}		skb->dst = (struct dst_entry *)rt;	dst_hold(skb_dst);routed:	skb->dev = skb->dst->dev;#if 0	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev, dst_output);#else	return 0;#endif}static int ip_local_deliver(struct sk_buff *skb){#if 0	return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL, nf_send_local);#else	return 0;#endif}int ip_finish_output(struct sk_buff *skb){	struct net_device *dev = skb->dst->dev;		skb->dev = dev;	skb->protocol = htons(ETH_P_IP);	/*	if (skb->mac.ethernet)		skb->mac.ethernet->h_proto = skb->protocol;	*/#if 0	return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,		nf_send);#else	return 0;#endif	}static int ip_output(struct sk_buff *skb){	/* FIXME: fragment? */	return ip_finish_output(skb);}unsigned short ip_compute_csum(unsigned char * buff, int len){    return csum_fold (csum_partial(buff, len, 0));}static int __ip_route_output_key(struct rtable **rp, struct flowi *flp){	struct rtable *rth;	struct net_device *dev;	struct ipv4_route *route;	if (should_i_fail(__func__))		return -ENOMEM;	/* check for a cached route */	for (rth = rcache; rth; rth = rth->u.rt_next) {		if (rth->fl.fl4_dst == flp->fl4_dst &&		    rth->fl.fl4_src == flp->fl4_src &&		    rth->fl.iif     == 0 &&		    rth->fl.oif     == flp->oif &&#ifdef CONFIG_IP_ROUTE_FWMARK		    rth->fl.fl4_fwmark == flp->fl4_fwmark &&#endif		    rth->fl.fl4_tos == flp->fl4_tos) {		    	dst_hold(&rth->u.dst)			*rp = rth;			return 0;		}	}	list_for_each_entry(dev, &interfaces, entry) {		struct in_ifaddr *ifaddr;				if (!dev->ip_ptr)			continue;		ifaddr = ((struct in_device *)(dev->ip_ptr))->ifa_list;		while (ifaddr) {			if (flp->fl4_dst == ifaddr->ifa_local) {				rth = talloc_zero(dev->ip_ptr, struct rtable);				talloc_set_destructor(rth, destroy_rtable);				rth->u.dst.output = ip_output;				rth->u.dst.input  = ip_local_deliver;				rth->u.dst.dev    = &loopback_dev;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)				rth->u.dst.pmtu	  = 1500;#endif				rth->rt_src       = rth->fl.fl4_src				                  = flp->fl4_src;				rth->rt_dst       = rth->fl.fl4_dst				                  = flp->fl4_dst;				rth->rt_gateway   = flp->fl4_dst;				rth->rt_iif       = rth->fl.iif = flp->iif;				rth->fl.fl4_tos	= flp->fl4_tos;#ifdef CONFIG_IP_ROUTE_FWMARK				rth->fl.fl4_fwmark = flp->fl4_fwmark;#endif				rth->u.rt_next = rcache;				rcache = rth;				*rp = rth;				return 0;			}			ifaddr = ifaddr->ifa_next;		}			}	/* otherwise, find the appropriate route & create an rcache entry */	list_for_each_entry(route, &routes, entry) {		if ((flp->fl4_dst & route->netmask) ==		           route->network) {			rth = talloc_zero(route, struct rtable);			talloc_set_destructor(rth, destroy_rtable);			rth->u.dst.dev    =  route->interface;			rth->u.dst.output = ip_output;			rth->u.dst.input  = NULL;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)			rth->u.dst.pmtu	  = 1500;#endif			rth->rt_src       = rth->fl.fl4_src = flp->fl4_src;			if (!rth->rt_src)				rth->rt_src					= inet_select_addr(route->interface,							   flp->fl4_dst,							   RT_SCOPE_UNIVERSE);			rth->rt_dst       = rth->fl.fl4_dst = flp->fl4_dst;			rth->rt_gateway   = route->gateway;			rth->fl.oif       = route->interface->ifindex;			rth->fl.oif = flp->oif;			rth->fl.fl4_tos	= flp->fl4_tos;#ifdef CONFIG_IP_ROUTE_FWMARK			rth->fl.fl4_fwmark = flp->fl4_fwmark;#endif			/* add to rcache list */			rth->u.rt_next = rcache;			rcache = rth;			*rp = rth;			return 0;		}	}	return 1;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)int ip_route_output_key(struct rtable **rp, struct rt_key *key){	struct flowi fl;	fl.fl4_dst = key->dst;	fl.fl4_src = key->src;	fl.iif = 0;	fl.oif = key->oif;#ifdef CONFIG_IP_ROUTE_FWMARK	fl.fl4_fwmark = key->fwmark;#endif	fl.fl4_tos = key->tos;	return __ip_route_output_key(rp, &fl);}#elseint ip_route_output_key(struct rtable **rp, struct flowi *flp){	return __ip_route_output_key(rp, flp);}#endif/* 2.6.10-rc3 added this. */int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,		struct sock *sk, int flags){	struct rtable **rp = (void *)dst_p;	return __ip_route_output_key(rp, fl);}#if 0static int ip_forward(struct sk_buff *skb){	u32 check;	if (!(--skb->nh.iph->ttl)) {		log_route(skb, "ip_forward:ttl expired");		icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);		kfree_skb(skb);		return 1;	}	nfsim_update_skb(skb, &skb->nh.iph->ttl, sizeof(skb->nh.iph->ttl));	check = skb->nh.iph->check;	check += htons(0x0100);	skb->nh.iph->check = check + (check>=0xFFFF);	/* Tell nfsim it's me changing data here. */	nfsim_update_skb(skb, &skb->nh.iph->check, sizeof(skb->nh.iph->check));	/* FIXME: strict source routing... */#if 0	return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, skb->dst->dev,		dst_output);#else	return 0;#endif}#endif#if 0int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,		   u8 tos, struct net_device *dev){	struct rtable *rth;	struct ipv4_route *route;	int iif = dev->ifindex;	for (rth = rcache; rth; rth = rth->u.rt_next) {		if (rth->fl.fl4_dst == daddr &&		    rth->fl.fl4_src == saddr &&		    rth->fl.iif == iif &&		    rth->fl.oif == 0 &&#ifdef CONFIG_IP_ROUTE_FWMARK		    rth->fl.fl4_fwmark == skb->nfmark &&#endif		    rth->fl.fl4_tos == tos) {			dst_hold(&rth->u.dst);			skb->dst = (struct dst_entry*)rth;			return 0;		}	}	/* is this a local packet ? */	list_for_each_entry(dev, &interfaces, entry) {		struct in_ifaddr *ifaddr;				if (!dev->ip_ptr)			continue;		ifaddr = ((struct in_device *)(dev->ip_ptr))->ifa_list;		while (ifaddr) {			if (skb->nh.iph->daddr == ifaddr->ifa_local) {				log_route(skb,					"route:local packet (%s)",			 		dev->name);				rth = talloc_zero(dev->ip_ptr, struct rtable);				talloc_set_destructor(rth, destroy_rtable);				rth->u.dst.output = NULL;				rth->u.dst.input  = ip_local_deliver;				rth->u.dst.dev    = &loopback_dev;				rth->rt_src       = rth->fl.fl4_src = saddr;				rth->rt_dst       = rth->fl.fl4_dst = daddr;				rth->rt_gateway   = daddr;				rth->rt_iif       = rth->fl.iif = dev->ifindex;				rth->fl.fl4_tos	= tos;#ifdef CONFIG_IP_ROUTE_FWMARK				rth->fl.fl4_fwmark = skb->nfmark;#endif				skb->dst = &rth->u.dst;				return 0;			}			ifaddr = ifaddr->ifa_next;		}			}	/* otherwise, find the appropriate route & create an rcache entry */	list_for_each_entry(route, &routes, entry) {		if ((skb->nh.iph->daddr & route->netmask) ==		           route->network) {			rth = talloc_zero(route, struct rtable);			talloc_set_destructor(rth, destroy_rtable);			rth->u.dst.dev = route->interface;			rth->u.dst.output = ip_output;			rth->u.dst.input  = ip_forward;			rth->rt_src       = rth->fl.fl4_src = saddr;			rth->rt_dst       = rth->fl.fl4_dst = daddr;			rth->rt_gateway   = route->gateway;			rth->rt_iif       = rth->fl.iif =						route->interface->ifindex;			rth->fl.oif = 0;			rth->fl.fl4_tos	= tos;#ifdef CONFIG_IP_ROUTE_FWMARK			rth->fl.fl4_fwmark = skb->nfmark;#endif			/* add to rcache list */			rth->u.rt_next = rcache;			rcache = rth;						skb->dst = &rth->u.dst;			return 0;		}	}	log_route(skb, "ERROR: packet is not local and no matching "		"route (dst=%u.%u.%u.%u)", NIPQUAD(daddr));	return 1;}#endifint ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)){	log_packet(skb, "ip_fragment");	(*output)(skb);	return 0;}struct fraglist{	struct list_head list;	struct sk_buff *frags[20];};static struct list_head fraglist[IP_DEFRAG_VS_FWD];static void init_fraglist(void){	unsigned int i;	for (i = 0; i < ARRAY_SIZE(fraglist); i++)		INIT_LIST_HEAD(&fraglist[i]);}init_call(init_fraglist);#if 0static struct sk_buff *gather_frag(struct fraglist *f, struct sk_buff *skb){	unsigned int i, len, off, max = 0;	bool ended = false;	char filled[70000] = { 0 };	char data[70000];	for (i = 0; i < ARRAY_SIZE(f->frags); i++) {		if (!f->frags[i]) {			if (!skb)				break;			f->frags[i] = skb;			talloc_steal(f, skb);			skb = NULL;		}

⌨️ 快捷键说明

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