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

📄 addrconf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			} else {				if (hiscore.attrs & IPV6_SADDR_SCORE_OIF)					continue;			}			/* Rule 6: Prefer matching label */			if (hiscore.rule < 6) {				if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label)					hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;				hiscore.rule++;			}			if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) {				score.attrs |= IPV6_SADDR_SCORE_LABEL;				if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {					score.rule = 6;					goto record_it;				}			} else {				if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL)					continue;			}#ifdef CONFIG_IPV6_PRIVACY			/* Rule 7: Prefer public address			 * Note: prefer temprary address if use_tempaddr >= 2			 */			if (hiscore.rule < 7) {				if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^				    (ifa_result->idev->cnf.use_tempaddr >= 2))					hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY;				hiscore.rule++;			}			if ((!(ifa->flags & IFA_F_TEMPORARY)) ^			    (ifa->idev->cnf.use_tempaddr >= 2)) {				score.attrs |= IPV6_SADDR_SCORE_PRIVACY;				if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) {					score.rule = 7;					goto record_it;				}			} else {				if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)					continue;			}#else			if (hiscore.rule < 7)				hiscore.rule++;#endif			/* Rule 8: Use longest matching prefix */			if (hiscore.rule < 8) {				hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);				hiscore.rule++;			}			score.matchlen = ipv6_addr_diff(&ifa->addr, daddr);			if (score.matchlen > hiscore.matchlen) {				score.rule = 8;				goto record_it;			}#if 0			else if (score.matchlen < hiscore.matchlen)				continue;#endif			/* Final Rule: choose first available one */			continue;record_it:			if (ifa_result)				in6_ifa_put(ifa_result);			in6_ifa_hold(ifa);			ifa_result = ifa;			hiscore = score;		}		read_unlock_bh(&idev->lock);	}	rcu_read_unlock();	read_unlock(&dev_base_lock);	if (!ifa_result)		return -EADDRNOTAVAIL;	ipv6_addr_copy(saddr, &ifa_result->addr);	in6_ifa_put(ifa_result);	return 0;}int ipv6_get_saddr(struct dst_entry *dst,		   struct in6_addr *daddr, struct in6_addr *saddr){	return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);}EXPORT_SYMBOL(ipv6_get_saddr);int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,		    unsigned char banned_flags){	struct inet6_dev *idev;	int err = -EADDRNOTAVAIL;	rcu_read_lock();	if ((idev = __in6_dev_get(dev)) != NULL) {		struct inet6_ifaddr *ifp;		read_lock_bh(&idev->lock);		for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {			if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) {				ipv6_addr_copy(addr, &ifp->addr);				err = 0;				break;			}		}		read_unlock_bh(&idev->lock);	}	rcu_read_unlock();	return err;}static int ipv6_count_addresses(struct inet6_dev *idev){	int cnt = 0;	struct inet6_ifaddr *ifp;	read_lock_bh(&idev->lock);	for (ifp=idev->addr_list; ifp; ifp=ifp->if_next)		cnt++;	read_unlock_bh(&idev->lock);	return cnt;}int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict){	struct inet6_ifaddr * ifp;	u8 hash = ipv6_addr_hash(addr);	read_lock_bh(&addrconf_hash_lock);	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {		if (ipv6_addr_equal(&ifp->addr, addr) &&		    !(ifp->flags&IFA_F_TENTATIVE)) {			if (dev == NULL || ifp->idev->dev == dev ||			    !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))				break;		}	}	read_unlock_bh(&addrconf_hash_lock);	return ifp != NULL;}EXPORT_SYMBOL(ipv6_chk_addr);staticint ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev){	struct inet6_ifaddr * ifp;	u8 hash = ipv6_addr_hash(addr);	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {		if (ipv6_addr_equal(&ifp->addr, addr)) {			if (dev == NULL || ifp->idev->dev == dev)				break;		}	}	return ifp != NULL;}struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict){	struct inet6_ifaddr * ifp;	u8 hash = ipv6_addr_hash(addr);	read_lock_bh(&addrconf_hash_lock);	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {		if (ipv6_addr_equal(&ifp->addr, addr)) {			if (dev == NULL || ifp->idev->dev == dev ||			    !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {				in6_ifa_hold(ifp);				break;			}		}	}	read_unlock_bh(&addrconf_hash_lock);	return ifp;}int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2){	const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;	const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);	__be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;	__be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);	int sk_ipv6only = ipv6_only_sock(sk);	int sk2_ipv6only = inet_v6_ipv6only(sk2);	int addr_type = ipv6_addr_type(sk_rcv_saddr6);	int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;	if (!sk2_rcv_saddr && !sk_ipv6only)		return 1;	if (addr_type2 == IPV6_ADDR_ANY &&	    !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))		return 1;	if (addr_type == IPV6_ADDR_ANY &&	    !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))		return 1;	if (sk2_rcv_saddr6 &&	    ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))		return 1;	if (addr_type == IPV6_ADDR_MAPPED &&	    !sk2_ipv6only &&	    (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr))		return 1;	return 0;}/* Gets referenced address, destroys ifaddr */static void addrconf_dad_stop(struct inet6_ifaddr *ifp){	if (ifp->flags&IFA_F_PERMANENT) {		spin_lock_bh(&ifp->lock);		addrconf_del_timer(ifp);		ifp->flags |= IFA_F_TENTATIVE;		spin_unlock_bh(&ifp->lock);		in6_ifa_put(ifp);#ifdef CONFIG_IPV6_PRIVACY	} else if (ifp->flags&IFA_F_TEMPORARY) {		struct inet6_ifaddr *ifpub;		spin_lock_bh(&ifp->lock);		ifpub = ifp->ifpub;		if (ifpub) {			in6_ifa_hold(ifpub);			spin_unlock_bh(&ifp->lock);			ipv6_create_tempaddr(ifpub, ifp);			in6_ifa_put(ifpub);		} else {			spin_unlock_bh(&ifp->lock);		}		ipv6_del_addr(ifp);#endif	} else		ipv6_del_addr(ifp);}void addrconf_dad_failure(struct inet6_ifaddr *ifp){	if (net_ratelimit())		printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);	addrconf_dad_stop(ifp);}/* Join to solicited addr multicast group. */void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr){	struct in6_addr maddr;	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))		return;	addrconf_addr_solict_mult(addr, &maddr);	ipv6_dev_mc_inc(dev, &maddr);}void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr){	struct in6_addr maddr;	if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))		return;	addrconf_addr_solict_mult(addr, &maddr);	__ipv6_dev_mc_dec(idev, &maddr);}static void addrconf_join_anycast(struct inet6_ifaddr *ifp){	struct in6_addr addr;	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);	if (ipv6_addr_any(&addr))		return;	ipv6_dev_ac_inc(ifp->idev->dev, &addr);}static void addrconf_leave_anycast(struct inet6_ifaddr *ifp){	struct in6_addr addr;	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);	if (ipv6_addr_any(&addr))		return;	__ipv6_dev_ac_dec(ifp->idev, &addr);}static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev){	if (dev->addr_len != ETH_ALEN)		return -1;	memcpy(eui, dev->dev_addr, 3);	memcpy(eui + 5, dev->dev_addr + 3, 3);	/*	 * The zSeries OSA network cards can be shared among various	 * OS instances, but the OSA cards have only one MAC address.	 * This leads to duplicate address conflicts in conjunction	 * with IPv6 if more than one instance uses the same card.	 *	 * The driver for these cards can deliver a unique 16-bit	 * identifier for each instance sharing the same card.  It is	 * placed instead of 0xFFFE in the interface identifier.  The	 * "u" bit of the interface identifier is not inverted in this	 * case.  Hence the resulting interface identifier has local	 * scope according to RFC2373.	 */	if (dev->dev_id) {		eui[3] = (dev->dev_id >> 8) & 0xFF;		eui[4] = dev->dev_id & 0xFF;	} else {		eui[3] = 0xFF;		eui[4] = 0xFE;		eui[0] ^= 2;	}	return 0;}static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev){	/* XXX: inherit EUI-64 from other interface -- yoshfuji */	if (dev->addr_len != ARCNET_ALEN)		return -1;	memset(eui, 0, 7);	eui[7] = *(u8*)dev->dev_addr;	return 0;}static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev){	if (dev->addr_len != INFINIBAND_ALEN)		return -1;	memcpy(eui, dev->dev_addr + 12, 8);	eui[0] |= 2;	return 0;}static int ipv6_generate_eui64(u8 *eui, struct net_device *dev){	switch (dev->type) {	case ARPHRD_ETHER:	case ARPHRD_FDDI:	case ARPHRD_IEEE802_TR:		return addrconf_ifid_eui48(eui, dev);	case ARPHRD_ARCNET:		return addrconf_ifid_arcnet(eui, dev);	case ARPHRD_INFINIBAND:		return addrconf_ifid_infiniband(eui, dev);	}	return -1;}static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev){	int err = -1;	struct inet6_ifaddr *ifp;	read_lock_bh(&idev->lock);	for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {		if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {			memcpy(eui, ifp->addr.s6_addr+8, 8);			err = 0;			break;		}	}	read_unlock_bh(&idev->lock);	return err;}#ifdef CONFIG_IPV6_PRIVACY/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */static int __ipv6_regen_rndid(struct inet6_dev *idev){regen:	get_random_bytes(idev->rndid, sizeof(idev->rndid));	idev->rndid[0] &= ~0x02;	/*	 * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:	 * check if generated address is not inappropriate	 *	 *  - Reserved subnet anycast (RFC 2526)	 *	11111101 11....11 1xxxxxxx	 *  - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1	 *	00-00-5E-FE-xx-xx-xx-xx	 *  - value 0	 *  - XXX: already assigned to an address on the device	 */	if (idev->rndid[0] == 0xfd &&	    (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&	    (idev->rndid[7]&0x80))		goto regen;	if ((idev->rndid[0]|idev->rndid[1]) == 0) {		if (idev->rndid[2] == 0x5e && idev->rndid[3] == 0xfe)			goto regen;		if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)			goto regen;	}	return 0;}static void ipv6_regen_rndid(unsigned long data){	struct inet6_dev *idev = (struct inet6_dev *) data;	unsigned long expires;	rcu_read_lock_bh();	write_lock_bh(&idev->lock);	if (idev->dead)		goto out;	if (__ipv6_regen_rndid(idev) < 0)		goto out;	expires = jiffies +		idev->cnf.temp_prefered_lft * HZ -		idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;	if (time_before(expires, jiffies)) {		printk(KERN_WARNING			"ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",			idev->dev->name);		goto out;	}	if (!mod_timer(&idev->regen_timer, expires))		in6_dev_hold(idev);out:	write_unlock_bh(&idev->lock);	rcu_read_unlock_bh();	in6_dev_put(idev);}static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) {	int ret = 0;	if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)		ret = __ipv6_regen_rndid(idev);	return ret;}#endif/* *	Add prefix route. */static voidaddrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,		      unsigned long expires, u32 flags){	struct fib6_config cfg = {		.fc_table = RT6_TABLE_PREFIX,		.fc_metric = IP6_RT_PRIO_ADDRCONF,		.fc_ifindex = dev->ifindex,		.fc_expires = expires,		.fc_dst_len = plen,		.fc_flags = RTF_UP | flags,	};	ipv6_addr_copy(&cfg.fc_dst, pfx);	/* Prevent useless cloning on PtP SIT.	   This thing is done here expecting that the whole	   class of non-broadcast devices need not cloning.	 */#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)	if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))		cfg.fc_flags |= RTF_NONEXTHOP;#endif	ip6_route_add(&cfg);}/* Create "default" multicast route to the interface */static void addrconf_add_mroute(struct net_device *dev){	struct fib6_config cfg = {		.fc_table = RT6_TABLE_LOCAL,		.fc_metric = IP6_RT_PRIO_ADDRCONF,		.fc_ifindex = dev->ifindex,		.fc_dst_len = 8,		.fc_flags = RTF_UP,	};	ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);	ip6_route_add(&cfg);}#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)static void sit_route_add(struct net_device *dev){	struct fib6_config cfg = {		.fc_table = RT6_TABLE_MAIN,		.fc_metric = IP6_RT_PRIO_ADDRCONF,		.fc_ifindex = dev->ifindex,		.fc_dst_len = 96,		.fc_flags = RTF_UP | RTF_NONEXTHOP,	};	/* prefix length - 96 bits "::d.d.d.d" */	ip6_route_add(&cfg);}#endifstatic void addrconf_add_lroute(struct net_device *dev){	struct in6_addr addr;	ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);	addrconf_prefix_route(&addr, 64, dev, 0, 0);}static struct inet6_dev *addrconf_add_dev(struct net_device *dev){	struct inet6_dev *idev;	ASSERT_RTNL();	if ((idev = ipv6_find_idev(dev)) == NULL)		return NULL;	/* Add default multicast route */	addrconf_add_mroute(dev);	/* Add link local route */	addrconf_add_lroute(dev);	return idev;

⌨️ 快捷键说明

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