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

📄 fib_semantics.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if (fi->fib_prefsrc) {		if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||		    memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))			if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)				goto err_inval;	}link_it:	if ((ofi = fib_find_info(fi)) != NULL) {		kfree(fi);		ofi->fib_refcnt++;		return ofi;	}	fi->fib_refcnt++;	fi->fib_next = fib_info_list;	fi->fib_prev = NULL;	if (fib_info_list)		fib_info_list->fib_prev = fi;	fib_info_list = fi;	return fi;err_inval:	err = -EINVAL;failure:        *errp = err;        if (fi)		kfree(fi);	return NULL;}int fib_semantic_match(int type, struct fib_info *fi, const struct rt_key *key, struct fib_result *res){	int err = fib_props[type].error;	if (err == 0) {		if (fi->fib_flags&RTNH_F_DEAD)			return 1;		res->fi = fi;		switch (type) {#ifdef CONFIG_IP_ROUTE_NAT		case RTN_NAT:			FIB_RES_RESET(*res);			return 0;#endif		case RTN_UNICAST:		case RTN_LOCAL:		case RTN_BROADCAST:		case RTN_ANYCAST:		case RTN_MULTICAST:			for_nexthops(fi) {				if (nh->nh_flags&RTNH_F_DEAD)					continue;				if (!key->oif || key->oif == nh->nh_oif)					break;			}#ifdef CONFIG_IP_ROUTE_MULTIPATH			if (nhsel < fi->fib_nhs) {				res->nh_sel = nhsel;				return 0;			}#else			if (nhsel < 1)				return 0;#endif			endfor_nexthops(fi);			return 1;		default:			printk(KERN_DEBUG "impossible 102\n");			return -EINVAL;		}	}	return err;}/* Find appropriate source address to this destination */u32 __fib_res_prefsrc(struct fib_result *res){	return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);}#ifdef CONFIG_RTNETLINKintfib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,	      u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,	      struct fib_info *fi){	struct rtmsg *rtm;	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));	rtm = NLMSG_DATA(nlh);	rtm->rtm_family = AF_INET;	rtm->rtm_dst_len = dst_len;	rtm->rtm_src_len = 0;	rtm->rtm_tos = tos;	rtm->rtm_table = tb_id;	rtm->rtm_type = type;	rtm->rtm_flags = fi->fib_flags;	rtm->rtm_scope = scope;	if (rtm->rtm_dst_len)		RTA_PUT(skb, RTA_DST, 4, dst);	rtm->rtm_protocol = fi->fib_protocol;	if (fi->fib_priority)		RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);#ifdef CONFIG_NET_CLS_ROUTE	if (fi->fib_nh[0].nh_tclassid)		RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);#endif	if (fi->fib_mtu || fi->fib_window || fi->fib_rtt) {		int i;		struct rtattr *mx = (struct rtattr *)skb->tail;		RTA_PUT(skb, RTA_METRICS, 0, NULL);		for (i=0; i<FIB_MAX_METRICS; i++) {			if (fi->fib_metrics[i])				RTA_PUT(skb, i+1, sizeof(unsigned), fi->fib_metrics + i);		}		mx->rta_len = skb->tail - (u8*)mx;	}	if (fi->fib_prefsrc)		RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc);	if (fi->fib_nhs == 1) {		if (fi->fib_nh->nh_gw)			RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw);		if (fi->fib_nh->nh_oif)			RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);	}#ifdef CONFIG_IP_ROUTE_MULTIPATH	if (fi->fib_nhs > 1) {		struct rtnexthop *nhp;		struct rtattr *mp_head;		if (skb_tailroom(skb) <= RTA_SPACE(0))			goto rtattr_failure;		mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0));		for_nexthops(fi) {			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))				goto rtattr_failure;			nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));			nhp->rtnh_flags = nh->nh_flags & 0xFF;			nhp->rtnh_hops = nh->nh_weight-1;			nhp->rtnh_ifindex = nh->nh_oif;			if (nh->nh_gw)				RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw);			nhp->rtnh_len = skb->tail - (unsigned char*)nhp;		} endfor_nexthops(fi);		mp_head->rta_type = RTA_MULTIPATH;		mp_head->rta_len = skb->tail - (u8*)mp_head;	}#endif	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}#endif /* CONFIG_RTNETLINK */#ifndef CONFIG_IP_NOSIOCRTintfib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,		    struct kern_rta *rta, struct rtentry *r){	int    plen;	u32    *ptr;	memset(rtm, 0, sizeof(*rtm));	memset(rta, 0, sizeof(*rta));	if (r->rt_dst.sa_family != AF_INET)		return -EAFNOSUPPORT;	/* Check mask for validity:	   a) it must be contiguous.	   b) destination must have all host bits clear.	   c) if application forgot to set correct family (AF_INET),	      reject request unless it is absolutely clear i.e.	      both family and mask are zero.	 */	plen = 32;	ptr = &((struct sockaddr_in*)&r->rt_dst)->sin_addr.s_addr;	if (!(r->rt_flags&RTF_HOST)) {		u32 mask = ((struct sockaddr_in*)&r->rt_genmask)->sin_addr.s_addr;		if (r->rt_genmask.sa_family != AF_INET) {			if (mask || r->rt_genmask.sa_family)				return -EAFNOSUPPORT;		}		if (bad_mask(mask, *ptr))			return -EINVAL;		plen = inet_mask_len(mask);	}	nl->nlmsg_flags = NLM_F_REQUEST;	nl->nlmsg_pid = 0;	nl->nlmsg_seq = 0;	nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));	if (cmd == SIOCDELRT) {		nl->nlmsg_type = RTM_DELROUTE;		nl->nlmsg_flags = 0;	} else {		nl->nlmsg_type = RTM_NEWROUTE;		nl->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;		rtm->rtm_protocol = RTPROT_BOOT;	}	rtm->rtm_dst_len = plen;	rta->rta_dst = ptr;	if (r->rt_metric) {		*(u32*)&r->rt_pad3 = r->rt_metric - 1;		rta->rta_priority = (u32*)&r->rt_pad3;	}	if (r->rt_flags&RTF_REJECT) {		rtm->rtm_scope = RT_SCOPE_HOST;		rtm->rtm_type = RTN_UNREACHABLE;		return 0;	}	rtm->rtm_scope = RT_SCOPE_NOWHERE;	rtm->rtm_type = RTN_UNICAST;	if (r->rt_dev) {#ifdef CONFIG_IP_ALIAS		char *colon;#endif		struct device *dev;		char   devname[IFNAMSIZ];		if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1))			return -EFAULT;		devname[IFNAMSIZ-1] = 0;#ifdef CONFIG_IP_ALIAS		colon = strchr(devname, ':');		if (colon)			*colon = 0;#endif		dev = dev_get(devname);		if (!dev)			return -ENODEV;		rta->rta_oif = &dev->ifindex;#ifdef CONFIG_IP_ALIAS		if (colon) {			struct in_ifaddr *ifa;			struct in_device *in_dev = dev->ip_ptr;			if (!in_dev)				return -ENODEV;			*colon = ':';			for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)				if (strcmp(ifa->ifa_label, devname) == 0)					break;			if (ifa == NULL)				return -ENODEV;			rta->rta_prefsrc = &ifa->ifa_local;		}#endif	}	ptr = &((struct sockaddr_in*)&r->rt_gateway)->sin_addr.s_addr;	if (r->rt_gateway.sa_family == AF_INET && *ptr) {		rta->rta_gw = ptr;		if (r->rt_flags&RTF_GATEWAY && inet_addr_type(*ptr) == RTN_UNICAST)			rtm->rtm_scope = RT_SCOPE_UNIVERSE;	}	if (cmd == SIOCDELRT)		return 0;	if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL)		return -EINVAL;	if (rtm->rtm_scope == RT_SCOPE_NOWHERE)		rtm->rtm_scope = RT_SCOPE_LINK;	if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) {		struct rtattr *rec;		struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL);		if (mx == NULL)			return -ENOMEM;		rta->rta_mx = mx;		mx->rta_type = RTA_METRICS;		mx->rta_len  = RTA_LENGTH(0);		if (r->rt_flags&RTF_MTU) {			rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));			rec->rta_type = RTAX_MTU;			rec->rta_len = RTA_LENGTH(4);			mx->rta_len += RTA_LENGTH(4);			*(u32*)RTA_DATA(rec) = r->rt_mtu;		}		if (r->rt_flags&RTF_WINDOW) {			rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));			rec->rta_type = RTAX_WINDOW;			rec->rta_len = RTA_LENGTH(4);			mx->rta_len += RTA_LENGTH(4);			*(u32*)RTA_DATA(rec) = r->rt_window;		}		if (r->rt_flags&RTF_IRTT) {			rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));			rec->rta_type = RTAX_RTT;			rec->rta_len = RTA_LENGTH(4);			mx->rta_len += RTA_LENGTH(4);			*(u32*)RTA_DATA(rec) = r->rt_irtt;		}	}	return 0;}#endif/*   Update FIB if:   - local address disappeared -> we must delete all the entries     referring to it.   - device went down -> we must shutdown all nexthops going via it. */int fib_sync_down(u32 local, struct device *dev, int force){	int ret = 0;	int scope = RT_SCOPE_NOWHERE;		if (force)		scope = -1;	for_fib_info() {		if (local && fi->fib_prefsrc == local) {			fi->fib_flags |= RTNH_F_DEAD;			ret++;		} else if (dev && fi->fib_nhs) {			int dead = 0;			change_nexthops(fi) {				if (nh->nh_flags&RTNH_F_DEAD)					dead++;				else if (nh->nh_dev == dev &&					 nh->nh_scope != scope) {					nh->nh_flags |= RTNH_F_DEAD;#ifdef CONFIG_IP_ROUTE_MULTIPATH					fi->fib_power -= nh->nh_power;					nh->nh_power = 0;#endif					dead++;				}			} endfor_nexthops(fi)			if (dead == fi->fib_nhs) {				fi->fib_flags |= RTNH_F_DEAD;				ret++;			}		}	} endfor_fib_info();	return ret;}#ifdef CONFIG_IP_ROUTE_MULTIPATH/*   Dead device goes up. We wake up dead nexthops.   It takes sense only on multipath routes. */int fib_sync_up(struct device *dev){	int ret = 0;	if (!(dev->flags&IFF_UP))		return 0;	for_fib_info() {		int alive = 0;		change_nexthops(fi) {			if (!(nh->nh_flags&RTNH_F_DEAD)) {				alive++;				continue;			}			if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))				continue;			if (nh->nh_dev != dev || dev->ip_ptr == NULL)				continue;			alive++;			nh->nh_power = 0;			nh->nh_flags &= ~RTNH_F_DEAD;		} endfor_nexthops(fi)		if (alive == fi->fib_nhs) {			fi->fib_flags &= ~RTNH_F_DEAD;			ret++;		}	} endfor_fib_info();	return ret;}/*   The algorithm is suboptimal, but it provides really   fair weighted route distribution. */void fib_select_multipath(const struct rt_key *key, struct fib_result *res){	struct fib_info *fi = res->fi;	int w;	if (fi->fib_power <= 0) {		int power = 0;		change_nexthops(fi) {			if (!(nh->nh_flags&RTNH_F_DEAD)) {				power += nh->nh_weight;				nh->nh_power = nh->nh_weight;			}		} endfor_nexthops(fi);		fi->fib_power = power;#if 1		if (power <= 0) {			printk(KERN_CRIT "impossible 777\n");			return;		}#endif	}	/* w should be random number [0..fi->fib_power-1],	   it is pretty bad approximation.	 */	w = jiffies % fi->fib_power;	change_nexthops(fi) {		if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {			if ((w -= nh->nh_power) <= 0) {				nh->nh_power--;				fi->fib_power--;				res->nh_sel = nhsel;				return;			}		}	} endfor_nexthops(fi);#if 1	printk(KERN_CRIT "impossible 888\n");#endif	return;}#endif#ifdef CONFIG_PROC_FSstatic unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi){	static unsigned type2flags[RTN_MAX+1] = {		0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0	};	unsigned flags = type2flags[type];	if (fi && fi->fib_nh->nh_gw)		flags |= RTF_GATEWAY;	if (mask == 0xFFFFFFFF)		flags |= RTF_HOST;	if (!dead)		flags |= RTF_UP;	return flags;}void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer){	int len;	unsigned flags = fib_flag_trans(type, dead, mask, fi);	if (fi) {		len = sprintf(buffer, "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",			      fi->fib_dev ? fi->fib_dev->name : "*", prefix,			      fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,			      mask, fi->fib_mtu, fi->fib_window, fi->fib_rtt);	} else {		len = sprintf(buffer, "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",			      prefix, 0,			      flags, 0, 0, 0,			      mask, 0, 0, 0);	}	memset(buffer+len, ' ', 127-len);	buffer[127] = '\n';}#endif

⌨️ 快捷键说明

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