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

📄 in6_src.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			wild &= ~INPLOOKUP_WILDCARD6;
#endif
#endif
#if 0
			t = in_pcblookup_bind(&tcbtable,
					      (struct in_addr *)&in6p->in6p_laddr.s6_addr32[3],
					      lport);
#else
			t = NULL;
#endif
		} else {
#ifdef HAVE_NRL_INPCB
#ifdef INPLOOKUP_WILDCARD4
			wild &= ~INPLOOKUP_WILDCARD4;
#endif
			/* XXX: ugly cast... */
			t = in_pcblookup(head, (struct in_addr *)&zeroin6_addr,
					 0, (struct in_addr *)laddr,
					 lport, wild | INPLOOKUP_IPV6);
#else
			t = in6_pcblookup(head, &zeroin6_addr, 0, laddr,
					  lport, wild);
#endif
		}
		if (t == 0)
			break;
	  startover:
		if (head->in6p_lport >= max)
			head->in6p_lport = min;
		else
			head->in6p_lport++;
		if (head->in6p_lport == last_port)
			return (EADDRINUSE);
	}

	in6p->in6p_lport = lport;
	return(0);		/* success */
}
#ifdef HAVE_NRL_INPCB
#undef in6pcb
#undef in6p_socket
#undef in6p_lport
#undef in6p_head
#undef in6p_flags
#undef IN6PLOOKUP_WILDCARD
#endif
#endif /* !FreeBSD3 && !OpenBSD*/

#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)
/*
 * XXX: this is borrowed from in6_pcbbind(). If possible, we should
 * share this function by all *bsd*...
 */
int
in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct proc *p)
{
	struct socket *so = inp->inp_socket;
	u_int16_t lport = 0, first, last, *lastport;
	int count, wild = 0;
	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;

	/* XXX: this is redundant when called from in6_pcbbind */
	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
		wild = INPLOOKUP_WILDCARD;

	inp->inp_flags |= INP_ANONPORT;

	if (inp->inp_flags & INP_HIGHPORT) {
		first = ipport_hifirstauto;	/* sysctl */
		last  = ipport_hilastauto;
		lastport = &pcbinfo->lasthi;
	} else if (inp->inp_flags & INP_LOWPORT) {
		first = ipport_lowfirstauto;	/* 1023 */
		last  = ipport_lowlastauto;	/* 600 */
		lastport = &pcbinfo->lastlow;
	} else {
		first = ipport_firstauto;	/* sysctl */
		last  = ipport_lastauto;
		lastport = &pcbinfo->lastport;
	}
	/*
	 * Simple check to ensure all ports are not used up causing
	 * a deadlock here.
	 *
	 * We split the two cases (up and down) so that the direction
	 * is not being tested on each round of the loop.
	 */
	if (first > last) {
		/*
		 * counting down
		 */
		count = first - last;

		do {
			if (count-- < 0) {	/* completely used? */
				/*
				 * Undo any address bind that may have
				 * occurred above.
				 */
				inp->in6p_laddr = in6addr_any;
				return (EAGAIN);
			}
			--*lastport;
			if (*lastport > first || *lastport < last)
				*lastport = first;
			lport = htons(*lastport);
		} while (in6_pcblookup_local(pcbinfo,
					     &inp->in6p_laddr, lport, wild));
	} else {
		/*
			 * counting up
			 */
		count = last - first;

		do {
			if (count-- < 0) {	/* completely used? */
				/*
				 * Undo any address bind that may have
				 * occurred above.
				 */
				inp->in6p_laddr = in6addr_any;
				return (EAGAIN);
			}
			++*lastport;
			if (*lastport < first || *lastport > last)
				*lastport = first;
			lport = htons(*lastport);
		} while (in6_pcblookup_local(pcbinfo,
					     &inp->in6p_laddr, lport, wild));
	}

	inp->inp_lport = lport;
	if (in_pcbinshash(inp) != 0) {
		inp->in6p_laddr = in6addr_any;
		inp->inp_lport = 0;
		return (EAGAIN);
	}

	return(0);
}
#endif

/*
 * Generate kernel-internal form (scopeid embedded into s6_addr16[1]).
 * If the address scope of is interface-local or link-local, embed the
 * interface index in the address.
 *
 * This function should be nuked in the future, when we get rid of embedded
 * scopeid thing.
 */
int
in6_embedscope(in6, sin6)
	struct in6_addr *in6;
	const struct sockaddr_in6 *sin6;
{
#ifdef SCOPEDROUTING
	/*
	 * XXX: the SCOPEDROUTING code path is NOT expected to work at this
	 * moment (20011112).  We added this just in case.
	 */
	return(0);		/* do nothing */
#else
	struct ifnet *ifp;
	u_int32_t zoneid = sin6->sin6_scope_id;

	*in6 = sin6->sin6_addr;

	/*
	 * don't try to read sin6->sin6_addr beyond here, since the caller may
	 * ask us to overwrite existing sockaddr_in6
	 */

	if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
		/* KAME assumption: link id == interface id */
		if (zoneid) {
			if (if_index < zoneid)
				return(ENXIO);  /* XXX EINVAL? */
#if defined(__FreeBSD__) && __FreeBSD__ >= 5
			ifp = ifnet_byindex(zoneid);
#else
			ifp = ifindex2ifnet[zoneid];
#endif
			if (ifp == NULL) /* XXX: this can happen for some OS */
				return(ENXIO);

			/* XXX assignment to 16bit from 32bit variable */
			in6->s6_addr16[1] = htons(zoneid & 0xffff);
		}
	}

	return 0;
#endif
}

/*
 * generate standard sockaddr_in6 from embedded form.
 * touches sin6_addr and sin6_scope_id only.
 *
 * this function should be nuked in the future, when we get rid of
 * embedded scopeid thing.
 */
int
in6_recoverscope(sin6, in6, ifp)
	struct sockaddr_in6 *sin6;
	const struct in6_addr *in6;
	struct ifnet *ifp;
{
	u_int32_t zoneid;

	sin6->sin6_addr = *in6;

	/*
	 * don't try to read *in6 beyond here, since the caller may
	 * ask us to overwrite existing sockaddr_in6
	 */

	sin6->sin6_scope_id = 0;
	if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
		/*
		 * KAME assumption: link id == interface id
		 */
		zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
		if (zoneid) {
			/* sanity check */
			if (zoneid < 0 || if_index < zoneid)
				return ENXIO;
			if (ifp && ifp->if_index != zoneid)
				return ENXIO;
			sin6->sin6_addr.s6_addr16[1] = 0;
			sin6->sin6_scope_id = zoneid;
		}
	}

	return 0;
}

/*
 * just clear the embedded scope identifer.
 * XXX: currently used for bsdi4 only as a supplement function.
 */
void
in6_clearscope(addr)
	struct in6_addr *addr;
{
	if (IN6_IS_SCOPE_LINKLOCAL(addr) || IN6_IS_ADDR_MC_INTFACELOCAL(addr))
		addr->s6_addr16[1] = 0;
}

void
addrsel_policy_init()
{
	init_policy_queue();

	/* initialize the "last resort" policy */
	bzero(&defaultaddrpolicy, sizeof(defaultaddrpolicy));
	defaultaddrpolicy.label = ADDR_LABEL_NOTAPP;
}

static struct in6_addrpolicy *
lookup_addrsel_policy(key)
	struct sockaddr_in6 *key;
{
	struct in6_addrpolicy *match = NULL;

	match = match_addrsel_policy(key);

	if (match == NULL)
		match = &defaultaddrpolicy;
	else
		match->use++;

	return(match);
}


int
in6_src_ioctl(cmd, data)
	u_long cmd;
	caddr_t data;
{
	int i;
	struct in6_addrpolicy ent0;

	if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY)
		return(EOPNOTSUPP); /* check for safety */

	ent0 = *(struct in6_addrpolicy *)data;

	if (ent0.label == ADDR_LABEL_NOTAPP)
		return(EINVAL);
	/* check if the prefix mask is consecutive. */
	if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0)
		return(EINVAL);
	/* clear trailing garbages (if any) of the prefix address. */
	for (i = 0; i < 4; i++) {
		ent0.addr.sin6_addr.s6_addr32[i] &=
			ent0.addrmask.sin6_addr.s6_addr32[i];
	}
	ent0.use = 0;

	switch (cmd) {
	case SIOCAADDRCTL_POLICY:
		return(add_addrsel_policyent(&ent0));
	case SIOCDADDRCTL_POLICY:
		return(delete_addrsel_policyent(&ent0));
	}

	return(0);		/* XXX: compromise compilers */
}

/*
 * The followings are implementation of the policy table using a
 * simple tail queue.
 * XXX such details should be hidden.
 * XXX implementation using binary tree should be more efficient.
 */
struct addrsel_policyent {
	TAILQ_ENTRY(addrsel_policyent) ape_entry;
	struct in6_addrpolicy ape_policy;
};

TAILQ_HEAD(addrsel_policyhead, addrsel_policyent);

struct addrsel_policyhead addrsel_policytab;

static void
init_policy_queue()
{
	TAILQ_INIT(&addrsel_policytab);
}

static int
add_addrsel_policyent(newpolicy)
	struct in6_addrpolicy *newpolicy;
{
	struct addrsel_policyent *new, *pol;

	/* duplication check */
	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
	     pol = TAILQ_NEXT(pol, ape_entry)) {
		if (SA6_ARE_ADDR_EQUAL(&newpolicy->addr,
				       &pol->ape_policy.addr) &&
		    SA6_ARE_ADDR_EQUAL(&newpolicy->addrmask,
				       &pol->ape_policy.addrmask)) {
			return(EEXIST);	/* or override it? */
		}
	}

	MALLOC(new, struct addrsel_policyent *, sizeof(*new), M_IFADDR,
	       M_WAITOK);
	bzero(new, sizeof(*new));

	/* XXX: should validate entry */
	new->ape_policy = *newpolicy;

	TAILQ_INSERT_TAIL(&addrsel_policytab, new, ape_entry);

	return(0);
}

static int
delete_addrsel_policyent(key)
	struct in6_addrpolicy *key;
{
	struct addrsel_policyent *pol;

	/* search for the entry in the table */
	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
	     pol = TAILQ_NEXT(pol, ape_entry)) {
		if (SA6_ARE_ADDR_EQUAL(&key->addr, &pol->ape_policy.addr) &&
		    SA6_ARE_ADDR_EQUAL(&key->addrmask,
				       &pol->ape_policy.addrmask)) {
			break;
		}
	}
	if (pol == NULL)
		return(ESRCH);

	TAILQ_REMOVE(&addrsel_policytab, pol, ape_entry);

	return(0);
}

void
_show_addrsel_policy(void)
{
	struct addrsel_policyent *pol;

        log(LOG_ADDR, "IPv6 address policy table\n");
	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
	     pol = TAILQ_NEXT(pol, ape_entry)) {
            log(LOG_ADDR, "Addr: \n");
            log_dump(LOG_ADDR, &pol->ape_policy.addr, 16);
            log(LOG_ADDR, "Mask:\n");
            log_dump(LOG_ADDR, &pol->ape_policy.addrmask, 16);
	}
}

static struct in6_addrpolicy *
match_addrsel_policy(key)
	struct sockaddr_in6 *key;
{
	struct addrsel_policyent *pent;
	struct in6_addrpolicy *bestpol = NULL, *pol;
	int matchlen, bestmatchlen = -1;
	u_char *mp, *ep, *k, *p, m;

	for (pent = TAILQ_FIRST(&addrsel_policytab); pent;
	     pent = TAILQ_NEXT(pent, ape_entry)) {
		matchlen = 0;

		pol = &pent->ape_policy;
		mp = (u_char *)&pol->addrmask.sin6_addr;
		ep = mp + 16;	/* XXX: scope field? */
		k = (u_char *)&key->sin6_addr;
		p = (u_char *)&pol->addr.sin6_addr;
		for (; mp < ep && *mp; mp++, k++, p++) {
			m = *mp;
			if ((*k & m) != *p)
				goto next; /* not match */
			if (m == 0xff) /* short cut for a typical case */
				matchlen += 8;
			else {
				while(m >= 0x80) {
					matchlen++;
					m <<= 1;
				}
			}
		}

		/* matched.  check if this is better than the current best. */
		if (bestpol == NULL ||
		    matchlen > bestmatchlen) {
			bestpol = pol;
			bestmatchlen = matchlen;
		}

	  next:
		continue;
	}

	return(bestpol);
}

⌨️ 快捷键说明

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