version 1.1.2.2, 2000/08/27 01:25:08 |
version 1.2, 2000/07/07 15:54:19 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $KAME: in6_src.c,v 1.34 2000/08/26 10:00:45 itojun Exp $ */ |
/* $KAME: in6_src.c,v 1.27 2000/06/21 08:07:13 itojun Exp $ */ |
|
|
/* |
/* |
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
|
|
#include <netinet6/in6_pcb.h> |
#include <netinet6/in6_pcb.h> |
#include <netinet6/ip6_var.h> |
#include <netinet6/ip6_var.h> |
#include <netinet6/nd6.h> |
#include <netinet6/nd6.h> |
|
#ifdef ENABLE_DEFAULT_SCOPE |
|
#include <netinet6/scope6_var.h> |
|
#endif |
|
|
#include <net/net_osdep.h> |
#include <net/net_osdep.h> |
|
|
Line 342 in6_pcbsetport(laddr, in6p) |
|
Line 345 in6_pcbsetport(laddr, in6p) |
|
wild = IN6PLOOKUP_WILDCARD; |
wild = IN6PLOOKUP_WILDCARD; |
|
|
if (in6p->in6p_flags & IN6P_LOWPORT) { |
if (in6p->in6p_flags & IN6P_LOWPORT) { |
#ifndef IPNOPRIVPORTS |
|
if (p == 0 || (suser(p->p_ucred, &p->p_acflag) != 0)) |
if (p == 0 || (suser(p->p_ucred, &p->p_acflag) != 0)) |
return (EACCES); |
return (EACCES); |
#endif |
min = IPV6PORT_RESERVEDMIN; |
min = ip6_lowportmin; |
max = IPV6PORT_RESERVEDMAX; |
max = ip6_lowportmax; |
|
} else { |
} else { |
min = ip6_anonportmin; |
min = IPV6PORT_ANONMIN; |
max = ip6_anonportmax; |
max = IPV6PORT_ANONMAX; |
} |
} |
|
|
/* value out of range */ |
/* value out of range */ |
Line 388 in6_pcbsetport(laddr, in6p) |
|
Line 389 in6_pcbsetport(laddr, in6p) |
|
in6p->in6p_lport = lport; |
in6p->in6p_lport = lport; |
return(0); /* success */ |
return(0); /* success */ |
} |
} |
|
|
|
/* |
|
* generate kernel-internal form (scopeid embedded into s6_addr16[1]). |
|
* If the address scope of is link-local, embed the interface index in the |
|
* address. The routine determines our precedence |
|
* between advanced API scope/interface specification and basic API |
|
* specification. |
|
* |
|
* this function should be nuked in the future, when we get rid of |
|
* embedded scopeid thing. |
|
* |
|
* XXX actually, it is over-specification to return ifp against sin6_scope_id. |
|
* there can be multiple interfaces that belong to a particular scope zone |
|
* (in specification, we have 1:N mapping between a scope zone and interfaces). |
|
* we may want to change the function to return something other than ifp. |
|
*/ |
|
int |
|
in6_embedscope(in6, sin6, in6p, ifpp) |
|
struct in6_addr *in6; |
|
const struct sockaddr_in6 *sin6; |
|
struct in6pcb *in6p; |
|
struct ifnet **ifpp; |
|
{ |
|
struct ifnet *ifp = NULL; |
|
u_int32_t scopeid; |
|
|
|
*in6 = sin6->sin6_addr; |
|
scopeid = sin6->sin6_scope_id; |
|
if (ifpp) |
|
*ifpp = NULL; |
|
|
|
/* |
|
* don't try to read sin6->sin6_addr beyond here, since the caller may |
|
* ask us to overwrite existing sockaddr_in6 |
|
*/ |
|
|
|
#ifdef ENABLE_DEFAULT_SCOPE |
|
if (scopeid == 0) |
|
scopeid = scope6_addr2default(in6); |
|
#endif |
|
|
|
if (IN6_IS_SCOPE_LINKLOCAL(in6)) { |
|
struct in6_pktinfo *pi; |
|
|
|
/* |
|
* KAME assumption: link id == interface id |
|
*/ |
|
|
|
if (in6p && in6p->in6p_outputopts && |
|
(pi = in6p->in6p_outputopts->ip6po_pktinfo) && |
|
pi->ipi6_ifindex) { |
|
ifp = ifindex2ifnet[pi->ipi6_ifindex]; |
|
in6->s6_addr16[1] = htons(pi->ipi6_ifindex); |
|
} else if (in6p && IN6_IS_ADDR_MULTICAST(in6) && |
|
in6p->in6p_moptions && |
|
in6p->in6p_moptions->im6o_multicast_ifp) { |
|
ifp = in6p->in6p_moptions->im6o_multicast_ifp; |
|
in6->s6_addr16[1] = htons(ifp->if_index); |
|
} else if (scopeid) { |
|
/* boundary check */ |
|
if (scopeid < 0 || if_index < scopeid) |
|
return ENXIO; /* XXX EINVAL? */ |
|
ifp = ifindex2ifnet[scopeid]; |
|
/*XXX assignment to 16bit from 32bit variable */ |
|
in6->s6_addr16[1] = htons(scopeid & 0xffff); |
|
} |
|
|
|
if (ifpp) |
|
*ifpp = ifp; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
|
* 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 scopeid; |
|
|
|
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)) { |
|
/* |
|
* KAME assumption: link id == interface id |
|
*/ |
|
scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]); |
|
if (scopeid) { |
|
/* sanity check */ |
|
if (scopeid < 0 || if_index < scopeid) |
|
return ENXIO; |
|
#ifndef FAKE_LOOPBACK_IF |
|
if (ifp && (ifp->if_flags & IFF_LOOPBACK) == 0 && |
|
ifp->if_index != scopeid) { |
|
return ENXIO; |
|
} |
|
#else |
|
if (ifp && ifp->if_index != scopeid) |
|
return ENXIO; |
|
#endif |
|
sin6->sin6_addr.s6_addr16[1] = 0; |
|
sin6->sin6_scope_id = scopeid; |
|
} |
|
} |
|
|
|
return 0; |
|
} |