Make ifconfig(8) set and display preference numbers for IPv6
addresses. Make the kernel support SIOC[SG]IFADDRPREF for IPv6 interface addresses. In in6ifa_ifpforlinklocal(), consult preference numbers before making an otherwise arbitrary choice of in6_ifaddr. Otherwise, preference numbers are *not* consulted by the kernel, but that will be rather easy for somebody with a little bit of free time to fix. Please note that setting the preference number for a link-local IPv6 address does not work right, yet, but that ought to be fixed soon. In support of the changes above, 1 Add a method to struct domain for "externalizing" a sockaddr, and provide an implementation for IPv6. Expect more work in this area: it may be more proper to say that the IPv6 implementation "internalizes" a sockaddr. Add sockaddr_externalize(). 2 Add a subroutine, sofamily(), that returns a struct socket's address family or AF_UNSPEC. 3 Make a lot of IPv4-specific code generic, and move it from sys/netinet/ to sys/net/ for re-use by IPv6 parts of the kernel and ifconfig(8).
This commit is contained in:
parent
e72611bc37
commit
c5d5f7697a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $ */
|
||||
/* $NetBSD: af_inet.c,v 1.14 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $");
|
||||
__RCSID("$NetBSD: af_inet.c,v 1.14 2009/09/11 22:06:29 dyoung Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -63,7 +63,6 @@ static void in_status(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
static void in_commit_address(prop_dictionary_t, prop_dictionary_t);
|
||||
static void in_alias(const char *, prop_dictionary_t, prop_dictionary_t,
|
||||
struct in_aliasreq *);
|
||||
static void in_preference(const char *, const struct sockaddr *);
|
||||
|
||||
static struct afswtch af = {
|
||||
.af_name = "inet", .af_af = AF_INET, .af_status = in_status,
|
||||
@ -139,46 +138,12 @@ in_alias(const char *ifname, prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t
|
||||
in_get_preference(const char *ifname, const struct sockaddr *sa)
|
||||
{
|
||||
struct if_addrprefreq ifap;
|
||||
int s;
|
||||
|
||||
if ((s = getsock(AF_INET)) == -1) {
|
||||
if (errno == EPROTONOSUPPORT)
|
||||
return 0;
|
||||
err(EXIT_FAILURE, "socket");
|
||||
}
|
||||
memset(&ifap, 0, sizeof(ifap));
|
||||
estrlcpy(ifap.ifap_name, ifname, sizeof(ifap.ifap_name));
|
||||
memcpy(&ifap.ifap_addr, sa, MIN(sizeof(ifap.ifap_addr), sa->sa_len));
|
||||
if (ioctl(s, SIOCGIFADDRPREF, &ifap) == -1) {
|
||||
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
|
||||
return 0;
|
||||
warn("SIOCGIFADDRPREF");
|
||||
}
|
||||
return ifap.ifap_preference;
|
||||
}
|
||||
|
||||
static void
|
||||
in_preference(const char *ifname, const struct sockaddr *sa)
|
||||
{
|
||||
int16_t preference;
|
||||
|
||||
if (lflag)
|
||||
return;
|
||||
|
||||
preference = in_get_preference(ifname, sa);
|
||||
printf(" preference %" PRId16, preference);
|
||||
}
|
||||
|
||||
static void
|
||||
in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct in_aliasreq ifra;
|
||||
int printprefs = 0;
|
||||
bool printprefs = false;
|
||||
const char *ifname;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
@ -187,19 +152,8 @@ in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
err(EXIT_FAILURE, "getifaddrs");
|
||||
|
||||
/* Print address preference numbers if any address has a non-zero
|
||||
* preference assigned.
|
||||
*/
|
||||
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (strcmp(ifname, ifa->ifa_name) != 0)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
if (in_get_preference(ifa->ifa_name, ifa->ifa_addr) != 0) {
|
||||
printprefs = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printprefs = ifa_any_preferences(ifname, ifap, AF_INET);
|
||||
|
||||
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (strcmp(ifname, ifa->ifa_name) != 0)
|
||||
continue;
|
||||
@ -213,7 +167,7 @@ in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
memcpy(&ifra.ifra_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
|
||||
in_alias(ifa->ifa_name, env, oenv, &ifra);
|
||||
if (printprefs)
|
||||
in_preference(ifa->ifa_name, ifa->ifa_addr);
|
||||
ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
|
||||
printf("\n");
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: af_inet6.c,v 1.24 2009/08/07 18:53:37 dyoung Exp $ */
|
||||
/* $NetBSD: af_inet6.c,v 1.25 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_inet6.c,v 1.24 2009/08/07 18:53:37 dyoung Exp $");
|
||||
__RCSID("$NetBSD: af_inet6.c,v 1.25 2009/09/11 22:06:29 dyoung Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -374,8 +374,6 @@ in6_alias(const char *ifname, prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
printf("infty");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -384,12 +382,14 @@ in6_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct in6_ifreq ifr;
|
||||
const char *ifname;
|
||||
bool printprefs = false;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "%s: getifname", __func__);
|
||||
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
err(EXIT_FAILURE, "getifaddrs");
|
||||
printprefs = ifa_any_preferences(ifname, ifap, AF_INET6);
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (strcmp(ifname, ifa->ifa_name) != 0)
|
||||
continue;
|
||||
@ -402,6 +402,9 @@ in6_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
|
||||
memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
|
||||
in6_alias(ifname, env, oenv, &ifr);
|
||||
if (printprefs)
|
||||
ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
|
||||
printf("\n");
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: util.c,v 1.12 2009/08/07 18:53:37 dyoung Exp $ */
|
||||
/* $NetBSD: util.c,v 1.13 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: util.c,v 1.12 2009/08/07 18:53:37 dyoung Exp $");
|
||||
__RCSID("$NetBSD: util.c,v 1.13 2009/09/11 22:06:29 dyoung Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
@ -290,6 +290,60 @@ print_link_addresses(prop_dictionary_t env, bool print_active_only)
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
|
||||
int16_t
|
||||
ifa_get_preference(const char *ifname, const struct sockaddr *sa)
|
||||
{
|
||||
struct if_addrprefreq ifap;
|
||||
int s;
|
||||
|
||||
if ((s = getsock(sa->sa_family)) == -1) {
|
||||
if (errno == EPROTONOSUPPORT)
|
||||
return 0;
|
||||
err(EXIT_FAILURE, "socket");
|
||||
}
|
||||
memset(&ifap, 0, sizeof(ifap));
|
||||
estrlcpy(ifap.ifap_name, ifname, sizeof(ifap.ifap_name));
|
||||
memcpy(&ifap.ifap_addr, sa, MIN(sizeof(ifap.ifap_addr), sa->sa_len));
|
||||
if (ioctl(s, SIOCGIFADDRPREF, &ifap) == -1) {
|
||||
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
|
||||
return 0;
|
||||
warn("SIOCGIFADDRPREF");
|
||||
}
|
||||
return ifap.ifap_preference;
|
||||
}
|
||||
|
||||
void
|
||||
ifa_print_preference(const char *ifname, const struct sockaddr *sa)
|
||||
{
|
||||
int16_t preference;
|
||||
|
||||
if (lflag)
|
||||
return;
|
||||
|
||||
preference = ifa_get_preference(ifname, sa);
|
||||
printf(" preference %" PRId16, preference);
|
||||
}
|
||||
|
||||
bool
|
||||
ifa_any_preferences(const char *ifname, struct ifaddrs *ifap, int family)
|
||||
{
|
||||
struct ifaddrs *ifa;
|
||||
|
||||
/* Print address preference numbers if any address has a non-zero
|
||||
* preference assigned.
|
||||
*/
|
||||
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (strcmp(ifname, ifa->ifa_name) != 0)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != family)
|
||||
continue;
|
||||
if (ifa_get_preference(ifa->ifa_name, ifa->ifa_addr) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef INET6
|
||||
/* KAME idiosyncrasy */
|
||||
void
|
||||
|
@ -2,6 +2,9 @@
|
||||
#define _IFCONFIG_UTIL_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
@ -25,5 +28,8 @@ int indirect_ioctl(prop_dictionary_t, unsigned long, void *);
|
||||
#ifdef INET6
|
||||
void in6_fillscopeid(struct sockaddr_in6 *sin6);
|
||||
#endif /* INET6 */
|
||||
bool ifa_any_preferences(const char *, struct ifaddrs *, int);
|
||||
void ifa_print_preference(const char *, const struct sockaddr *);
|
||||
int16_t ifa_get_preference(const char *, const struct sockaddr *);
|
||||
|
||||
#endif /* _IFCONFIG_UTIL_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uipc_domain.c,v 1.83 2009/09/08 18:01:34 dyoung Exp $ */
|
||||
/* $NetBSD: uipc_domain.c,v 1.84 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.83 2009/09/08 18:01:34 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.84 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
@ -268,6 +268,20 @@ sockaddr_copy(struct sockaddr *dst, socklen_t socklen,
|
||||
return memcpy(dst, src, src->sa_len);
|
||||
}
|
||||
|
||||
struct sockaddr *
|
||||
sockaddr_externalize(struct sockaddr *dst, socklen_t socklen,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
struct domain *dom;
|
||||
|
||||
dom = pffinddomain(src->sa_family);
|
||||
|
||||
if (dom != NULL && dom->dom_sockaddr_externalize != NULL)
|
||||
return (*dom->dom_sockaddr_externalize)(dst, socklen, src);
|
||||
|
||||
return sockaddr_copy(dst, socklen, src);
|
||||
}
|
||||
|
||||
int
|
||||
sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uipc_socket.c,v 1.189 2009/04/30 20:41:33 ad Exp $ */
|
||||
/* $NetBSD: uipc_socket.c,v 1.190 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
|
||||
@ -63,7 +63,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.189 2009/04/30 20:41:33 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.190 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_sock_counters.h"
|
||||
@ -554,6 +554,19 @@ fsocreate(int domain, struct socket **sop, int type, int protocol,
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
sofamily(const struct socket *so)
|
||||
{
|
||||
const struct protosw *pr;
|
||||
const struct domain *dom;
|
||||
|
||||
if ((pr = so->so_proto) == NULL)
|
||||
return AF_UNSPEC;
|
||||
if ((dom = pr->pr_domain) == NULL)
|
||||
return AF_UNSPEC;
|
||||
return dom->dom_family;
|
||||
}
|
||||
|
||||
int
|
||||
sobind(struct socket *so, struct mbuf *nam, struct lwp *l)
|
||||
{
|
||||
|
66
sys/net/if.c
66
sys/net/if.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.c,v 1.234 2009/08/13 00:23:31 dyoung Exp $ */
|
||||
/* $NetBSD: if.c,v 1.235 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
|
||||
@ -90,7 +90,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.234 2009/08/13 00:23:31 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.235 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
@ -1573,6 +1573,68 @@ ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
|
||||
lwp_t *l)
|
||||
{
|
||||
struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
|
||||
struct ifaddr *ifa;
|
||||
const struct sockaddr *any, *sa;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
} u;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
|
||||
KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
|
||||
NULL) != 0)
|
||||
return EPERM;
|
||||
case SIOCGIFADDRPREF:
|
||||
break;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* sanity checks */
|
||||
if (data == NULL || ifp == NULL) {
|
||||
panic("invalid argument to %s", __func__);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/* address must be specified on ADD and DELETE */
|
||||
sa = sstocsa(&ifap->ifap_addr);
|
||||
if (sa->sa_family != sofamily(so))
|
||||
return EINVAL;
|
||||
if ((any = sockaddr_any(sa)) == NULL || sa->sa_len != any->sa_len)
|
||||
return EINVAL;
|
||||
|
||||
IFADDR_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != sa->sa_family)
|
||||
continue;
|
||||
sockaddr_externalize(&u.sa, sizeof(u.ss), ifa->ifa_addr);
|
||||
if (sockaddr_cmp(&u.sa, sa) == 0)
|
||||
break;
|
||||
}
|
||||
if (ifa == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
ifa->ifa_preference = ifap->ifap_preference;
|
||||
return 0;
|
||||
case SIOCGIFADDRPREF:
|
||||
/* fill in the if_laddrreq structure */
|
||||
(void)sockaddr_copy(sstosa(&ifap->ifap_addr),
|
||||
sizeof(ifap->ifap_addr), ifa->ifa_addr);
|
||||
ifap->ifap_preference = ifa->ifa_preference;
|
||||
return 0;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface ioctls.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.h,v 1.143 2009/08/13 00:23:32 dyoung Exp $ */
|
||||
/* $NetBSD: if.h,v 1.144 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
@ -829,6 +829,8 @@ void if_up(struct ifnet *);
|
||||
int ifconf(u_long, void *);
|
||||
void ifinit(void);
|
||||
void ifinit1(void);
|
||||
int ifaddrpref_ioctl(struct socket *, u_long, void *, struct ifnet *,
|
||||
lwp_t *);
|
||||
int ifioctl(struct socket *, u_long, void *, struct lwp *);
|
||||
int ifioctl_common(struct ifnet *, u_long, void *);
|
||||
int ifpromisc(struct ifnet *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in.c,v 1.134 2009/04/18 14:58:05 tsutsui Exp $ */
|
||||
/* $NetBSD: in.c,v 1.135 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -91,7 +91,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.134 2009/04/18 14:58:05 tsutsui Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.135 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet_conf.h"
|
||||
@ -139,8 +139,6 @@ static void in_len2mask(struct in_addr *, u_int);
|
||||
static int in_lifaddr_ioctl(struct socket *, u_long, void *,
|
||||
struct ifnet *, struct lwp *);
|
||||
|
||||
static int in_ifaddrpref_ioctl(struct socket *, u_long, void *,
|
||||
struct ifnet *);
|
||||
static int in_addprefix(struct in_ifaddr *, int);
|
||||
static int in_scrubprefix(struct in_ifaddr *);
|
||||
|
||||
@ -321,15 +319,15 @@ in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
|
||||
switch (cmd) {
|
||||
case SIOCALIFADDR:
|
||||
case SIOCDLIFADDR:
|
||||
case SIOCSIFADDRPREF:
|
||||
case SIOCGIFADDRPREF:
|
||||
case SIOCGLIFADDR:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
if (cmd == SIOCGIFADDRPREF || cmd == SIOCSIFADDRPREF)
|
||||
return in_ifaddrpref_ioctl(so, cmd, data, ifp);
|
||||
else
|
||||
return in_lifaddr_ioctl(so, cmd, data, ifp, l);
|
||||
return in_lifaddr_ioctl(so, cmd, data, ifp, l);
|
||||
case SIOCGIFADDRPREF:
|
||||
case SIOCSIFADDRPREF:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
return ifaddrpref_ioctl(so, cmd, data, ifp, l);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -339,7 +337,6 @@ in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
|
||||
IFP_TO_IA(ifp, ia);
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case SIOCAIFADDR:
|
||||
case SIOCDIFADDR:
|
||||
case SIOCGIFALIAS:
|
||||
@ -777,66 +774,6 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
||||
return EOPNOTSUPP; /*just for safety*/
|
||||
}
|
||||
|
||||
static int
|
||||
in_ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data,
|
||||
struct ifnet *ifp)
|
||||
{
|
||||
struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr *sa;
|
||||
struct in_ifaddr *ia = NULL; /* appease gcc -Wuninitialized */
|
||||
struct in_addr match;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
/* sanity checks */
|
||||
if (data == NULL || ifp == NULL) {
|
||||
panic("invalid argument to %s", __func__);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/* address must be specified on ADD and DELETE */
|
||||
sa = (struct sockaddr *)&ifap->ifap_addr;
|
||||
if (sa->sa_family != AF_INET)
|
||||
return EINVAL;
|
||||
if (sa->sa_len != sizeof(struct sockaddr_in))
|
||||
return EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
case SIOCGIFADDRPREF:
|
||||
break;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
sin = (struct sockaddr_in *)&ifap->ifap_addr;
|
||||
match.s_addr = sin->sin_addr.s_addr;
|
||||
|
||||
IFADDR_FOREACH(ifa, ifp) {
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
if (ia->ia_addr.sin_family != AF_INET)
|
||||
continue;
|
||||
if (ia->ia_addr.sin_addr.s_addr == match.s_addr)
|
||||
break;
|
||||
}
|
||||
if (ifa == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
ifa->ifa_preference = ifap->ifap_preference;
|
||||
return 0;
|
||||
case SIOCGIFADDRPREF:
|
||||
/* fill in the if_laddrreq structure */
|
||||
(void)memcpy(&ifap->ifap_addr, &ia->ia_addr,
|
||||
ia->ia_addr.sin_len);
|
||||
ifap->ifap_preference = ifa->ifa_preference;
|
||||
return 0;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete any existing route for an interface.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6.c,v 1.152 2009/08/13 00:34:04 dyoung Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.153 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.152 2009/08/13 00:34:04 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.153 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_pfil_hooks.h"
|
||||
@ -350,13 +350,14 @@ in6_mask2len(struct in6_addr *mask, u_char *lim0)
|
||||
|
||||
static int
|
||||
in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
|
||||
struct lwp *l)
|
||||
lwp_t *l)
|
||||
{
|
||||
struct in6_ifreq *ifr = (struct in6_ifreq *)data;
|
||||
struct in6_ifaddr *ia = NULL;
|
||||
struct in6_aliasreq *ifra = (struct in6_aliasreq *)data;
|
||||
struct sockaddr_in6 *sa6;
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
/*
|
||||
* XXX: Fix me, once we fix SIOCSIFADDR, SIOCIFDSTADDR, etc.
|
||||
@ -370,6 +371,11 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
|
||||
case SIOCGETSGCNT_IN6:
|
||||
case SIOCGETMIFCNT_IN6:
|
||||
return mrt6_ioctl(cmd, data);
|
||||
case SIOCGIFADDRPREF:
|
||||
case SIOCSIFADDRPREF:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
return ifaddrpref_ioctl(so, cmd, data, ifp, l);
|
||||
}
|
||||
|
||||
if (ifp == NULL)
|
||||
@ -1793,22 +1799,24 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpforlinklocal(const struct ifnet *ifp, const int ignoreflags)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *best_ifa = NULL, *ifa;
|
||||
|
||||
IFADDR_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue; /* just for safety */
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
|
||||
if ((((struct in6_ifaddr *)ifa)->ia6_flags &
|
||||
ignoreflags) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa)))
|
||||
continue;
|
||||
if ((((struct in6_ifaddr *)ifa)->ia6_flags & ignoreflags) != 0)
|
||||
continue;
|
||||
if (best_ifa == NULL)
|
||||
best_ifa = ifa;
|
||||
else if (best_ifa->ifa_preference < ifa->ifa_preference)
|
||||
best_ifa = ifa;
|
||||
}
|
||||
|
||||
return (struct in6_ifaddr *)ifa;
|
||||
return (struct in6_ifaddr *)best_ifa;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6.h,v 1.67 2009/08/19 18:52:48 seanb Exp $ */
|
||||
/* $NetBSD: in6.h,v 1.68 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -684,6 +684,8 @@ in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
|
||||
struct mbuf;
|
||||
struct ifnet;
|
||||
int sockaddr_in6_cmp(const struct sockaddr *, const struct sockaddr *);
|
||||
struct sockaddr *sockaddr_in6_externalize(struct sockaddr *, socklen_t,
|
||||
const struct sockaddr *);
|
||||
int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t);
|
||||
void in6_delayed_cksum(struct mbuf *);
|
||||
int in6_localaddr(const struct in6_addr *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_proto.c,v 1.86 2009/09/11 20:10:06 dyoung Exp $ */
|
||||
/* $NetBSD: in6_proto.c,v 1.87 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.86 2009/09/11 20:10:06 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.87 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -421,6 +421,7 @@ struct domain inet6domain = {
|
||||
.dom_sa_cmpofs = offsetof(struct sockaddr_in6, sin6_addr),
|
||||
.dom_sa_cmplen = sizeof(struct in6_addr),
|
||||
.dom_sa_any = (const struct sockaddr *)&in6_any,
|
||||
.dom_sockaddr_externalize = sockaddr_in6_externalize,
|
||||
.dom_rtcache = LIST_HEAD_INITIALIZER(inet6domain.dom_rtcache)
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: scope6.c,v 1.7 2009/03/15 21:26:09 cegger Exp $ */
|
||||
/* $NetBSD: scope6.c,v 1.8 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
/* $KAME$ */
|
||||
|
||||
/*-
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: scope6.c,v 1.7 2009/03/15 21:26:09 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: scope6.c,v 1.8 2009/09/11 22:06:29 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -328,6 +328,20 @@ sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sockaddr *
|
||||
sockaddr_in6_externalize(struct sockaddr *dst, socklen_t socklen,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = satosin6(sockaddr_copy(dst, socklen, src));
|
||||
|
||||
if (sin6 == NULL || sa6_recoverscope(sin6) != 0)
|
||||
return NULL;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* generate standard sockaddr_in6 from embedded form.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: domain.h,v 1.28 2009/05/27 23:44:35 pooka Exp $ */
|
||||
/* $NetBSD: domain.h,v 1.29 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -75,6 +75,9 @@ struct domain {
|
||||
void *(*dom_sockaddr_addr)(struct sockaddr *, socklen_t *);
|
||||
int (*dom_sockaddr_cmp)(const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
struct sockaddr *(*dom_sockaddr_externalize)(struct sockaddr *,
|
||||
socklen_t,
|
||||
const struct sockaddr *);
|
||||
const struct sockaddr *dom_sa_any;
|
||||
struct ifqueue *dom_ifqueues[2]; /* ifqueue for domain */
|
||||
STAILQ_ENTRY(domain) dom_link;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: socket.h,v 1.95 2009/04/28 20:54:50 dyoung Exp $ */
|
||||
/* $NetBSD: socket.h,v 1.96 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -573,6 +573,8 @@ sockaddr_getlen(const struct sockaddr *sa)
|
||||
__BEGIN_DECLS
|
||||
struct sockaddr *sockaddr_copy(struct sockaddr *, socklen_t,
|
||||
const struct sockaddr *);
|
||||
struct sockaddr *sockaddr_externalize(struct sockaddr *, socklen_t,
|
||||
const struct sockaddr *);
|
||||
struct sockaddr *sockaddr_alloc(sa_family_t, socklen_t, int);
|
||||
const void *sockaddr_const_addr(const struct sockaddr *, socklen_t *);
|
||||
void *sockaddr_addr(struct sockaddr *, socklen_t *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: socketvar.h,v 1.120 2009/09/02 14:56:57 tls Exp $ */
|
||||
/* $NetBSD: socketvar.h,v 1.121 2009/09/11 22:06:29 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
||||
@ -281,6 +281,7 @@ void soinit(void);
|
||||
void soinit2(void);
|
||||
int soabort(struct socket *);
|
||||
int soaccept(struct socket *, struct mbuf *);
|
||||
int sofamily(const struct socket *);
|
||||
int sobind(struct socket *, struct mbuf *, struct lwp *);
|
||||
void socantrcvmore(struct socket *);
|
||||
void socantsendmore(struct socket *);
|
||||
|
Loading…
Reference in New Issue
Block a user