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

📄 devinet.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* devinet.c * linqianghe@163.com * 2006-10-15 */#include "devinet.h"#include "log.h"#include "af_inet.h"#include "neighbour.h"#include "igmp.h"#include <linux/inetdevice.h>#include <linux/rtnetlink.h>#include <linux/in.h>extern struct neigh_table myarp_tbl;static struct notifier_block *myinetaddr_chain;static struct ipv4_devconf myipv4_devconf_dflt = {	.accept_redirects =  1,	.send_redirects =    1,	.secure_redirects =  1,	.shared_media =	     1,	.accept_source_route = 1,};static struct in_ifaddr *myinet_alloc_ifa(void){	struct in_ifaddr *ifa = kmalloc( sizeof(*ifa), GFP_KERNEL );	if( ifa ){		memset( ifa, 0, sizeof(*ifa) );		INIT_RCU_HEAD(&ifa->rcu_head);	}	return ifa;}struct in_device *myinetdev_init( struct net_device *dev ){	struct in_device *in_dev;	ASSERT_RTNL();	in_dev = kmalloc( sizeof(*in_dev), GFP_KERNEL );	if( !in_dev )		goto out;	memset(in_dev, 0, sizeof(*in_dev));	INIT_RCU_HEAD(&in_dev->rcu_head);	memcpy( &in_dev->cnf, &myipv4_devconf_dflt, sizeof(in_dev->cnf) );	in_dev->cnf.sysctl = NULL;	in_dev->dev = dev;	if( (in_dev->arp_parms = myneigh_parms_alloc(dev, &myarp_tbl)) == NULL )		goto out_kfree;	dev_hold(dev);//#ifdef CONFIG_SYSCTL//	neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,//			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);//#endif	in_dev_hold(in_dev);	rcu_assign_pointer(dev->ip_ptr, in_dev);//#ifdef CONFIG_SYSCTL//	devinet_sysctl_register(in_dev, &in_dev->cnf);//#endif	myip_mc_init_dev(in_dev);	if( dev->flags & IFF_UP )		myip_mc_up( in_dev );out:	return in_dev;out_kfree:	kfree( in_dev );	in_dev = NULL;	goto out;}static void myinet_rcu_free_ifa( struct rcu_head *head ){	struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);	if (ifa->ifa_dev)		in_dev_put(ifa->ifa_dev);	kfree(ifa);}static inline void myinet_free_ifa( struct in_ifaddr *ifa ){	call_rcu( &ifa->rcu_head, myinet_rcu_free_ifa );}static int myinet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,				u32 pid, u32 seq, int event, unsigned int flags){	struct ifaddrmsg *ifm;	struct nlmsghdr  *nlh;	unsigned char	*b = skb->tail;	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);	ifm = NLMSG_DATA(nlh);	ifm->ifa_family = MY_AF_INET;	ifm->ifa_prefixlen = ifa->ifa_prefixlen;	ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;	ifm->ifa_scope = ifa->ifa_scope;	ifm->ifa_index = ifa->ifa_dev->dev->ifindex;	if (ifa->ifa_address)		RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);	if (ifa->ifa_local)		RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);	if (ifa->ifa_broadcast)		RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);	if (ifa->ifa_anycast)		RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);	if (ifa->ifa_label[0])		RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}static void myrtmsg_ifa( int event, struct in_ifaddr* ifa ){	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128);	struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);	if (!skb)		netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);	else if( myinet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0 ){		kfree_skb(skb);		netlink_set_err( rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL );	}else{		PR_DEBUG( "netlink_broadcast!!\n" );		netlink_broadcast( rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL );	}}static int myinet_insert_ifa(struct in_ifaddr *ifa){	struct in_device *in_dev = ifa->ifa_dev;	struct in_ifaddr *ifa1, **ifap, **last_primary;	ASSERT_RTNL();	if( !ifa->ifa_local ){		myinet_free_ifa( ifa );		return 0;	}	ifa->ifa_flags &= ~IFA_F_SECONDARY;	last_primary = &in_dev->ifa_list;	for( ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL; ifap = &ifa1->ifa_next ){		if( !(ifa1->ifa_flags & IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope )			last_primary = &ifa1->ifa_next;		if( ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa) ){			if( ifa1->ifa_local == ifa->ifa_local ){				myinet_free_ifa(ifa);				return -EEXIST;			}			if( ifa1->ifa_scope != ifa->ifa_scope ){				myinet_free_ifa(ifa);				return -EINVAL;			}			ifa->ifa_flags |= IFA_F_SECONDARY;		}	}	if( !(ifa->ifa_flags & IFA_F_SECONDARY) ){		net_srandom( ifa->ifa_local );		ifap = last_primary;	}	ifa->ifa_next = *ifap;	*ifap = ifa;	//myrtmsg_ifa( RTM_NEWADDR, ifa );	notifier_call_chain( &myinetaddr_chain, NETDEV_UP, ifa );	return 0;}static void myinetdev_destroy(struct in_device *in_dev);static void myinet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,				int destroy){	struct in_ifaddr *promote = NULL;	struct in_ifaddr *ifa, *ifa1 = *ifap;	struct in_ifaddr *last_prim = in_dev->ifa_list;	struct in_ifaddr *prev_prom = NULL;	//int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);	int do_promote = 0;	ASSERT_RTNL();	if( !(ifa1->ifa_flags & IFA_F_SECONDARY) ){		struct in_ifaddr **ifap1 = &ifa1->ifa_next;		while ((ifa = *ifap1) != NULL) {			if( !(ifa->ifa_flags & IFA_F_SECONDARY) && ifa1->ifa_scope <= ifa->ifa_scope )				last_prim = ifa;			if( !(ifa->ifa_flags & IFA_F_SECONDARY) ||							ifa1->ifa_mask != ifa->ifa_mask ||							!inet_ifa_match(ifa1->ifa_address, ifa)) {				ifap1 = &ifa->ifa_next;				prev_prom = ifa;				continue;			}			if (!do_promote) {				*ifap1 = ifa->ifa_next;				myrtmsg_ifa(RTM_DELADDR, ifa);				notifier_call_chain( &myinetaddr_chain, NETDEV_DOWN, ifa );				myinet_free_ifa(ifa);			}else{				promote = ifa;				break;			}		}	}	*ifap = ifa1->ifa_next;	myrtmsg_ifa(RTM_DELADDR, ifa1);	notifier_call_chain( &myinetaddr_chain, NETDEV_DOWN, ifa1 );	if( promote ){		if( prev_prom ){			prev_prom->ifa_next = promote->ifa_next;			promote->ifa_next = last_prim->ifa_next;			last_prim->ifa_next = promote;		}		promote->ifa_flags &= ~IFA_F_SECONDARY;		myrtmsg_ifa(RTM_NEWADDR, promote);		notifier_call_chain( &myinetaddr_chain, NETDEV_UP, promote );		for( ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next ){			if (ifa1->ifa_mask != ifa->ifa_mask ||			    !inet_ifa_match(ifa1->ifa_address, ifa))					continue;			//fib_add_ifaddr(ifa);		}	}	if( destroy ){		myinet_free_ifa(ifa1);		if( !in_dev->ifa_list )			myinetdev_destroy( in_dev );	}}void myarp_ifdown( struct net_device *dev ){	myneigh_ifdown( &myarp_tbl, dev );}void myin_dev_finish_destroy(struct in_device *idev){	struct net_device *dev = idev->dev;	BUG_TRAP(!idev->ifa_list);	BUG_TRAP(!idev->mc_list);	PR_DEBUG( "in_dev_finish_destroy: %p=%s\n", idev, dev ? dev->name : "NIL");	dev_put(dev);	if (!idev->dead)		PR_DEBUG("Freeing alive in_device %p\n", idev);	else		kfree(idev);}static void myin_dev_rcu_put(struct rcu_head *head){	struct in_device *idev = container_of(head, struct in_device, rcu_head);	myin_dev_put(idev);}static void myinetdev_destroy(struct in_device *in_dev){	struct in_ifaddr *ifa;	struct net_device *dev;	ASSERT_RTNL();	dev = in_dev->dev;	if( dev == &loopback_dev )		return;	in_dev->dead = 1;	//ip_mc_destroy_dev(in_dev);	while( (ifa = in_dev->ifa_list) != NULL ){		myinet_del_ifa(in_dev, &in_dev->ifa_list, 0);		myinet_free_ifa(ifa);	}/*#ifdef CONFIG_SYSCTL	devinet_sysctl_unregister(&in_dev->cnf);#endif*/	dev->ip_ptr = NULL;/*#ifdef CONFIG_SYSCTL	neigh_sysctl_unregister(in_dev->arp_parms);#endif*/	myneigh_parms_release( &myarp_tbl, in_dev->arp_parms );	myarp_ifdown( dev );	call_rcu( &in_dev->rcu_head, myin_dev_rcu_put );	}static void myinetdev_changename(struct net_device *dev, struct in_device *in_dev){ 	struct in_ifaddr *ifa;	int named = 0;	for( ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next ){ 		char old[IFNAMSIZ], *dot; 		memcpy(old, ifa->ifa_label, IFNAMSIZ);		memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 		if( named++ == 0 )			continue;		dot = strchr(ifa->ifa_label, ':');		if (dot == NULL) { 			sprintf(old, ":%d", named); 			dot = old;		}		if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { 			strcat(ifa->ifa_label, dot); 		} else { 			strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); 		} 	}	}static int myinetdev_event(struct notifier_block *this, unsigned long event,			 void *ptr){	struct net_device *dev = ptr;	struct in_device *in_dev = __in_dev_get_rtnl(dev);	ASSERT_RTNL();

⌨️ 快捷键说明

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