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

📄 nr_route.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return 0;}/* *	Decrement the obsolescence count by one. If a route is reduced to a *	count of zero, remove it. Also remove any unlocked neighbours with *	zero nodes routing via it. */static int nr_dec_obs(void){	struct nr_neigh *nr_neigh;	struct nr_node  *s, *nr_node;	int i;	nr_node = nr_node_list;	while (nr_node != NULL) {		s       = nr_node;		nr_node = nr_node->next;		for (i = 0; i < s->count; i++) {			switch (s->routes[i].obs_count) {			case 0:		/* A locked entry */				break;			case 1:		/* From 1 -> 0 */				nr_neigh = s->routes[i].neighbour;				nr_neigh->count--;				if (nr_neigh->count == 0 && !nr_neigh->locked)					nr_remove_neigh(nr_neigh);				s->count--;				switch (i) {					case 0:						s->routes[0] = s->routes[1];					case 1:						s->routes[1] = s->routes[2];					case 2:						break;				}				break;			default:				s->routes[i].obs_count--;				break;			}		}		if (s->count <= 0)			nr_remove_node(s);	}	return 0;}/* *	A device has been removed. Remove its routes and neighbours. */void nr_rt_device_down(struct net_device *dev){	struct nr_neigh *s, *nr_neigh = nr_neigh_list;	struct nr_node  *t, *nr_node;	int i;	while (nr_neigh != NULL) {		s        = nr_neigh;		nr_neigh = nr_neigh->next;		if (s->dev == dev) {			nr_node = nr_node_list;			while (nr_node != NULL) {				t       = nr_node;				nr_node = nr_node->next;				for (i = 0; i < t->count; i++) {					if (t->routes[i].neighbour == s) {						t->count--;						switch (i) {							case 0:								t->routes[0] = t->routes[1];							case 1:								t->routes[1] = t->routes[2];							case 2:								break;						}					}				}				if (t->count <= 0)					nr_remove_node(t);			}			nr_remove_neigh(s);		}	}}/* *	Check that the device given is a valid AX.25 interface that is "up". *	Or a valid ethernet interface with an AX.25 callsign binding. */static struct net_device *nr_ax25_dev_get(char *devname){	struct net_device *dev;	if ((dev = dev_get_by_name(devname)) == NULL)		return NULL;	if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)		return dev;	dev_put(dev);	return NULL;}/* *	Find the first active NET/ROM device, usually "nr0". */struct net_device *nr_dev_first(void){	struct net_device *dev, *first = NULL;	read_lock(&dev_base_lock);	for (dev = dev_base; dev != NULL; dev = dev->next) {		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)				first = dev;	}	read_unlock(&dev_base_lock);	return first;}/* *	Find the NET/ROM device for the given callsign. */struct net_device *nr_dev_get(ax25_address *addr){	struct net_device *dev;	read_lock(&dev_base_lock);	for (dev = dev_base; dev != NULL; dev = dev->next) {		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {			dev_hold(dev);			goto out;		}	}out:	read_unlock(&dev_base_lock);	return dev;}static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters){	static ax25_digi ax25_digi;	int i;	if (ndigis == 0)		return NULL;	for (i = 0; i < ndigis; i++) {		ax25_digi.calls[i]    = digipeaters[i];		ax25_digi.repeated[i] = 0;	}	ax25_digi.ndigi      = ndigis;	ax25_digi.lastrepeat = -1;	return &ax25_digi;}/* *	Handle the ioctls that control the routing functions. */int nr_rt_ioctl(unsigned int cmd, void *arg){	struct nr_route_struct nr_route;	struct net_device *dev;	switch (cmd) {		case SIOCADDRT:			if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))				return -EFAULT;			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)				return -EINVAL;			if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS)				return -EINVAL;			switch (nr_route.type) {				case NETROM_NODE:					return nr_add_node(&nr_route.callsign,						nr_route.mnemonic,						&nr_route.neighbour,						nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),						dev, nr_route.quality,						nr_route.obs_count);				case NETROM_NEIGH:					return nr_add_neigh(&nr_route.callsign,						nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),						dev, nr_route.quality);				default:					return -EINVAL;			}		case SIOCDELRT:			if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))				return -EFAULT;			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)				return -EINVAL;			switch (nr_route.type) {				case NETROM_NODE:					return nr_del_node(&nr_route.callsign,						&nr_route.neighbour, dev);				case NETROM_NEIGH:					return nr_del_neigh(&nr_route.callsign,						dev, nr_route.quality);				default:					return -EINVAL;			}		case SIOCNRDECOBS:			return nr_dec_obs();		default:			return -EINVAL;	}	return 0;}/* * 	A level 2 link has timed out, therefore it appears to be a poor link, *	then don't use that neighbour until it is reset. */void nr_link_failed(ax25_cb *ax25, int reason){	struct nr_neigh *nr_neigh;	struct nr_node  *nr_node;	for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)		if (nr_neigh->ax25 == ax25)			break;	if (nr_neigh == NULL) return;	nr_neigh->ax25 = NULL;	if (++nr_neigh->failed < sysctl_netrom_link_fails_count) return;	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)		if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)			nr_node->which++;}/* *	Route a frame to an appropriate AX.25 connection. A NULL ax25_cb *	indicates an internally generated frame. */int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25){	ax25_address *nr_src, *nr_dest;	struct nr_neigh *nr_neigh;	struct nr_node  *nr_node;	struct net_device *dev;	unsigned char *dptr;	nr_src  = (ax25_address *)(skb->data + 0);	nr_dest = (ax25_address *)(skb->data + 7);	if (ax25 != NULL)		nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,			    ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser);	if ((dev = nr_dev_get(nr_dest)) != NULL) {	/* Its for me */		if (ax25 == NULL)			/* Its from me */			return nr_loopback_queue(skb);		else			return nr_rx_frame(skb, dev);	}	if (!sysctl_netrom_routing_control && ax25 != NULL)		return 0;	/* Its Time-To-Live has expired */	if (--skb->data[14] == 0)		return 0;	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)		if (ax25cmp(nr_dest, &nr_node->callsign) == 0)			break;	if (nr_node == NULL || nr_node->which >= nr_node->count)		return 0;	nr_neigh = nr_node->routes[nr_node->which].neighbour;	if ((dev = nr_dev_first()) == NULL)		return 0;	dptr  = skb_push(skb, 1);	*dptr = AX25_P_NETROM;	nr_neigh->ax25 = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);	return (nr_neigh->ax25 != NULL);}int nr_nodes_get_info(char *buffer, char **start, off_t offset, int length){	struct nr_node *nr_node;	int len     = 0;	off_t pos   = 0;	off_t begin = 0;	int i;	cli();	len += sprintf(buffer, "callsign  mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) {		len += sprintf(buffer + len, "%-9s %-7s  %d %d",			ax2asc(&nr_node->callsign),			(nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,			nr_node->which + 1,			nr_node->count);					for (i = 0; i < nr_node->count; i++) {			len += sprintf(buffer + len, "  %3d   %d %05d",				nr_node->routes[i].quality,				nr_node->routes[i].obs_count,				nr_node->routes[i].neighbour->number);		}		len += sprintf(buffer + len, "\n");		pos = begin + len;		if (pos < offset) {			len   = 0;			begin = pos;		}		if (pos > offset + length)			break;	}	sti();	*start = buffer + (offset - begin);	len   -= (offset - begin);	if (len > length) len = length;	return len;} int nr_neigh_get_info(char *buffer, char **start, off_t offset, int length){	struct nr_neigh *nr_neigh;	int len     = 0;	off_t pos   = 0;	off_t begin = 0;	int i;	cli();	len += sprintf(buffer, "addr  callsign  dev  qual lock count failed digipeaters\n");	for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) {		len += sprintf(buffer + len, "%05d %-9s %-4s  %3d    %d   %3d    %3d",			nr_neigh->number,			ax2asc(&nr_neigh->callsign),			nr_neigh->dev ? nr_neigh->dev->name : "???",			nr_neigh->quality,			nr_neigh->locked,			nr_neigh->count,			nr_neigh->failed);		if (nr_neigh->digipeat != NULL) {			for (i = 0; i < nr_neigh->digipeat->ndigi; i++)				len += sprintf(buffer + len, " %s", ax2asc(&nr_neigh->digipeat->calls[i]));		}		len += sprintf(buffer + len, "\n");		pos = begin + len;		if (pos < offset) {			len   = 0;			begin = pos;		}		if (pos > offset + length)			break;	}	sti();	*start = buffer + (offset - begin);	len   -= (offset - begin);	if (len > length) len = length;	return len;} /* *	Free all memory associated with the nodes and routes lists. */void __exit nr_rt_free(void){	struct nr_neigh *s, *nr_neigh = nr_neigh_list;	struct nr_node  *t, *nr_node  = nr_node_list;	while (nr_node != NULL) {		t       = nr_node;		nr_node = nr_node->next;		nr_remove_node(t);	}	while (nr_neigh != NULL) {		s        = nr_neigh;		nr_neigh = nr_neigh->next;		nr_remove_neigh(s);	}}

⌨️ 快捷键说明

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