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

📄 ddp.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 4 页
字号:
	spin_lock_bh(&atalk_iface_lock);	for (iface = atalk_iface_list; iface; iface = iface->next) {		if ((node == ATADDR_BCAST ||		     node == ATADDR_ANYNODE ||		     iface->address.s_node == node) &&		    iface->address.s_net == net &&		    !(iface->status & ATIF_PROBE))			break;		/* XXXX.0 -- net.0 returns the iface associated with net */		if (node == ATADDR_ANYNODE && net != ATADDR_ANYNET &&		    ntohs(iface->nets.nr_firstnet) <= ntohs(net) &&		    ntohs(net) <= ntohs(iface->nets.nr_lastnet))		        break;	}	spin_unlock_bh(&atalk_iface_lock);	return iface;}/* * Find a route for an AppleTalk packet. This ought to get cached in * the socket (later on...). We know about host routes and the fact * that a route must be direct to broadcast. */static struct atalk_route *atrtr_find(struct at_addr *target){	/*	 * we must search through all routes unless we find a 	 * host route, because some host routes might overlap	 * network routes	 */	struct atalk_route *net_route = NULL;	struct atalk_route *r;		read_lock_bh(&atalk_router_lock);	for (r = atalk_router_list; r; r = r->next) {		if (!(r->flags & RTF_UP))			continue;		if (r->target.s_net == target->s_net) {			if (r->flags & RTF_HOST) {				/*				 * if this host route is for the target,				 * the we're done				 */				if (r->target.s_node == target->s_node)					goto out;			} else				/*				 * this route will work if there isn't a				 * direct host route, so cache it				 */				net_route = r;		}	}		/* 	 * if we found a network route but not a direct host	 * route, then return it	 */	if (net_route)		r = net_route;	else if (atrtr_default.dev)		r = &atrtr_default;	else /* No route can be found */		r = NULL;out:	read_unlock_bh(&atalk_router_lock);	return r;}/* * Given an AppleTalk network, find the device to use. This can be * a simple lookup. */struct net_device *atrtr_get_dev(struct at_addr *sa){	struct atalk_route *atr = atrtr_find(sa);	return atr ? atr->dev : NULL;}/* Set up a default router */static void atrtr_set_default(struct net_device *dev){	atrtr_default.dev = dev;	atrtr_default.flags = RTF_UP;	atrtr_default.gateway.s_net = htons(0);	atrtr_default.gateway.s_node = 0;}/* * Add a router. Basically make sure it looks valid and stuff the * entry in the list. While it uses netranges we always set them to one * entry to work like netatalk. */static int atrtr_create(struct rtentry *r, struct net_device *devhint){	struct sockaddr_at *ta = (struct sockaddr_at *)&r->rt_dst;	struct sockaddr_at *ga = (struct sockaddr_at *)&r->rt_gateway;	struct atalk_route *rt;	struct atalk_iface *iface, *riface;	int retval;	/*	 * Fixme: Raise/Lower a routing change semaphore for these	 * operations.	 */	/* Validate the request */	if (ta->sat_family != AF_APPLETALK)		return -EINVAL;	if (!devhint && ga->sat_family != AF_APPLETALK)		return -EINVAL;	/* Now walk the routing table and make our decisions */	write_lock_bh(&atalk_router_lock);	for (rt = atalk_router_list; rt; rt = rt->next) {		if (r->rt_flags != rt->flags)			continue;		if (ta->sat_addr.s_net == rt->target.s_net) {			if (!(rt->flags & RTF_HOST))				break;			if (ta->sat_addr.s_node == rt->target.s_node)				break;		}	}	if (!devhint) {		riface = NULL;		spin_lock_bh(&atalk_iface_lock);		for (iface = atalk_iface_list; iface; iface = iface->next) {			if (!riface &&			    ntohs(ga->sat_addr.s_net) >=			    		ntohs(iface->nets.nr_firstnet) &&			    ntohs(ga->sat_addr.s_net) <=			    		ntohs(iface->nets.nr_lastnet))				riface = iface;			if (ga->sat_addr.s_net == iface->address.s_net &&			    ga->sat_addr.s_node == iface->address.s_node)				riface = iface;		}				spin_unlock_bh(&atalk_iface_lock);		retval = -ENETUNREACH;		if (!riface)			goto out;		devhint = riface->dev;	}	if (!rt) {		rt = kmalloc(sizeof(struct atalk_route), GFP_ATOMIC);		retval = -ENOBUFS;		if (!rt)			goto out;		rt->next = atalk_router_list;		atalk_router_list = rt;	}	/* Fill in the routing entry */	rt->target  = ta->sat_addr;	rt->dev     = devhint;	rt->flags   = r->rt_flags;	rt->gateway = ga->sat_addr;	retval = 0;out:	write_unlock_bh(&atalk_router_lock);	return retval;}/* Delete a route. Find it and discard it */static int atrtr_delete(struct at_addr * addr){	struct atalk_route **r = &atalk_router_list;	int retval = 0;	struct atalk_route *tmp;	write_lock_bh(&atalk_router_lock);	while ((tmp = *r) != NULL) {		if (tmp->target.s_net == addr->s_net &&		    (!(tmp->flags&RTF_GATEWAY) ||		     tmp->target.s_node == addr->s_node)) {			*r = tmp->next;			kfree(tmp);			goto out;		}		r = &tmp->next;	}	retval = -ENOENT;out:	write_unlock_bh(&atalk_router_lock);	return retval;}/* * Called when a device is downed. Just throw away any routes * via it. */void atrtr_device_down(struct net_device *dev){	struct atalk_route **r = &atalk_router_list;	struct atalk_route *tmp;	write_lock_bh(&atalk_router_lock);	while ((tmp = *r) != NULL) {		if (tmp->dev == dev) {			*r = tmp->next;			kfree(tmp);		} else			r = &tmp->next;	}	write_unlock_bh(&atalk_router_lock);	if (atrtr_default.dev == dev)		atrtr_set_default(NULL);}/* Actually down the interface */static inline void atalk_dev_down(struct net_device *dev){	atrtr_device_down(dev);	/* Remove all routes for the device */	aarp_device_down(dev);	/* Remove AARP entries for the device */	atif_drop_device(dev);	/* Remove the device */}/* * A device event has occurred. Watch for devices going down and * delete our use of them (iface and route). */static int ddp_device_event(struct notifier_block *this, unsigned long event,				void *ptr){	if (event == NETDEV_DOWN)		/* Discard any use of this */	        atalk_dev_down((struct net_device *) ptr);	return NOTIFY_DONE;}/* ioctl calls. Shouldn't even need touching *//* Device configuration ioctl calls */static int atif_ioctl(int cmd, void *arg){	static char aarp_mcast[6] = {0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF};	struct ifreq atreq;	struct netrange *nr;	struct sockaddr_at *sa;	struct net_device *dev;	struct atalk_iface *atif;	int ct;	int limit;	struct rtentry rtdef;	int add_route;	if (copy_from_user(&atreq, arg, sizeof(atreq)))		return -EFAULT;	dev = __dev_get_by_name(atreq.ifr_name);	if (!dev)		return -ENODEV;	sa = (struct sockaddr_at*) &atreq.ifr_addr;	atif = atalk_find_dev(dev);	switch (cmd) {		case SIOCSIFADDR:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			if (sa->sat_family != AF_APPLETALK)				return -EINVAL;			if (dev->type != ARPHRD_ETHER &&			    dev->type != ARPHRD_LOOPBACK &&			    dev->type != ARPHRD_LOCALTLK &&			    dev->type != ARPHRD_PPP)				return -EPROTONOSUPPORT;			nr = (struct netrange *) &sa->sat_zero[0];			add_route = 1;			/*			 * if this is a point-to-point iface, and we already			 * have an iface for this AppleTalk address, then we			 * should not add a route			 */			if ((dev->flags & IFF_POINTOPOINT) &&			    atalk_find_interface(sa->sat_addr.s_net,				    		 sa->sat_addr.s_node)) {				printk(KERN_DEBUG "AppleTalk: point-to-point "						  "interface added with "						  "existing address\n");				add_route = 0;			}						/*			 * Phase 1 is fine on LocalTalk but we don't do			 * EtherTalk phase 1. Anyone wanting to add it go ahead.			 */			if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)				return -EPROTONOSUPPORT;			if (sa->sat_addr.s_node == ATADDR_BCAST ||			    sa->sat_addr.s_node == 254)				return -EINVAL;			if (atif) {				/* Already setting address */				if (atif->status & ATIF_PROBE)					return -EBUSY;				atif->address.s_net  = sa->sat_addr.s_net;				atif->address.s_node = sa->sat_addr.s_node;				atrtr_device_down(dev);	/* Flush old routes */			} else {				atif = atif_add_device(dev, &sa->sat_addr);				if (!atif)					return -ENOMEM;			}			atif->nets = *nr;			/*			 * Check if the chosen address is used. If so we			 * error and atalkd will try another.			 */			if (!(dev->flags & IFF_LOOPBACK) &&			    !(dev->flags & IFF_POINTOPOINT) &&			    atif_probe_device(atif) < 0) {				atif_drop_device(dev);				return -EADDRINUSE;			}			/* Hey it worked - add the direct routes */			sa = (struct sockaddr_at *) &rtdef.rt_gateway;			sa->sat_family = AF_APPLETALK;			sa->sat_addr.s_net  = atif->address.s_net;			sa->sat_addr.s_node = atif->address.s_node;			sa = (struct sockaddr_at *) &rtdef.rt_dst;			rtdef.rt_flags = RTF_UP;			sa->sat_family = AF_APPLETALK;			sa->sat_addr.s_node = ATADDR_ANYNODE;			if (dev->flags & IFF_LOOPBACK ||			    dev->flags & IFF_POINTOPOINT)				rtdef.rt_flags |= RTF_HOST;			/* Routerless initial state */			if (nr->nr_firstnet == htons(0) &&			    nr->nr_lastnet == htons(0xFFFE)) {				sa->sat_addr.s_net = atif->address.s_net;				atrtr_create(&rtdef, dev);				atrtr_set_default(dev);			} else {				limit = ntohs(nr->nr_lastnet);				if (limit - ntohs(nr->nr_firstnet) > 4096) {					printk(KERN_WARNING "Too many routes/"							    "iface.\n");					return -EINVAL;				}				if (add_route)					for (ct = ntohs(nr->nr_firstnet);					     ct <= limit; ct++) {						sa->sat_addr.s_net = htons(ct);						atrtr_create(&rtdef, dev);					}			}			dev_mc_add(dev, aarp_mcast, 6, 1);			return 0;		case SIOCGIFADDR:			if (!atif)				return -EADDRNOTAVAIL;			sa->sat_family = AF_APPLETALK;			sa->sat_addr = atif->address;			break;		case SIOCGIFBRDADDR:			if (!atif)				return -EADDRNOTAVAIL;			sa->sat_family = AF_APPLETALK;			sa->sat_addr.s_net = atif->address.s_net;			sa->sat_addr.s_node = ATADDR_BCAST;			break;	        case SIOCATALKDIFADDR:	        case SIOCDIFADDR:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			if (sa->sat_family != AF_APPLETALK)				return -EINVAL;			atalk_dev_down(dev);			break;					case SIOCSARP:			if (!capable(CAP_NET_ADMIN))                                return -EPERM;                        if (sa->sat_family != AF_APPLETALK)                                return -EINVAL;                        if (!atif)                                return -EADDRNOTAVAIL;                        /*                         * for now, we only support proxy AARP on ELAP;                         * we should be able to do it for LocalTalk, too.                         */                        if (dev->type != ARPHRD_ETHER)                                return -EPROTONOSUPPORT;                        /*                         * atif points to the current interface on this network;                         * we aren't concerned about its current status (at			 * least for now), but it has all the settings about			 * the network we're going to probe. Consequently, it			 * must exist.                         */                        if (!atif)                                return -EADDRNOTAVAIL;                        nr = (struct netrange *) &(atif->nets);                        /*                         * Phase 1 is fine on Localtalk but we don't do                         * Ethertalk phase 1. Anyone wanting to add it go ahead.                         */                        if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)                                return -EPROTONOSUPPORT;                        if (sa->sat_addr.s_node == ATADDR_BCAST ||			    sa->sat_addr.s_node == 254)                                return -EINVAL;                        /*                         * Check if the chosen address is used. If so we                         * error and ATCP will try another.                         */                      	if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)                      		return -EADDRINUSE;                      				/*                         * We now have an address on the local network, and			 * the AARP code will defend it for us until we take it			 * down. We don't set up any routes right now, because			 * ATCP will install them manually via SIOCADDRT.                         */                        break;                case SIOCDARP:                        if (!capable(CAP_NET_ADMIN))                                return -EPERM;                        if (sa->sat_family != AF_APPLETALK)                                return -EINVAL;                        if (!atif)                                return -EADDRNOTAVAIL;                        /* give to aarp module to remove proxy entry */                        aarp_proxy_remove(atif->dev, &(sa->sat_addr));                        return 0;	}	return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0;}/* Routing ioctl() calls */static int atrtr_ioctl(unsigned int cmd, void *arg){	struct net_device *dev = NULL;	struct rtentry rt;	if (copy_from_user(&rt, arg, sizeof(rt)))		return -EFAULT;	switch (cmd) {		case SIOCDELRT:			if (rt.rt_dst.sa_family != AF_APPLETALK)				return -EINVAL;			return atrtr_delete(&((struct sockaddr_at *)						&rt.rt_dst)->sat_addr);		case SIOCADDRT:			/* FIXME: the name of the device is still in user			 * space, isn't it? */			if (rt.rt_dev) {				dev = __dev_get_by_name(rt.rt_dev);				if (!dev)					return -ENODEV;			}						return atrtr_create(&rt, dev);	}	return -EINVAL;}/* Called from proc fs - just make it print the ifaces neatly */static int atalk_if_get_info(char *buffer, char **start, off_t offset,			     int length){	off_t pos = 0;	off_t begin = 0;	struct atalk_iface *iface;	int len = sprintf(buffer, "Interface	  Address   "				  "Networks   Status\n");	spin_lock_bh(&atalk_iface_lock);	for (iface = atalk_iface_list; iface; iface = iface->next) {		len += sprintf(buffer+len,"%-16s %04X:%02X  %04X-%04X  %d\n",

⌨️ 快捷键说明

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