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

📄 dsr-dev.c

📁 DSR-UU is a DSR implementation that runs in Linux and in the ns-2 network simulator. DSR-UU imple
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) Uppsala University * * This file is distributed under the terms of the GNU general Public * License (GPL), see the file LICENSE * * Author: Erik Nordström, <erikn@it.uu.se> */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/etherdevice.h>#include <linux/init.h>#include <linux/if_ether.h>#include <net/ip.h>#include <linux/random.h>#include <linux/wireless.h>#include "debug.h"#include "dsr.h"#include "neigh.h"#include "dsr-pkt.h"#include "dsr-opt.h"#include "dsr-rreq.h"#include "link-cache.h"#include "dsr-srt.h"#include "dsr-ack.h"#include "send-buf.h"#include "maint-buf.h"#include "dsr-io.h"/* Our dsr device */static struct net_device *dsr_dev;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)/* dsr_node must be static on some older kernels, otherwise it segfaults on * module load */static struct dsr_node *dsr_node;#elsestruct dsr_node *dsr_node;#endifstatic int rp_filter = 0;static int forwarding = 0;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)static int dsr_dev_llrecv(struct sk_buff *skb, struct net_device *indev,			  struct packet_type *pt);#elsestatic int dsr_dev_llrecv(struct sk_buff *skb, struct net_device *indev,			  struct packet_type *pt, struct net_device *orig_dev);#endifstatic struct packet_type dsr_packet_type = {	.type = __constant_htons(ETH_P_IP),	.func = dsr_dev_llrecv,};struct sk_buff *dsr_skb_create(struct dsr_pkt *dp, struct net_device *dev){	struct sk_buff *skb;	char *buf;	int ip_len;	int tot_len;	int dsr_opts_len = dsr_pkt_opts_len(dp);	ip_len = dp->nh.iph->ihl << 2;	tot_len = ip_len + dsr_opts_len + dp->payload_len;	DEBUG("ip_len=%d dsr_opts_len=%d payload_len=%d tot_len=%d\n",	      ip_len, dsr_opts_len, dp->payload_len, tot_len);#ifdef KERNEL26	skb = alloc_skb(tot_len + LL_RESERVED_SPACE(dev), GFP_ATOMIC);#else	skb = alloc_skb(dev->hard_header_len + 15 + tot_len, GFP_ATOMIC);#endif	if (!skb) {		DEBUG("alloc_skb failed\n");		return NULL;	}	/* We align to 16 bytes, for ethernet: 2 bytes + 14 bytes header */#ifdef KERNEL26	skb_reserve(skb, LL_RESERVED_SPACE(dev));#else	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);#endif	skb->mac.raw = skb->data - 14;	skb->nh.raw = skb->data;	skb->dev = dev;	skb->protocol = htons(ETH_P_IP);	/* Copy in all the headers in the right order */	buf = skb_put(skb, tot_len);	memcpy(buf, dp->nh.raw, ip_len);	/* For some reason the checksum has to be recalculated here, at least	 * when there is a record route IP option */	ip_send_check((struct iphdr *)buf);	buf += ip_len;	/* Add DSR header if it exists */	if (dsr_opts_len) {		memcpy(buf, dp->dh.raw, dsr_opts_len);		buf += dsr_opts_len;	}	/* Add payload */	if (dp->payload_len && dp->payload)		memcpy(buf, dp->payload, dp->payload_len);	return skb;}int dsr_hw_header_create(struct dsr_pkt *dp, struct sk_buff *skb){	struct sockaddr broadcast =	    { AF_UNSPEC, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };	struct neighbor_info neigh_info;	if (dp->dst.s_addr == DSR_BROADCAST)		memcpy(neigh_info.hw_addr.sa_data, broadcast.sa_data, ETH_ALEN);	else {		/* Get hardware destination address */		if (neigh_tbl_query(dp->nxt_hop, &neigh_info) < 0) {			DEBUG			    ("Could not get hardware address for next hop %s\n",			     print_ip(dp->nxt_hop));			return -1;		}	}	if (skb->dev->hard_header) {		skb->dev->hard_header(skb, skb->dev, ETH_P_IP,				      neigh_info.hw_addr.sa_data, 0, skb->len);	} else {		DEBUG("Missing hard_header\n");		return -1;	}	return 0;}static int dsr_dev_inetaddr_event(struct notifier_block *this,				  unsigned long event, void *ptr){	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;	struct in_device *indev;	if (!ifa)		return NOTIFY_DONE;	indev = ifa->ifa_dev;	if (!indev)		return NOTIFY_DONE;	switch (event) {	case NETDEV_UP:		DEBUG("inetdev UP\n");		if (indev->dev == dsr_dev) {			struct dsr_node *dnode;			struct in_addr addr, bc;			dnode = (struct dsr_node *)indev->dev->priv;			dsr_node_lock(dnode);			dnode->ifaddr.s_addr = ifa->ifa_address;			dnode->bcaddr.s_addr = ifa->ifa_broadcast;			dnode->slave_indev = in_dev_get(dnode->slave_dev);                        /* Disable rp_filter and enable forwarding */                        if (dnode->slave_indev) {                                rp_filter = dnode->slave_indev->cnf.rp_filter;                                forwarding = dnode->slave_indev->cnf.forwarding;                                dnode->slave_indev->cnf.rp_filter = 0;                                dnode->slave_indev->cnf.forwarding = 1;                        }						dsr_node_unlock(dnode);						addr.s_addr = ifa->ifa_address;			bc.s_addr = ifa->ifa_broadcast;						DEBUG("New ip=%s broadcast=%s\n",			      print_ip(addr), print_ip(bc));		}		break;	default:		break;	};	return NOTIFY_DONE;}static int dsr_dev_netdev_event(struct notifier_block *this,				unsigned long event, void *ptr){	struct net_device *dev = (struct net_device *)ptr;	struct dsr_node *dnode = (struct dsr_node *)dsr_dev->priv;	int slave_change = 0;	if (!dev)		return NOTIFY_DONE;	switch (event) {	case NETDEV_REGISTER:		DEBUG("Netdev register %s\n", dev->name);		if (dnode->slave_dev == NULL && 		    strcmp(dev->name, dnode->slave_ifname) == 0) {						DEBUG("Slave dev %s up\n", dev->name);						dsr_node_lock(dnode);			dnode->slave_dev = dev;			dev_hold(dev);			dsr_node_unlock(dnode);			/* Reduce the MTU to allow DSR options of 100			 * bytes. If larger, drop or implement			 * fragmentation... ;-) Alternatively find a			 * way to dynamically reduce the data size of			 * packets depending on the size of the DSR			 * header. */			dsr_dev->mtu = dev->mtu - DSR_OPTS_MAX_SIZE;						DEBUG("Registering packet type\n");			dsr_packet_type.func = dsr_dev_llrecv;			dsr_packet_type.dev = dev;			dev_add_pack(&dsr_packet_type);						slave_change = 1;		}		if (slave_change)			DEBUG("New DSR slave interface %s\n", dev->name);		break;	case NETDEV_CHANGE:		DEBUG("Netdev change\n");		break;	case NETDEV_UP:		DEBUG("Netdev up %s\n", dev->name);		if (ConfVal(PromiscOperation) &&		    dev == dsr_dev && dnode->slave_dev)			dev_set_promiscuity(dnode->slave_dev, +1);		break;	case NETDEV_UNREGISTER:		DEBUG("Netdev unregister %s\n", dev->name);				dsr_node_lock(dnode);		if (dev == dnode->slave_dev) {			dev_remove_pack(&dsr_packet_type);			dsr_packet_type.func = NULL;			slave_change = 1;			dev_put(dev);			dnode->slave_dev = NULL;		}		dsr_node_unlock(dnode);		if (slave_change)			DEBUG("DSR slave interface %s unregisterd\n",			      dev->name);		break;	case NETDEV_DOWN:		DEBUG("Netdev down %s\n", dev->name);		if (dev == dsr_dev) {			if (dnode->slave_dev && ConfVal(PromiscOperation))				dev_set_promiscuity(dnode->slave_dev, -1);			dsr_node_lock(dnode);                        if (dnode->slave_indev) {                                dnode->slave_indev->cnf.rp_filter = rp_filter;                                dnode->slave_indev->cnf.forwarding = forwarding;                                in_dev_put(dnode->slave_indev);                                dnode->slave_indev = NULL;                        }                        dsr_node_unlock(dnode);		} else if (dev == dnode->slave_dev && dnode->slave_indev) {			dsr_node_lock(dnode);			dnode->slave_indev->cnf.rp_filter = rp_filter;			dnode->slave_indev->cnf.forwarding = forwarding;                                in_dev_put(dnode->slave_indev);			dnode->slave_indev = NULL;                        dsr_node_unlock(dnode);		} 		break;	default:		break;	};	return NOTIFY_DONE;}static int dsr_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);static struct net_device_stats *dsr_dev_get_stats(struct net_device *dev);static int dsr_dev_set_address(struct net_device *dev, void *p){	struct sockaddr *sa = p;	if (!is_valid_ether_addr(sa->sa_data))		return -EADDRNOTAVAIL;	memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);	return 0;}/* fake multicast ability */static void set_multicast_list(struct net_device *dev){}#ifdef CONFIG_NET_FASTROUTEstatic int dsr_dev_accept_fastpath(struct net_device *dev, 				   struct dst_entry *dst){	return -1;}#endifstatic int dsr_dev_open(struct net_device *dev){	netif_start_queue(dev);	return 0;}static int dsr_dev_stop(struct net_device *dev){	netif_stop_queue(dev);	return 0;}static void dsr_dev_uninit(struct net_device *dev){	struct dsr_node *dnode = (struct dsr_node *)dev->priv;	dsr_node_lock(dnode);		if (dnode->slave_dev)		dev_put(dnode->slave_dev);	if (dnode->slave_indev)		in_dev_put(dnode->slave_indev);	dsr_node_unlock(dnode);	if (dsr_packet_type.func) {

⌨️ 快捷键说明

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