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

📄 dn_route.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 3 页
字号:
        if (memcmp(ptr, dn_hiord_addr, 4) != 0)                goto drop_it;        ptr += 6;        /* Source info */        ptr += 2;	cb->src = dn_htons(dn_eth2dn(ptr));        if (memcmp(ptr, dn_hiord_addr, 4) != 0)                goto drop_it;        ptr += 6;        /* Other junk */        ptr++;        cb->hops = *ptr++; /* Visit Count */	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);drop_it:	kfree_skb(skb);	return NET_RX_DROP;}static int dn_route_rx_short(struct sk_buff *skb){	struct dn_skb_cb *cb = DN_SKB_CB(skb);	unsigned char *ptr = skb->data;	if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */		goto drop_it;	skb_pull(skb, 5);	skb->h.raw = skb->data;	cb->dst = *(dn_address *)ptr;        ptr += 2;        cb->src = *(dn_address *)ptr;        ptr += 2;        cb->hops = *ptr & 0x3f;	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);drop_it:        kfree_skb(skb);        return NET_RX_DROP;}static int dn_route_discard(struct sk_buff *skb){	/*	 * I know we drop the packet here, but thats considered success in	 * this case	 */	kfree_skb(skb);	return NET_RX_SUCCESS;}static int dn_route_ptp_hello(struct sk_buff *skb){	dn_dev_hello(skb);	dn_neigh_pointopoint_hello(skb);	return NET_RX_SUCCESS;}int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){	struct dn_skb_cb *cb;	unsigned char flags = 0;	__u16 len = dn_ntohs(*(__u16 *)skb->data);	struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;	unsigned char padlen = 0;	if (dn == NULL)		goto dump_it;	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)		goto out;	skb_pull(skb, 2);	if (len > skb->len)		goto dump_it;	skb_trim(skb, len);	flags = *skb->data;	cb = DN_SKB_CB(skb);	cb->stamp = jiffies;	cb->iif = dev->ifindex;	/*	 * If we have padding, remove it.	 */	if (flags & DN_RT_F_PF) {		padlen = flags & ~DN_RT_F_PF;		skb_pull(skb, padlen);		flags = *skb->data;	}	skb->nh.raw = skb->data;	/*	 * Weed out future version DECnet	 */	if (flags & DN_RT_F_VER)		goto dump_it;	cb->rt_flags = flags;	if (decnet_debug_level & 1)		printk(KERN_DEBUG 			"dn_route_rcv: got 0x%02x from %s [%d %d %d]\n",			(int)flags, (dev) ? dev->name : "???", len, skb->len, 			padlen);        if (flags & DN_RT_PKT_CNTL) {                switch(flags & DN_RT_CNTL_MSK) {        	        case DN_RT_PKT_INIT:				dn_dev_init_pkt(skb);				break;                	case DN_RT_PKT_VERI:				dn_dev_veri_pkt(skb);				break;		}		if (dn->parms.state != DN_DEV_S_RU)			goto dump_it;		switch(flags & DN_RT_CNTL_MSK) {                	case DN_RT_PKT_HELO:				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello);                	case DN_RT_PKT_L1RT:                	case DN_RT_PKT_L2RT:                                return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);                	case DN_RT_PKT_ERTH:				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello);                	case DN_RT_PKT_EEDH:				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello);                }        } else {		if (dn->parms.state != DN_DEV_S_RU)			goto dump_it;		skb_pull(skb, 1); /* Pull flags */                switch(flags & DN_RT_PKT_MSK) {                	case DN_RT_PKT_LONG:                        	return dn_route_rx_long(skb);                	case DN_RT_PKT_SHORT:                        	return dn_route_rx_short(skb);		}        }dump_it:	kfree_skb(skb);out:	return NET_RX_DROP;}static int dn_output(struct sk_buff *skb){	struct dst_entry *dst = skb->dst;	struct dn_route *rt = (struct dn_route *)dst;	struct net_device *dev = dst->dev;	struct dn_skb_cb *cb = DN_SKB_CB(skb);	struct neighbour *neigh;	int err = -EINVAL;	if ((neigh = dst->neighbour) == NULL)		goto error;	skb->dev = dev;	cb->src = rt->rt_saddr;	cb->dst = rt->rt_daddr;	/*	 * Always set the Intra-Ethernet bit on all outgoing packets	 * originated on this node. Only valid flag from upper layers	 * is return-to-sender-requested. Set hop count to 0 too.	 */	cb->rt_flags &= ~DN_RT_F_RQR;	cb->rt_flags |= DN_RT_F_IE;	cb->hops = 0;	return NF_HOOK(PF_DECnet, NF_DN_LOCAL_OUT, skb, NULL, dev, neigh->output);error:	if (net_ratelimit())		printk(KERN_DEBUG "dn_output: This should not happen\n");	kfree_skb(skb);	return err;}#ifdef CONFIG_DECNET_ROUTERstatic int dn_forward(struct sk_buff *skb){	struct dn_skb_cb *cb = DN_SKB_CB(skb);	struct dst_entry *dst = skb->dst;	struct neighbour *neigh;	struct net_device *dev = skb->dev;	int err = -EINVAL;	if ((neigh = dst->neighbour) == NULL)		goto error;	/*	 * Hop count exceeded.	 */	err = NET_RX_DROP;	if (++cb->hops > 30)		goto drop;	skb->dev = dst->dev;	/*	 * If packet goes out same interface it came in on, then set	 * the Intra-Ethernet bit. This has no effect for short	 * packets, so we don't need to test for them here.	 */	if (cb->iif == dst->dev->ifindex)		cb->rt_flags |= DN_RT_F_IE;	else		cb->rt_flags &= ~DN_RT_F_IE;	return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output);error:	if (net_ratelimit())		printk(KERN_DEBUG "dn_forward: This should not happen\n");drop:	kfree_skb(skb);	return err;}#endif/* * Drop packet. This is used for endnodes and for * when we should not be forwarding packets from * this dest. */static int dn_blackhole(struct sk_buff *skb){	kfree_skb(skb);	return NET_RX_DROP;}/* * Used to catch bugs. This should never normally get * called. */static int dn_rt_bug(struct sk_buff *skb){	if (net_ratelimit()) {		struct dn_skb_cb *cb = DN_SKB_CB(skb);		printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n",				cb->src, cb->dst);	}	kfree_skb(skb);	return NET_RX_BAD;}static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_address src, int flags){	struct dn_route *rt = NULL;	struct net_device *dev = decnet_default_device;	struct neighbour *neigh = NULL;	struct dn_dev *dn_db;	unsigned hash;#ifdef CONFIG_DECNET_ROUTER	struct dn_fib_key key;	struct dn_fib_res res;	int err;	key.src = src;	key.dst = dst;	key.iif = 0;	key.oif = 0;	key.fwmark = 0;	key.scope = RT_SCOPE_UNIVERSE;	if ((err = dn_fib_lookup(&key, &res)) == 0) {		switch(res.type) {			case RTN_UNICAST:				/*				 * This method of handling multipath				 * routes is a hack and will change.				 * It works for now though.				 */				if (res.fi->fib_nhs)					dn_fib_select_multipath(&key, &res);				neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1);				err = -ENOBUFS;				if (!neigh)					break;				err = 0;				break;			case RTN_UNREACHABLE:				err = -EHOSTUNREACH;				break;			default:				err = -EINVAL;		}		dn_fib_res_put(&res);		if (err < 0)			return err;		goto got_route;	}	if (err != -ESRCH)		return err;#endif 	/* Look in On-Ethernet cache first */	if (!(flags & MSG_TRYHARD)) {		if ((neigh = dn_neigh_lookup(&dn_neigh_table, &dst)) != NULL)			goto got_route;	}	if (dev == NULL)		return -EINVAL;	dn_db = dev->dn_ptr;	if (dn_db == NULL)		return -EINVAL;	/* Try default router */	if ((neigh = neigh_clone(dn_db->router)) != NULL)		goto got_route;	/* Send to default device (and hope for the best) if above fail */	if ((neigh = __neigh_lookup(&dn_neigh_table, &dst, dev, 1)) != NULL)		goto got_route;	return -EINVAL;got_route:	if ((rt = dst_alloc(&dn_dst_ops)) == NULL) {		neigh_release(neigh);		return -EINVAL;	}	dn_db = (struct dn_dev *)neigh->dev->dn_ptr;		rt->key.saddr  = src;	rt->rt_saddr   = src;	rt->key.daddr  = dst;	rt->rt_daddr   = dst;	rt->key.oif    = neigh ? neigh->dev->ifindex : -1;	rt->key.iif    = 0;	rt->key.fwmark = 0;	rt->u.dst.neighbour = neigh;	rt->u.dst.dev = neigh ? neigh->dev : NULL;	rt->u.dst.lastuse = jiffies;	rt->u.dst.output = dn_output;	rt->u.dst.input  = dn_rt_bug;	if (dn_dev_islocal(neigh->dev, rt->rt_daddr))		rt->u.dst.input = dn_nsp_rx;	hash = dn_hash(rt->key.saddr, rt->key.daddr);	dn_insert_route(rt, hash);	*pprt = &rt->u.dst;	return 0;}int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags){	unsigned hash = dn_hash(src, dst);	struct dn_route *rt = NULL;	if (!(flags & MSG_TRYHARD)) {		read_lock_bh(&dn_rt_hash_table[hash].lock);		for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {			if ((dst == rt->key.daddr) &&					(src == rt->key.saddr) &&					(rt->key.iif == 0) &&					(rt->key.oif != 0)) {				rt->u.dst.lastuse = jiffies;				dst_hold(&rt->u.dst);				rt->u.dst.__use++;				read_unlock_bh(&dn_rt_hash_table[hash].lock);				*pprt = &rt->u.dst;				return 0;			}		}		read_unlock_bh(&dn_rt_hash_table[hash].lock);	}	return dn_route_output_slow(pprt, dst, src, flags);}static int dn_route_input_slow(struct sk_buff *skb){	struct dn_route *rt = NULL;	struct dn_skb_cb *cb = DN_SKB_CB(skb);	struct net_device *dev = skb->dev;	struct dn_dev *dn_db;	struct neighbour *neigh = NULL;	int (*dnrt_input)(struct sk_buff *skb);	int (*dnrt_output)(struct sk_buff *skb);	u32 fwmark = 0;	unsigned hash;	dn_address saddr = cb->src;	dn_address daddr = cb->dst;#ifdef CONFIG_DECNET_ROUTER	struct dn_fib_key key;	struct dn_fib_res res;	int err;#endif	if (dev == NULL)		return -EINVAL;	if ((dn_db = dev->dn_ptr) == NULL)		return -EINVAL;

⌨️ 快捷键说明

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