Import NetBSD ifconfig(8)
Not all of its functionality is actually implemented in the operating system. In addition, a few modules (agr, vlan) have been disabled because we have not imported the necessary headers yet. Change-Id: I4c9271065d640bd9112b4bd27e2652e1d51b18b4
This commit is contained in:
parent
f1fab66e7d
commit
90b801219a
|
|
@ -210,6 +210,7 @@
|
|||
./sbin/fsck_ext2fs minix-base
|
||||
./sbin/fsck_mfs minix-base
|
||||
./sbin/halt minix-base
|
||||
./sbin/ifconfig minix-base
|
||||
./sbin/init minix-base
|
||||
./sbin/minix-service minix-base
|
||||
./sbin/mkfs.mfs minix-base
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@
|
|||
./usr/libdata/debug/sbin/fsck.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/fsck_ext2fs.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/fsck_mfs.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/ifconfig.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/init.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/minix-service.debug minix-debug debug
|
||||
./usr/libdata/debug/sbin/mknod.debug minix-debug debug
|
||||
|
|
|
|||
|
|
@ -3409,7 +3409,7 @@
|
|||
./usr/man/man8/halt.8 minix-man
|
||||
./usr/man/man8/httpd.8 minix-man obsolete
|
||||
./usr/man/man8/i2cscan.8 minix-man
|
||||
./usr/man/man8/ifconfig.8 minix-man obsolete
|
||||
./usr/man/man8/ifconfig.8 minix-man
|
||||
./usr/man/man8/in.httpd.8 minix-man obsolete
|
||||
./usr/man/man8/inet.8 minix-man obsolete
|
||||
./usr/man/man8/init.8 minix-man
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
SUBDIR= \
|
||||
chown \
|
||||
fsck init \
|
||||
fsck ifconfig init \
|
||||
mknod nologin \
|
||||
ping \
|
||||
reboot rcorder \
|
||||
|
|
|
|||
40
sbin/ifconfig/Makefile
Normal file
40
sbin/ifconfig/Makefile
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# $NetBSD: Makefile,v 1.56 2015/05/19 08:14:38 ozaki-r Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
|
||||
# when making a change to this file, please check if the change is
|
||||
# also needed for src/distrib/utils/x_ifconfig.
|
||||
# such stuff should be into Makefile.inc.
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
RUMPPRG=ifconfig
|
||||
MAN= ifconfig.8
|
||||
|
||||
#DBG+=-g
|
||||
SRCS= af_atalk.c af_link.c carp.c
|
||||
.if (${USE_INET6} != "no")
|
||||
CPPFLAGS+= -DINET6
|
||||
SRCS+= af_inet6.c
|
||||
.endif
|
||||
|
||||
.include "Makefile.inc"
|
||||
|
||||
.PATH: ${.CURDIR}/../../lib/libc/net
|
||||
RUMPSRCS= getifaddrs.c getnameinfo.c if_indextoname.c
|
||||
.if (${MKRUMP} != "no")
|
||||
CPPFLAGS+= -DRUMP_ACTION
|
||||
.endif
|
||||
|
||||
.ifdef SMALLPROG
|
||||
CPPFLAGS+=-DSMALL
|
||||
.endif
|
||||
|
||||
CPPFLAGS+=-I${NETBSDSRCDIR}/sys/dist/pf/
|
||||
SRCS+= pfsync.c
|
||||
|
||||
.if ${MACHINE_ARCH} == "m68000"
|
||||
# XXX workaround for gcc -O1 bug (PR bin/40036 and toolchain/40066)
|
||||
COPTS.ifconfig.c+= -fno-loop-optimize
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
23
sbin/ifconfig/Makefile.inc
Normal file
23
sbin/ifconfig/Makefile.inc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# $NetBSD: Makefile.inc,v 1.9 2012/10/31 10:17:34 msaitoh Exp $
|
||||
|
||||
# shared stuff with src/distrib/utils/x_ifconfig for install media.
|
||||
# stuff not required by install media should be into Makefile.
|
||||
|
||||
DPADD+=${LIBUTIL}
|
||||
DPADD+=${LIBPROP}
|
||||
LDADD+=-lutil
|
||||
LDADD+=-lprop
|
||||
|
||||
INCS+=af_inetany.h env.h extern.h media.h parse.h util.h
|
||||
SRCS+= af_inet.c
|
||||
SRCS+= af_inetany.c
|
||||
#SRCS+= agr.c
|
||||
SRCS+= env.c
|
||||
SRCS+= ether.c
|
||||
SRCS+= ieee80211.c
|
||||
SRCS+= ifconfig.c
|
||||
SRCS+= media.c
|
||||
SRCS+= parse.c
|
||||
SRCS+= tunnel.c
|
||||
SRCS+= util.c
|
||||
#SRCS+= vlan.c
|
||||
249
sbin/ifconfig/af_atalk.c
Normal file
249
sbin/ifconfig/af_atalk.c
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/* $NetBSD: af_atalk.c,v 1.19 2013/10/19 00:35:30 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_atalk.c,v 1.19 2013/10/19 00:35:30 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netatalk/at.h>
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "af_inetany.h"
|
||||
#include "parse.h"
|
||||
#include "extern.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
#ifndef satocsat
|
||||
#define satocsat(__sa) ((const struct sockaddr_at *)(__sa))
|
||||
#endif
|
||||
|
||||
static void at_status(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
static void at_commit_address(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
static void at_constructor(void) __attribute__((constructor));
|
||||
|
||||
static struct afswtch ataf = {
|
||||
.af_name = "atalk", .af_af = AF_APPLETALK, .af_status = at_status,
|
||||
.af_addr_commit = at_commit_address
|
||||
};
|
||||
struct pinteger phase = PINTEGER_INITIALIZER1(&phase, "phase",
|
||||
1, 2, 10, NULL, "phase", &command_root.pb_parser);
|
||||
|
||||
struct pstr parse_range = PSTR_INITIALIZER(&range, "range", NULL, "range",
|
||||
&command_root.pb_parser);
|
||||
|
||||
static const struct kwinst atalkkw[] = {
|
||||
{.k_word = "phase", .k_nextparser = &phase.pi_parser}
|
||||
, {.k_word = "range", .k_nextparser = &parse_range.ps_parser}
|
||||
};
|
||||
|
||||
struct pkw atalk = PKW_INITIALIZER(&atalk, "AppleTalk", NULL, NULL,
|
||||
atalkkw, __arraycount(atalkkw), NULL);
|
||||
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void
|
||||
setatrange_impl(prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
struct netrange *nr)
|
||||
{
|
||||
char range[24];
|
||||
u_short first = 123, last = 123;
|
||||
|
||||
if (getargstr(env, "range", range, sizeof(range)) == -1)
|
||||
return;
|
||||
|
||||
if (sscanf(range, "%hu-%hu", &first, &last) != 2 ||
|
||||
first == 0 || last == 0 || first > last)
|
||||
errx(EXIT_FAILURE, "%s: illegal net range: %u-%u", range,
|
||||
first, last);
|
||||
nr->nr_firstnet = htons(first);
|
||||
nr->nr_lastnet = htons(last);
|
||||
}
|
||||
|
||||
static void
|
||||
at_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct ifaliasreq ifra __attribute__((aligned(4)));
|
||||
struct afparam atparam = {
|
||||
.req = BUFPARAM(ifra)
|
||||
, .dgreq = BUFPARAM(ifr)
|
||||
, .name = {
|
||||
{.buf = ifr.ifr_name,
|
||||
.buflen = sizeof(ifr.ifr_name)}
|
||||
, {.buf = ifra.ifra_name,
|
||||
.buflen = sizeof(ifra.ifra_name)}
|
||||
}
|
||||
, .dgaddr = BUFPARAM(ifr.ifr_addr)
|
||||
, .addr = BUFPARAM(ifra.ifra_addr)
|
||||
, .dst = BUFPARAM(ifra.ifra_dstaddr)
|
||||
, .brd = BUFPARAM(ifra.ifra_broadaddr)
|
||||
, .mask = BUFPARAM(ifra.ifra_mask)
|
||||
, .aifaddr = IFADDR_PARAM(SIOCAIFADDR)
|
||||
, .difaddr = IFADDR_PARAM(SIOCDIFADDR)
|
||||
, .gifaddr = IFADDR_PARAM(SIOCGIFADDR)
|
||||
, .defmask = {.buf = NULL, .buflen = 0}
|
||||
};
|
||||
struct netrange nr = {.nr_phase = 2}; /* AppleTalk net range */
|
||||
prop_data_t d, d0;
|
||||
prop_dictionary_t ienv;
|
||||
struct paddr_prefix *addr;
|
||||
struct sockaddr_at *sat;
|
||||
|
||||
if ((d0 = (prop_data_t)prop_dictionary_get(env, "address")) == NULL)
|
||||
return;
|
||||
|
||||
addr = prop_data_data(d0);
|
||||
|
||||
sat = (struct sockaddr_at *)&addr->pfx_addr;
|
||||
|
||||
(void)prop_dictionary_get_uint8(env, "phase", &nr.nr_phase);
|
||||
/* Default range of one */
|
||||
nr.nr_firstnet = nr.nr_lastnet = sat->sat_addr.s_net;
|
||||
setatrange_impl(env, oenv, &nr);
|
||||
|
||||
if (ntohs(nr.nr_firstnet) > ntohs(sat->sat_addr.s_net) ||
|
||||
ntohs(nr.nr_lastnet) < ntohs(sat->sat_addr.s_net))
|
||||
errx(EXIT_FAILURE, "AppleTalk address is not in range");
|
||||
memcpy(&sat->sat_zero, &nr, sizeof(nr));
|
||||
|
||||
/* Copy the new address to a temporary input environment */
|
||||
|
||||
d = prop_data_create_data_nocopy(addr, paddr_prefix_size(addr));
|
||||
ienv = prop_dictionary_copy_mutable(env);
|
||||
|
||||
if (d == NULL)
|
||||
err(EXIT_FAILURE, "%s: prop_data_create_data", __func__);
|
||||
if (ienv == NULL)
|
||||
err(EXIT_FAILURE, "%s: prop_dictionary_copy_mutable", __func__);
|
||||
|
||||
if (!prop_dictionary_set(ienv, "address", (prop_object_t)d))
|
||||
err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
|
||||
|
||||
/* copy to output environment for good measure */
|
||||
if (!prop_dictionary_set(oenv, "address", (prop_object_t)d))
|
||||
err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
|
||||
|
||||
prop_object_release((prop_object_t)d);
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
memset(&ifra, 0, sizeof(ifra));
|
||||
commit_address(ienv, oenv, &atparam);
|
||||
|
||||
/* release temporary input environment */
|
||||
prop_object_release((prop_object_t)ienv);
|
||||
}
|
||||
|
||||
static void
|
||||
sat_print1(const char *prefix, const struct sockaddr *sa)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
(void)getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, 0);
|
||||
|
||||
printf("%s%s", prefix, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
at_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
{
|
||||
struct sockaddr_at *sat;
|
||||
struct ifreq ifr;
|
||||
int s;
|
||||
const char *ifname;
|
||||
unsigned short flags;
|
||||
|
||||
if ((s = getsock(AF_APPLETALK)) == -1) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
return;
|
||||
err(EXIT_FAILURE, "getsock");
|
||||
}
|
||||
if ((ifname = getifinfo(env, oenv, &flags)) == NULL)
|
||||
err(EXIT_FAILURE, "%s: getifinfo", __func__);
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_addr.sa_family = AF_APPLETALK;
|
||||
if (prog_ioctl(s, SIOCGIFADDR, &ifr) != -1)
|
||||
;
|
||||
else if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
|
||||
if (!force)
|
||||
return;
|
||||
memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
|
||||
} else
|
||||
warn("SIOCGIFADDR");
|
||||
sat = (struct sockaddr_at *)&ifr.ifr_addr;
|
||||
|
||||
sat_print1("\tatalk ", &ifr.ifr_addr);
|
||||
|
||||
if (flags & IFF_POINTOPOINT) {
|
||||
estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
if (prog_ioctl(s, SIOCGIFDSTADDR, &ifr) == -1) {
|
||||
if (errno == EADDRNOTAVAIL)
|
||||
memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
|
||||
else
|
||||
warn("SIOCGIFDSTADDR");
|
||||
}
|
||||
sat_print1(" --> ", &ifr.ifr_dstaddr);
|
||||
}
|
||||
if (flags & IFF_BROADCAST) {
|
||||
/* note RTAX_BRD overlap with IFF_POINTOPOINT */
|
||||
/* note Appletalk broadcast is fixed. */
|
||||
printf(" broadcast %u.%u", ntohs(sat->sat_addr.s_net),
|
||||
ATADDR_BCAST);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
at_constructor(void)
|
||||
{
|
||||
register_family(&ataf);
|
||||
cmdloop_branch_init(&branch, &atalk.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
}
|
||||
247
sbin/ifconfig/af_inet.c
Normal file
247
sbin/ifconfig/af_inet.c
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* $NetBSD: af_inet.c,v 1.17 2015/05/12 14:05:29 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_inet.c,v 1.17 2015/05/12 14:05:29 roy Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "af_inetany.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
static void in_constructor(void) __attribute__((constructor));
|
||||
static void in_status(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
static void in_commit_address(prop_dictionary_t, prop_dictionary_t);
|
||||
static bool in_addr_tentative(struct ifaddrs *ifa);
|
||||
static void in_alias(const char *, prop_dictionary_t, prop_dictionary_t,
|
||||
struct in_aliasreq *);
|
||||
|
||||
static struct afswtch af = {
|
||||
.af_name = "inet", .af_af = AF_INET, .af_status = in_status,
|
||||
.af_addr_commit = in_commit_address,
|
||||
.af_addr_tentative = in_addr_tentative
|
||||
};
|
||||
|
||||
static void
|
||||
in_alias(const char *ifname, prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
struct in_aliasreq *creq)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
bool alias;
|
||||
int s;
|
||||
unsigned short flags;
|
||||
struct in_aliasreq in_addreq;
|
||||
const struct sockaddr_in * const asin = &in_addreq.ifra_addr;
|
||||
const struct sockaddr_in * const dsin = &in_addreq.ifra_dstaddr;
|
||||
const struct sockaddr_in * const bsin = &in_addreq.ifra_broadaddr;
|
||||
char hbuf[NI_MAXHOST];
|
||||
const int niflag = Nflag ? 0 : NI_NUMERICHOST;
|
||||
|
||||
if (lflag)
|
||||
return;
|
||||
|
||||
alias = true;
|
||||
|
||||
/* Get the non-alias address for this interface. */
|
||||
if ((s = getsock(AF_INET)) == -1) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
return;
|
||||
err(EXIT_FAILURE, "socket");
|
||||
}
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
if (prog_ioctl(s, SIOCGIFADDR, &ifr) == -1) {
|
||||
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
|
||||
return;
|
||||
warn("SIOCGIFADDR");
|
||||
}
|
||||
/* If creq and ifr are the same address, this is not an alias. */
|
||||
if (memcmp(&ifr.ifr_addr, &creq->ifra_addr, sizeof(ifr.ifr_addr)) == 0)
|
||||
alias = false;
|
||||
in_addreq = *creq;
|
||||
if (prog_ioctl(s, SIOCGIFALIAS, &in_addreq) == -1) {
|
||||
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
|
||||
return;
|
||||
} else
|
||||
warn("SIOCGIFALIAS");
|
||||
}
|
||||
|
||||
if (getnameinfo((const struct sockaddr *)asin, asin->sin_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, niflag))
|
||||
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
|
||||
printf("\tinet %s%s", alias ? "alias " : "", hbuf);
|
||||
|
||||
if (getifflags(env, oenv, &flags) == -1)
|
||||
err(EXIT_FAILURE, "%s: getifflags", __func__);
|
||||
|
||||
if (flags & IFF_POINTOPOINT) {
|
||||
if (getnameinfo((const struct sockaddr *)dsin, dsin->sin_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, niflag))
|
||||
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
|
||||
printf(" -> %s", hbuf);
|
||||
}
|
||||
|
||||
printf(" netmask 0x%x", ntohl(in_addreq.ifra_mask.sin_addr.s_addr));
|
||||
|
||||
if (flags & IFF_BROADCAST) {
|
||||
if (getnameinfo((const struct sockaddr *)bsin, bsin->sin_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, niflag))
|
||||
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
|
||||
printf(" broadcast %s", hbuf);
|
||||
}
|
||||
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
memcpy(&ifr.ifr_addr, &creq->ifra_addr, creq->ifra_addr.sin_len);
|
||||
if (prog_ioctl(s, SIOCGIFAFLAG_IN, &ifr) == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("SIOCGIFAFLAG_IN");
|
||||
} else {
|
||||
if (ifr.ifr_addrflags & IN_IFF_TENTATIVE)
|
||||
printf(" tentative");
|
||||
if (ifr.ifr_addrflags & IN_IFF_DUPLICATED)
|
||||
printf(" duplicated");
|
||||
if (ifr.ifr_addrflags & IN_IFF_DETACHED)
|
||||
printf(" detached");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct in_aliasreq ifra;
|
||||
bool printprefs = false;
|
||||
const char *ifname;
|
||||
|
||||
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_INET);
|
||||
|
||||
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 (sizeof(ifra.ifra_addr) < ifa->ifa_addr->sa_len)
|
||||
continue;
|
||||
|
||||
memset(&ifra, 0, sizeof(ifra));
|
||||
estrlcpy(ifra.ifra_name, ifa->ifa_name, sizeof(ifra.ifra_name));
|
||||
memcpy(&ifra.ifra_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
|
||||
in_alias(ifa->ifa_name, env, oenv, &ifra);
|
||||
if (printprefs)
|
||||
ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
|
||||
printf("\n");
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
|
||||
static void
|
||||
in_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct ifreq in_ifr;
|
||||
struct in_aliasreq in_ifra;
|
||||
struct afparam inparam = {
|
||||
.req = BUFPARAM(in_ifra)
|
||||
, .dgreq = BUFPARAM(in_ifr)
|
||||
, .name = {
|
||||
{.buf = in_ifr.ifr_name,
|
||||
.buflen = sizeof(in_ifr.ifr_name)}
|
||||
, {.buf = in_ifra.ifra_name,
|
||||
.buflen = sizeof(in_ifra.ifra_name)}
|
||||
}
|
||||
, .dgaddr = BUFPARAM(in_ifr.ifr_addr)
|
||||
, .addr = BUFPARAM(in_ifra.ifra_addr)
|
||||
, .dst = BUFPARAM(in_ifra.ifra_dstaddr)
|
||||
, .brd = BUFPARAM(in_ifra.ifra_broadaddr)
|
||||
, .mask = BUFPARAM(in_ifra.ifra_mask)
|
||||
, .aifaddr = IFADDR_PARAM(SIOCAIFADDR)
|
||||
, .difaddr = IFADDR_PARAM(SIOCDIFADDR)
|
||||
, .gifaddr = IFADDR_PARAM(SIOCGIFADDR)
|
||||
, .defmask = {.buf = NULL, .buflen = 0}
|
||||
};
|
||||
memset(&in_ifr, 0, sizeof(in_ifr));
|
||||
memset(&in_ifra, 0, sizeof(in_ifra));
|
||||
commit_address(env, oenv, &inparam);
|
||||
}
|
||||
|
||||
static bool
|
||||
in_addr_tentative(struct ifaddrs *ifa)
|
||||
{
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
int s;
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_addr = *ifa->ifa_addr;
|
||||
if ((s = getsock(AF_INET)) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
if (prog_ioctl(s, SIOCGIFAFLAG_IN, &ifr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCGIFAFLAG_IN");
|
||||
return ifr.ifr_addrflags & IN_IFF_TENTATIVE ? true : false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
in_constructor(void)
|
||||
{
|
||||
register_family(&af);
|
||||
}
|
||||
516
sbin/ifconfig/af_inet6.c
Normal file
516
sbin/ifconfig/af_inet6.c
Normal file
|
|
@ -0,0 +1,516 @@
|
|||
/* $NetBSD: af_inet6.c,v 1.33 2015/05/12 14:05:29 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_inet6.c,v 1.33 2015/05/12 14:05:29 roy Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "parse.h"
|
||||
#include "extern.h"
|
||||
#include "af_inetany.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
static void in6_constructor(void) __attribute__((constructor));
|
||||
static void in6_alias(const char *, prop_dictionary_t, prop_dictionary_t,
|
||||
struct in6_ifreq *);
|
||||
static void in6_commit_address(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
static int setia6eui64_impl(prop_dictionary_t, struct in6_aliasreq *);
|
||||
static int setia6flags_impl(prop_dictionary_t, struct in6_aliasreq *);
|
||||
static int setia6pltime_impl(prop_dictionary_t, struct in6_aliasreq *);
|
||||
static int setia6vltime_impl(prop_dictionary_t, struct in6_aliasreq *);
|
||||
|
||||
static int setia6lifetime(prop_dictionary_t, int64_t, time_t *, uint32_t *);
|
||||
|
||||
static void in6_status(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
static bool in6_addr_tentative(struct ifaddrs *ifa);
|
||||
|
||||
static struct usage_func usage;
|
||||
static cmdloop_branch_t branch[2];
|
||||
|
||||
static const struct kwinst ia6flagskw[] = {
|
||||
IFKW("anycast", IN6_IFF_ANYCAST)
|
||||
, IFKW("deprecated", IN6_IFF_DEPRECATED)
|
||||
};
|
||||
|
||||
static struct pinteger parse_pltime = PINTEGER_INITIALIZER(&parse_pltime,
|
||||
"pltime", 0, NULL, "pltime", &command_root.pb_parser);
|
||||
|
||||
static struct pinteger parse_vltime = PINTEGER_INITIALIZER(&parse_vltime,
|
||||
"vltime", 0, NULL, "vltime", &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst inet6kw[] = {
|
||||
{.k_word = "pltime", .k_nextparser = &parse_pltime.pi_parser}
|
||||
, {.k_word = "vltime", .k_nextparser = &parse_vltime.pi_parser}
|
||||
, {.k_word = "eui64", .k_key = "eui64", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_nextparser = &command_root.pb_parser}
|
||||
};
|
||||
|
||||
struct pkw ia6flags = PKW_INITIALIZER(&ia6flags, "ia6flags", NULL,
|
||||
"ia6flag", ia6flagskw, __arraycount(ia6flagskw), &command_root.pb_parser);
|
||||
struct pkw inet6 = PKW_INITIALIZER(&inet6, "IPv6 keywords", NULL,
|
||||
NULL, inet6kw, __arraycount(inet6kw), NULL);
|
||||
|
||||
static struct afswtch in6af = {
|
||||
.af_name = "inet6", .af_af = AF_INET6, .af_status = in6_status,
|
||||
.af_addr_commit = in6_commit_address,
|
||||
.af_addr_tentative = in6_addr_tentative
|
||||
};
|
||||
|
||||
static int
|
||||
prefix(void *val, int size)
|
||||
{
|
||||
u_char *pname = (u_char *)val;
|
||||
int byte, bit, plen = 0;
|
||||
|
||||
for (byte = 0; byte < size; byte++, plen += 8)
|
||||
if (pname[byte] != 0xff)
|
||||
break;
|
||||
if (byte == size)
|
||||
return (plen);
|
||||
for (bit = 7; bit != 0; bit--, plen++)
|
||||
if (!(pname[byte] & (1 << bit)))
|
||||
break;
|
||||
for (; bit != 0; bit--)
|
||||
if (pname[byte] & (1 << bit))
|
||||
return(0);
|
||||
byte++;
|
||||
for (; byte < size; byte++)
|
||||
if (pname[byte])
|
||||
return(0);
|
||||
return (plen);
|
||||
}
|
||||
|
||||
int
|
||||
setia6flags_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
|
||||
{
|
||||
int64_t ia6flag;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "ia6flag", &ia6flag)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ia6flag < 0) {
|
||||
ia6flag = -ia6flag;
|
||||
ifra->ifra_flags &= ~ia6flag;
|
||||
} else
|
||||
ifra->ifra_flags |= ia6flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setia6pltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
|
||||
{
|
||||
int64_t pltime;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "pltime", &pltime)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setia6lifetime(env, pltime,
|
||||
&ifra->ifra_lifetime.ia6t_preferred,
|
||||
&ifra->ifra_lifetime.ia6t_pltime);
|
||||
}
|
||||
|
||||
int
|
||||
setia6vltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
|
||||
{
|
||||
int64_t vltime;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "vltime", &vltime)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setia6lifetime(env, vltime,
|
||||
&ifra->ifra_lifetime.ia6t_expire,
|
||||
&ifra->ifra_lifetime.ia6t_vltime);
|
||||
}
|
||||
|
||||
static int
|
||||
setia6lifetime(prop_dictionary_t env, int64_t val, time_t *timep,
|
||||
uint32_t *ivalp)
|
||||
{
|
||||
time_t t;
|
||||
int af;
|
||||
|
||||
if ((af = getaf(env)) == -1 || af != AF_INET6) {
|
||||
errx(EXIT_FAILURE,
|
||||
"inet6 address lifetime not allowed for the AF");
|
||||
}
|
||||
|
||||
t = time(NULL);
|
||||
*timep = t + val;
|
||||
*ivalp = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setia6eui64_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
|
||||
{
|
||||
char buf[2][80];
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
const struct sockaddr_in6 *sin6 = NULL;
|
||||
const struct in6_addr *lladdr = NULL;
|
||||
struct in6_addr *in6;
|
||||
const char *ifname;
|
||||
bool doit = false;
|
||||
int af;
|
||||
|
||||
if (!prop_dictionary_get_bool(env, "eui64", &doit) || !doit) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
return -1;
|
||||
|
||||
af = getaf(env);
|
||||
if (af != AF_INET6) {
|
||||
errx(EXIT_FAILURE,
|
||||
"eui64 address modifier not allowed for the AF");
|
||||
}
|
||||
in6 = &ifra->ifra_addr.sin6_addr;
|
||||
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) {
|
||||
union {
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr sa;
|
||||
} any = {.sin6 = {.sin6_family = AF_INET6}};
|
||||
memcpy(&any.sin6.sin6_addr, &in6addr_any,
|
||||
sizeof(any.sin6.sin6_addr));
|
||||
(void)sockaddr_snprintf(buf[0], sizeof(buf[0]), "%a%%S",
|
||||
&any.sa);
|
||||
(void)sockaddr_snprintf(buf[1], sizeof(buf[1]), "%a%%S",
|
||||
(const struct sockaddr *)&ifra->ifra_addr);
|
||||
errx(EXIT_FAILURE, "interface index is already filled, %s | %s",
|
||||
buf[0], buf[1]);
|
||||
}
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
err(EXIT_FAILURE, "getifaddrs");
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6 &&
|
||||
strcmp(ifa->ifa_name, ifname) == 0) {
|
||||
sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
lladdr = &sin6->sin6_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lladdr == NULL)
|
||||
errx(EXIT_FAILURE, "could not determine link local address");
|
||||
|
||||
memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
|
||||
|
||||
freeifaddrs(ifap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX not really an alias */
|
||||
void
|
||||
in6_alias(const char *ifname, prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
struct in6_ifreq *creq)
|
||||
{
|
||||
struct in6_ifreq ifr6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
char hbuf[NI_MAXHOST];
|
||||
u_int32_t scopeid;
|
||||
int s;
|
||||
const int niflag = Nflag ? 0 : NI_NUMERICHOST;
|
||||
unsigned short flags;
|
||||
|
||||
/* Get the non-alias address for this interface. */
|
||||
if ((s = getsock(AF_INET6)) == -1) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
return;
|
||||
err(EXIT_FAILURE, "socket");
|
||||
}
|
||||
|
||||
sin6 = &creq->ifr_addr;
|
||||
|
||||
inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL);
|
||||
scopeid = sin6->sin6_scope_id;
|
||||
if (getnameinfo((const struct sockaddr *)sin6, sin6->sin6_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, niflag))
|
||||
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
|
||||
printf("\tinet6 %s", hbuf);
|
||||
|
||||
if (getifflags(env, oenv, &flags) == -1)
|
||||
err(EXIT_FAILURE, "%s: getifflags", __func__);
|
||||
|
||||
if (flags & IFF_POINTOPOINT) {
|
||||
ifr6 = *creq;
|
||||
if (prog_ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("SIOCGIFDSTADDR_IN6");
|
||||
memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr));
|
||||
ifr6.ifr_addr.sin6_family = AF_INET6;
|
||||
ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
sin6 = &ifr6.ifr_addr;
|
||||
inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL);
|
||||
hbuf[0] = '\0';
|
||||
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, niflag))
|
||||
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
|
||||
printf(" -> %s", hbuf);
|
||||
}
|
||||
|
||||
ifr6 = *creq;
|
||||
if (prog_ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("SIOCGIFNETMASK_IN6");
|
||||
} else {
|
||||
sin6 = &ifr6.ifr_addr;
|
||||
printf(" prefixlen %d", prefix(&sin6->sin6_addr,
|
||||
sizeof(struct in6_addr)));
|
||||
}
|
||||
|
||||
ifr6 = *creq;
|
||||
if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("SIOCGIFAFLAG_IN6");
|
||||
} else {
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
|
||||
printf(" anycast");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
||||
printf(" tentative");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED)
|
||||
printf(" duplicated");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED)
|
||||
printf(" detached");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
||||
printf(" deprecated");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF)
|
||||
printf(" autoconf");
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY)
|
||||
printf(" temporary");
|
||||
}
|
||||
|
||||
if (scopeid)
|
||||
printf(" scopeid 0x%x", scopeid);
|
||||
|
||||
if (get_flag('L')) {
|
||||
struct in6_addrlifetime *lifetime;
|
||||
ifr6 = *creq;
|
||||
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
|
||||
if (prog_ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("SIOCGIFALIFETIME_IN6");
|
||||
} else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
|
||||
time_t t = time(NULL);
|
||||
printf(" pltime ");
|
||||
if (lifetime->ia6t_preferred) {
|
||||
printf("%lu",
|
||||
(unsigned long)(lifetime->ia6t_preferred -
|
||||
MIN(t, lifetime->ia6t_preferred)));
|
||||
} else
|
||||
printf("infty");
|
||||
|
||||
printf(" vltime ");
|
||||
if (lifetime->ia6t_expire) {
|
||||
printf("%lu",
|
||||
(unsigned long)(lifetime->ia6t_expire -
|
||||
MIN(t, lifetime->ia6t_expire)));
|
||||
} else
|
||||
printf("infty");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
if (sizeof(ifr.ifr_addr) < ifa->ifa_addr->sa_len)
|
||||
continue;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
in6_pre_aifaddr(prop_dictionary_t env, const struct afparam *param)
|
||||
{
|
||||
struct in6_aliasreq *ifra = param->req.buf;
|
||||
|
||||
setia6eui64_impl(env, ifra);
|
||||
setia6vltime_impl(env, ifra);
|
||||
setia6pltime_impl(env, ifra);
|
||||
setia6flags_impl(env, ifra);
|
||||
inet6_putscopeid(&ifra->ifra_addr, INET6_IS_ADDR_LINKLOCAL);
|
||||
inet6_putscopeid(&ifra->ifra_dstaddr, INET6_IS_ADDR_LINKLOCAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
in6_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct in6_ifreq in6_ifr = {
|
||||
.ifr_addr = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_len = sizeof(in6_ifr.ifr_addr),
|
||||
.sin6_addr = {
|
||||
.s6_addr =
|
||||
{0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff}
|
||||
}
|
||||
}
|
||||
};
|
||||
static struct sockaddr_in6 in6_defmask = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_len = sizeof(in6_defmask),
|
||||
.sin6_addr = {
|
||||
.s6_addr = {0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff}
|
||||
}
|
||||
};
|
||||
|
||||
struct in6_aliasreq in6_ifra = {
|
||||
.ifra_prefixmask = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_len = sizeof(in6_ifra.ifra_prefixmask),
|
||||
.sin6_addr = {
|
||||
.s6_addr =
|
||||
{0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff}}},
|
||||
.ifra_lifetime = {
|
||||
.ia6t_pltime = ND6_INFINITE_LIFETIME
|
||||
, .ia6t_vltime = ND6_INFINITE_LIFETIME
|
||||
}
|
||||
};
|
||||
struct afparam in6param = {
|
||||
.req = BUFPARAM(in6_ifra)
|
||||
, .dgreq = BUFPARAM(in6_ifr)
|
||||
, .name = {
|
||||
{.buf = in6_ifr.ifr_name,
|
||||
.buflen = sizeof(in6_ifr.ifr_name)},
|
||||
{.buf = in6_ifra.ifra_name,
|
||||
.buflen = sizeof(in6_ifra.ifra_name)}
|
||||
}
|
||||
, .dgaddr = BUFPARAM(in6_ifr.ifr_addr)
|
||||
, .addr = BUFPARAM(in6_ifra.ifra_addr)
|
||||
, .dst = BUFPARAM(in6_ifra.ifra_dstaddr)
|
||||
, .brd = BUFPARAM(in6_ifra.ifra_broadaddr)
|
||||
, .mask = BUFPARAM(in6_ifra.ifra_prefixmask)
|
||||
, .aifaddr = IFADDR_PARAM(SIOCAIFADDR_IN6)
|
||||
, .difaddr = IFADDR_PARAM(SIOCDIFADDR_IN6)
|
||||
, .gifaddr = IFADDR_PARAM(SIOCGIFADDR_IN6)
|
||||
, .defmask = BUFPARAM(in6_defmask)
|
||||
, .pre_aifaddr = in6_pre_aifaddr
|
||||
};
|
||||
commit_address(env, oenv, &in6param);
|
||||
}
|
||||
|
||||
static bool
|
||||
in6_addr_tentative(struct ifaddrs *ifa)
|
||||
{
|
||||
int s;
|
||||
struct in6_ifreq ifr;
|
||||
|
||||
if ((s = getsock(AF_INET6)) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_addr = *(struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCGIFAFLAG_IN6");
|
||||
return ifr.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE ? true : false;
|
||||
}
|
||||
|
||||
static void
|
||||
in6_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n"
|
||||
"\t[ pltime n ] [ vltime n ] "
|
||||
"[ eui64 ]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
in6_constructor(void)
|
||||
{
|
||||
if (register_flag('L') != 0)
|
||||
err(EXIT_FAILURE, __func__);
|
||||
register_family(&in6af);
|
||||
usage_func_init(&usage, in6_usage);
|
||||
register_usage(&usage);
|
||||
cmdloop_branch_init(&branch[0], &ia6flags.pk_parser);
|
||||
cmdloop_branch_init(&branch[1], &inet6.pk_parser);
|
||||
register_cmdloop_branch(&branch[0]);
|
||||
register_cmdloop_branch(&branch[1]);
|
||||
}
|
||||
179
sbin/ifconfig/af_inetany.c
Normal file
179
sbin/ifconfig/af_inetany.c
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/* $NetBSD: af_inetany.c,v 1.17 2012/12/30 22:52:35 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_inetany.c,v 1.17 2012/12/30 22:52:35 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "af_inetany.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
static void *
|
||||
loadbuf(const struct apbuf *b, const struct paddr_prefix *pfx)
|
||||
{
|
||||
return memcpy(b->buf, &pfx->pfx_addr,
|
||||
MIN(b->buflen, pfx->pfx_addr.sa_len));
|
||||
}
|
||||
|
||||
void
|
||||
commit_address(prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
const struct afparam *param)
|
||||
{
|
||||
const char *ifname;
|
||||
int af, rc, s;
|
||||
bool alias, delete, replace;
|
||||
prop_data_t d;
|
||||
const struct paddr_prefix *addr, *brd, *dst, *mask;
|
||||
unsigned short flags;
|
||||
|
||||
if ((af = getaf(env)) == -1)
|
||||
af = AF_INET;
|
||||
|
||||
if ((s = getsock(af)) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "%s: getifname", __func__);
|
||||
|
||||
strlcpy(param->name[0].buf, ifname, param->name[0].buflen);
|
||||
strlcpy(param->name[1].buf, ifname, param->name[1].buflen);
|
||||
|
||||
if ((d = (prop_data_t)prop_dictionary_get(env, "address")) != NULL)
|
||||
addr = prop_data_data_nocopy(d);
|
||||
else if (!prop_dictionary_get_bool(env, "alias", &alias) || alias ||
|
||||
param->gifaddr.cmd == 0)
|
||||
return;
|
||||
else if (prog_ioctl(s, param->gifaddr.cmd, param->dgreq.buf) == -1)
|
||||
err(EXIT_FAILURE, "%s", param->gifaddr.desc);
|
||||
else if (prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf) == -1)
|
||||
err(EXIT_FAILURE, "%s", param->difaddr.desc);
|
||||
else
|
||||
return;
|
||||
|
||||
if ((d = (prop_data_t)prop_dictionary_get(env, "dst")) != NULL)
|
||||
dst = prop_data_data_nocopy(d);
|
||||
else
|
||||
dst = NULL;
|
||||
|
||||
if ((d = (prop_data_t)prop_dictionary_get(env, "netmask")) != NULL)
|
||||
mask = prop_data_data_nocopy(d);
|
||||
else
|
||||
mask = NULL;
|
||||
|
||||
if ((d = (prop_data_t)prop_dictionary_get(env, "broadcast")) != NULL)
|
||||
brd = prop_data_data_nocopy(d);
|
||||
else
|
||||
brd = NULL;
|
||||
|
||||
if (!prop_dictionary_get_bool(env, "alias", &alias)) {
|
||||
delete = false;
|
||||
replace = (param->gifaddr.cmd != 0);
|
||||
} else {
|
||||
replace = false;
|
||||
delete = !alias;
|
||||
}
|
||||
|
||||
loadbuf(¶m->addr, addr);
|
||||
|
||||
/* TBD: read matching ifaddr from kernel, use the netmask as default
|
||||
* TBD: handle preference
|
||||
*/
|
||||
if (getifflags(env, oenv, &flags) == -1)
|
||||
err(EXIT_FAILURE, "%s: getifflags", __func__);
|
||||
|
||||
switch (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) {
|
||||
case IFF_BROADCAST:
|
||||
if (brd != NULL)
|
||||
loadbuf(¶m->brd, brd);
|
||||
/*FALLTHROUGH*/
|
||||
case 0:
|
||||
break;
|
||||
case IFF_POINTOPOINT:
|
||||
if (brd != NULL) {
|
||||
errx(EXIT_FAILURE, "%s is not a broadcast interface",
|
||||
ifname);
|
||||
}
|
||||
if (dst != NULL)
|
||||
loadbuf(¶m->dst, dst);
|
||||
break;
|
||||
case IFF_BROADCAST|IFF_POINTOPOINT:
|
||||
errx(EXIT_FAILURE, "unsupported interface flags");
|
||||
}
|
||||
if (param->mask.buf == NULL) {
|
||||
if (mask != NULL)
|
||||
errx(EXIT_FAILURE, "netmask not supported");
|
||||
} else if (mask != NULL)
|
||||
loadbuf(¶m->mask, mask);
|
||||
else if (param->defmask.buf != NULL) {
|
||||
memcpy(param->mask.buf, param->defmask.buf,
|
||||
MIN(param->mask.buflen, param->defmask.buflen));
|
||||
}
|
||||
if (replace) {
|
||||
if (prog_ioctl(s, param->gifaddr.cmd, param->dgreq.buf) == 0) {
|
||||
rc = prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf);
|
||||
if (rc == -1)
|
||||
err(EXIT_FAILURE, "%s", param->difaddr.desc);
|
||||
} else if (errno == EADDRNOTAVAIL)
|
||||
; /* No address was assigned yet. */
|
||||
else
|
||||
err(EXIT_FAILURE, "%s", param->gifaddr.desc);
|
||||
} else if (delete) {
|
||||
loadbuf(¶m->dgaddr, addr);
|
||||
if (prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf) == -1)
|
||||
err(EXIT_FAILURE, "%s", param->difaddr.desc);
|
||||
return;
|
||||
}
|
||||
if (param->pre_aifaddr != NULL &&
|
||||
(*param->pre_aifaddr)(env, param) == -1)
|
||||
err(EXIT_FAILURE, "pre-%s", param->aifaddr.desc);
|
||||
if (prog_ioctl(s, param->aifaddr.cmd, param->req.buf) == -1)
|
||||
err(EXIT_FAILURE, "%s", param->aifaddr.desc);
|
||||
}
|
||||
59
sbin/ifconfig/af_inetany.h
Normal file
59
sbin/ifconfig/af_inetany.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* $NetBSD: af_inetany.h,v 1.4 2008/07/02 07:44:14 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IFCONFIG_AF_INETANY_H
|
||||
#define _IFCONFIG_AF_INETANY_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <prop/proplib.h>
|
||||
|
||||
#define IFADDR_PARAM(__arg) {.cmd = (__arg), .desc = #__arg}
|
||||
#define BUFPARAM(__arg) {.buf = &(__arg), .buflen = sizeof(__arg)}
|
||||
|
||||
struct apbuf {
|
||||
void *buf;
|
||||
size_t buflen;
|
||||
};
|
||||
|
||||
struct afparam {
|
||||
struct {
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
} name[2];
|
||||
struct apbuf dgaddr, addr, brd, dst, mask, req, dgreq, defmask,
|
||||
pre_aifaddr_arg;
|
||||
struct {
|
||||
unsigned long cmd;
|
||||
const char *desc;
|
||||
} aifaddr, difaddr, gifaddr;
|
||||
int (*pre_aifaddr)(prop_dictionary_t, const struct afparam *);
|
||||
};
|
||||
|
||||
void commit_address(prop_dictionary_t, prop_dictionary_t,
|
||||
const struct afparam *);
|
||||
|
||||
#endif /* _IFCONFIG_AF_INETANY_H */
|
||||
132
sbin/ifconfig/af_link.c
Normal file
132
sbin/ifconfig/af_link.c
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* $NetBSD: af_link.c,v 1.7 2014/01/19 22:31:13 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: af_link.c,v 1.7 2014/01/19 22:31:13 matt Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "af_inetany.h"
|
||||
|
||||
static void link_status(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
static void link_commit_address(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
static const struct kwinst linkkw[] = {
|
||||
{.k_word = "active", .k_key = "active", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_nextparser = &command_root.pb_parser}
|
||||
};
|
||||
|
||||
struct pkw link_pkw = PKW_INITIALIZER(&link_pkw, "link", NULL, NULL,
|
||||
linkkw, __arraycount(linkkw), NULL);
|
||||
|
||||
static struct afswtch af = {
|
||||
.af_name = "link", .af_af = AF_LINK, .af_status = link_status,
|
||||
.af_addr_commit = link_commit_address
|
||||
};
|
||||
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void link_constructor(void) __attribute__((constructor));
|
||||
|
||||
static void
|
||||
link_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
|
||||
{
|
||||
print_link_addresses(env, false);
|
||||
}
|
||||
|
||||
static int
|
||||
link_pre_aifaddr(prop_dictionary_t env, const struct afparam *param)
|
||||
{
|
||||
bool active;
|
||||
struct if_laddrreq *iflr = param->req.buf;
|
||||
|
||||
if (prop_dictionary_get_bool(env, "active", &active) && active)
|
||||
iflr->flags |= IFLR_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
link_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct if_laddrreq dgreq = {
|
||||
.addr = {
|
||||
.ss_family = AF_LINK,
|
||||
.ss_len = sizeof(dgreq.addr),
|
||||
},
|
||||
};
|
||||
struct if_laddrreq req = {
|
||||
.addr = {
|
||||
.ss_family = AF_LINK,
|
||||
.ss_len = sizeof(req.addr),
|
||||
}
|
||||
};
|
||||
struct afparam linkparam = {
|
||||
.req = BUFPARAM(req)
|
||||
, .dgreq = BUFPARAM(dgreq)
|
||||
, .name = {
|
||||
{.buf = dgreq.iflr_name,
|
||||
.buflen = sizeof(dgreq.iflr_name)},
|
||||
{.buf = req.iflr_name,
|
||||
.buflen = sizeof(req.iflr_name)}
|
||||
}
|
||||
, .dgaddr = BUFPARAM(dgreq.addr)
|
||||
, .addr = BUFPARAM(req.addr)
|
||||
, .aifaddr = IFADDR_PARAM(SIOCALIFADDR)
|
||||
, .difaddr = IFADDR_PARAM(SIOCDLIFADDR)
|
||||
, .gifaddr = IFADDR_PARAM(0)
|
||||
, .pre_aifaddr = link_pre_aifaddr
|
||||
};
|
||||
commit_address(env, oenv, &linkparam);
|
||||
}
|
||||
|
||||
static void
|
||||
link_constructor(void)
|
||||
{
|
||||
register_family(&af);
|
||||
cmdloop_branch_init(&branch, &link_pkw.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
}
|
||||
195
sbin/ifconfig/agr.c
Normal file
195
sbin/ifconfig/agr.c
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* $NetBSD: agr.c,v 1.15 2008/07/15 21:27:58 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c)2005 YAMAMOTO Takashi,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: agr.c,v 1.15 2008/07/15 21:27:58 dyoung Exp $");
|
||||
#endif /* !defined(lint) */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/agr/if_agrioctl.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
|
||||
static int agrsetport(prop_dictionary_t, prop_dictionary_t);
|
||||
static void agr_constructor(void) __attribute__((constructor));
|
||||
static int checkifname(prop_dictionary_t);
|
||||
static void assertifname(prop_dictionary_t);
|
||||
|
||||
static struct piface agrif = PIFACE_INITIALIZER(&agrif, "agr interface",
|
||||
agrsetport, "agrport", &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst agrkw[] = {
|
||||
{.k_word = "agrport", .k_type = KW_T_INT, .k_int = AGRCMD_ADDPORT,
|
||||
.k_nextparser = &agrif.pif_parser}
|
||||
, {.k_word = "-agrport", .k_type = KW_T_INT, .k_int = AGRCMD_REMPORT,
|
||||
.k_nextparser = &agrif.pif_parser}
|
||||
};
|
||||
|
||||
struct pkw agr = PKW_INITIALIZER(&agr, "agr", NULL, "agrcmd",
|
||||
agrkw, __arraycount(agrkw), NULL);
|
||||
|
||||
static int
|
||||
checkifname(prop_dictionary_t env)
|
||||
{
|
||||
const char *ifname;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
return 1;
|
||||
|
||||
return strncmp(ifname, "agr", 3) != 0 ||
|
||||
!isdigit((unsigned char)ifname[3]);
|
||||
}
|
||||
|
||||
static void
|
||||
assertifname(prop_dictionary_t env)
|
||||
{
|
||||
if (checkifname(env))
|
||||
errx(EXIT_FAILURE, "valid only with agr(4) interfaces");
|
||||
}
|
||||
|
||||
int
|
||||
agrsetport(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
char buf[IFNAMSIZ];
|
||||
struct agrreq ar;
|
||||
const char *port;
|
||||
int64_t cmd;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "agrcmd", &cmd)) {
|
||||
warnx("%s.%d", __func__, __LINE__);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prop_dictionary_get_cstring_nocopy(env, "agrport", &port)) {
|
||||
warnx("%s.%d", __func__, __LINE__);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
strlcpy(buf, port, sizeof(buf));
|
||||
|
||||
assertifname(env);
|
||||
memset(&ar, 0, sizeof(ar));
|
||||
ar.ar_version = AGRREQ_VERSION;
|
||||
ar.ar_cmd = cmd;
|
||||
ar.ar_buf = buf;
|
||||
ar.ar_buflen = strlen(buf);
|
||||
|
||||
if (indirect_ioctl(env, SIOCSETAGR, &ar) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSETAGR");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
agr_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct agrreq ar;
|
||||
void *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
struct agrportlist *apl;
|
||||
struct agrportinfo *api;
|
||||
int i;
|
||||
|
||||
if (checkifname(env))
|
||||
return;
|
||||
|
||||
again:
|
||||
memset(&ar, 0, sizeof(ar));
|
||||
ar.ar_version = AGRREQ_VERSION;
|
||||
ar.ar_cmd = AGRCMD_PORTLIST;
|
||||
ar.ar_buf = buf;
|
||||
ar.ar_buflen = buflen;
|
||||
|
||||
if (indirect_ioctl(env, SIOCGETAGR, &ar) == -1) {
|
||||
if (errno != E2BIG) {
|
||||
warn("SIOCGETAGR");
|
||||
return;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
buflen = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (buf == NULL) {
|
||||
buflen = ar.ar_buflen;
|
||||
buf = malloc(buflen);
|
||||
if (buf == NULL) {
|
||||
err(EXIT_FAILURE, "agr_status");
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
apl = buf;
|
||||
api = (void *)(apl + 1);
|
||||
|
||||
for (i = 0; i < apl->apl_nports; i++) {
|
||||
char tmp[256];
|
||||
|
||||
snprintb(tmp, sizeof(tmp), AGRPORTINFO_BITS, api->api_flags);
|
||||
printf("\tagrport: %s, flags=%s\n", api->api_ifname, tmp);
|
||||
api++;
|
||||
}
|
||||
}
|
||||
|
||||
static status_func_t status;
|
||||
static usage_func_t usage;
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void
|
||||
agr_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr, "\t[ agrport i ] [ -agrport i ]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
agr_constructor(void)
|
||||
{
|
||||
status_func_init(&status, agr_status);
|
||||
usage_func_init(&usage, agr_usage);
|
||||
register_status(&status);
|
||||
register_usage(&usage);
|
||||
cmdloop_branch_init(&branch, &agr.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
}
|
||||
295
sbin/ifconfig/carp.c
Normal file
295
sbin/ifconfig/carp.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/* $NetBSD: carp.c,v 1.13 2009/09/11 23:22:28 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
|
||||
* Copyright (c) 2003 Ryan McBride. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: carp.c,v 1.13 2009/09/11 23:22:28 dyoung Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/ip_carp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "parse.h"
|
||||
#include "extern.h"
|
||||
|
||||
static status_func_t status;
|
||||
static usage_func_t usage;
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void carp_constructor(void) __attribute__((constructor));
|
||||
static void carp_status(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarp_advbase(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarp_advskew(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarp_passwd(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarp_vhid(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarp_state(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setcarpdev(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
static const char *carp_states[] = { CARP_STATES };
|
||||
|
||||
struct kwinst carpstatekw[] = {
|
||||
{.k_word = "INIT", .k_nextparser = &command_root.pb_parser}
|
||||
, {.k_word = "BACKUP", .k_nextparser = &command_root.pb_parser}
|
||||
, {.k_word = "MASTER", .k_nextparser = &command_root.pb_parser}
|
||||
};
|
||||
|
||||
struct pinteger parse_advbase = PINTEGER_INITIALIZER1(&parse_advbase, "advbase",
|
||||
0, 255, 10, setcarp_advbase, "advbase", &command_root.pb_parser);
|
||||
|
||||
struct pinteger parse_advskew = PINTEGER_INITIALIZER1(&parse_advskew, "advskew",
|
||||
0, 254, 10, setcarp_advskew, "advskew", &command_root.pb_parser);
|
||||
|
||||
struct piface carpdev = PIFACE_INITIALIZER(&carpdev, "carpdev", setcarpdev,
|
||||
"carpdev", &command_root.pb_parser);
|
||||
|
||||
struct pkw carpstate = PKW_INITIALIZER(&carpstate, "carp state", setcarp_state,
|
||||
"carp_state", carpstatekw, __arraycount(carpstatekw),
|
||||
&command_root.pb_parser);
|
||||
|
||||
struct pstr pass = PSTR_INITIALIZER(&pass, "pass", setcarp_passwd,
|
||||
"pass", &command_root.pb_parser);
|
||||
|
||||
struct pinteger parse_vhid = PINTEGER_INITIALIZER1(&vhid, "vhid",
|
||||
0, 255, 10, setcarp_vhid, "vhid", &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst carpkw[] = {
|
||||
{.k_word = "advbase", .k_nextparser = &parse_advbase.pi_parser}
|
||||
, {.k_word = "advskew", .k_nextparser = &parse_advskew.pi_parser}
|
||||
, {.k_word = "carpdev", .k_nextparser = &carpdev.pif_parser}
|
||||
, {.k_word = "-carpdev", .k_key = "carpdev", .k_type = KW_T_STR,
|
||||
.k_str = "", .k_exec = setcarpdev,
|
||||
.k_nextparser = &command_root.pb_parser}
|
||||
, {.k_word = "pass", .k_nextparser = &pass.ps_parser}
|
||||
, {.k_word = "state", .k_nextparser = &carpstate.pk_parser}
|
||||
, {.k_word = "vhid", .k_nextparser = &parse_vhid.pi_parser}
|
||||
};
|
||||
|
||||
struct pkw carp = PKW_INITIALIZER(&carp, "CARP", NULL, NULL,
|
||||
carpkw, __arraycount(carpkw), NULL);
|
||||
|
||||
static void
|
||||
carp_set(prop_dictionary_t env, struct carpreq *carpr)
|
||||
{
|
||||
if (indirect_ioctl(env, SIOCSVH, carpr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSVH");
|
||||
}
|
||||
|
||||
static int
|
||||
carp_get1(prop_dictionary_t env, struct carpreq *carpr)
|
||||
{
|
||||
memset(carpr, 0, sizeof(*carpr));
|
||||
|
||||
return indirect_ioctl(env, SIOCGVH, carpr);
|
||||
}
|
||||
|
||||
static void
|
||||
carp_get(prop_dictionary_t env, struct carpreq *carpr)
|
||||
{
|
||||
if (carp_get1(env, carpr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCGVH");
|
||||
}
|
||||
|
||||
static void
|
||||
carp_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
const char *state;
|
||||
struct carpreq carpr;
|
||||
|
||||
if (carp_get1(env, &carpr) == -1)
|
||||
return;
|
||||
|
||||
if (carpr.carpr_vhid <= 0)
|
||||
return;
|
||||
if (carpr.carpr_state > CARP_MAXSTATE)
|
||||
state = "<UNKNOWN>";
|
||||
else
|
||||
state = carp_states[carpr.carpr_state];
|
||||
|
||||
printf("\tcarp: %s carpdev %s vhid %d advbase %d advskew %d\n",
|
||||
state, carpr.carpr_carpdev[0] != '\0' ?
|
||||
carpr.carpr_carpdev : "none", carpr.carpr_vhid,
|
||||
carpr.carpr_advbase, carpr.carpr_advskew);
|
||||
}
|
||||
|
||||
int
|
||||
setcarp_passwd(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
prop_data_t data;
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "pass");
|
||||
if (data == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
memset(carpr.carpr_key, 0, sizeof(carpr.carpr_key));
|
||||
/* XXX Should hash the password into the key here, perhaps? */
|
||||
strlcpy((char *)carpr.carpr_key, prop_data_data_nocopy(data),
|
||||
MIN(CARP_KEY_LEN, prop_data_size(data)));
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setcarp_vhid(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
int64_t vhid;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "vhid", &vhid)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
carpr.carpr_vhid = vhid;
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setcarp_advskew(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
int64_t advskew;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "advskew", &advskew)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
carpr.carpr_advskew = advskew;
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
setcarp_advbase(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
int64_t advbase;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "advbase", &advbase)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
carpr.carpr_advbase = advbase;
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
setcarp_state(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
int64_t carp_state;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "carp_state", &carp_state)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
carpr.carpr_state = carp_state;
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
setcarpdev(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
prop_string_t s;
|
||||
|
||||
s = (prop_string_t)prop_dictionary_get(env, "carpdev");
|
||||
if (s == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
carp_get(env, &carpr);
|
||||
|
||||
strlcpy(carpr.carpr_carpdev, prop_string_cstring_nocopy(s),
|
||||
sizeof(carpr.carpr_carpdev));
|
||||
|
||||
carp_set(env, &carpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
carp_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\t[ advbase n ] [ advskew n ] [ carpdev iface ] "
|
||||
"[ pass passphrase ] [ state state ] [ vhid n ]\n");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
carp_constructor(void)
|
||||
{
|
||||
cmdloop_branch_init(&branch, &carp.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
status_func_init(&status, carp_status);
|
||||
usage_func_init(&usage, carp_usage);
|
||||
register_status(&status);
|
||||
register_usage(&usage);
|
||||
}
|
||||
180
sbin/ifconfig/env.c
Normal file
180
sbin/ifconfig/env.c
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/* $NetBSD: env.c,v 1.9 2013/02/07 13:20:51 apb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: env.c,v 1.9 2013/02/07 13:20:51 apb Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "util.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
prop_dictionary_t
|
||||
prop_dictionary_augment(prop_dictionary_t bottom, prop_dictionary_t top)
|
||||
{
|
||||
prop_object_iterator_t i;
|
||||
prop_dictionary_t d;
|
||||
prop_object_t ko, o;
|
||||
prop_dictionary_keysym_t k;
|
||||
const char *key;
|
||||
|
||||
d = prop_dictionary_copy_mutable(bottom);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
i = prop_dictionary_iterator(top);
|
||||
|
||||
while (i != NULL && (ko = prop_object_iterator_next(i)) != NULL) {
|
||||
k = (prop_dictionary_keysym_t)ko;
|
||||
key = prop_dictionary_keysym_cstring_nocopy(k);
|
||||
o = prop_dictionary_get_keysym(top, k);
|
||||
if (o == NULL || !prop_dictionary_set(d, key, o)) {
|
||||
prop_object_release((prop_object_t)d);
|
||||
d = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NULL)
|
||||
prop_object_iterator_release(i);
|
||||
if (d != NULL)
|
||||
prop_dictionary_make_immutable(d);
|
||||
return d;
|
||||
}
|
||||
|
||||
int
|
||||
getifflags(prop_dictionary_t env, prop_dictionary_t oenv,
|
||||
unsigned short *flagsp)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
const char *ifname;
|
||||
uint64_t ifflags;
|
||||
int s;
|
||||
|
||||
if (prop_dictionary_get_uint64(env, "ifflags", &ifflags)) {
|
||||
*flagsp = (unsigned short)ifflags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((s = getsock(AF_UNSPEC)) == -1)
|
||||
return -1;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
return -1;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
if (prog_ioctl(s, SIOCGIFFLAGS, &ifr) == -1)
|
||||
return -1;
|
||||
|
||||
*flagsp = (unsigned short)ifr.ifr_flags;
|
||||
|
||||
prop_dictionary_set_uint64(oenv, "ifflags",
|
||||
(unsigned short)ifr.ifr_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
getifinfo(prop_dictionary_t env, prop_dictionary_t oenv, unsigned short *flagsp)
|
||||
{
|
||||
if (getifflags(env, oenv, flagsp) == -1)
|
||||
return NULL;
|
||||
|
||||
return getifname(env);
|
||||
}
|
||||
|
||||
const char *
|
||||
getifname(prop_dictionary_t env)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
return prop_dictionary_get_cstring_nocopy(env, "if", &s) ? s : NULL;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
getargdata(prop_dictionary_t env, const char *key, uint8_t *buf, size_t buflen)
|
||||
{
|
||||
prop_data_t data;
|
||||
size_t datalen;
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, key);
|
||||
if (data == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
datalen = prop_data_size(data);
|
||||
if (datalen > buflen) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, buflen);
|
||||
memcpy(buf, prop_data_data_nocopy(data), datalen);
|
||||
return datalen;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
getargstr(prop_dictionary_t env, const char *key, char *buf, size_t buflen)
|
||||
{
|
||||
prop_data_t data;
|
||||
size_t datalen;
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, key);
|
||||
if (data == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
datalen = prop_data_size(data);
|
||||
if (datalen >= buflen) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, buflen);
|
||||
memcpy(buf, prop_data_data_nocopy(data), datalen);
|
||||
return datalen;
|
||||
}
|
||||
|
||||
int
|
||||
getaf(prop_dictionary_t env)
|
||||
{
|
||||
int64_t af;
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "af", &af)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return (int)af;
|
||||
}
|
||||
25
sbin/ifconfig/env.h
Normal file
25
sbin/ifconfig/env.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _IFCONFIG_ENV_H
|
||||
#define _IFCONFIG_ENV_H
|
||||
|
||||
#include <prop/proplib.h>
|
||||
|
||||
const char *getifname(prop_dictionary_t);
|
||||
ssize_t getargstr(prop_dictionary_t, const char *, char *, size_t);
|
||||
ssize_t getargdata(prop_dictionary_t, const char *, uint8_t *, size_t);
|
||||
int getaf(prop_dictionary_t);
|
||||
int getifflags(prop_dictionary_t, prop_dictionary_t, unsigned short *);
|
||||
const char *getifinfo(prop_dictionary_t, prop_dictionary_t, unsigned short *);
|
||||
prop_dictionary_t prop_dictionary_augment(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
/*
|
||||
* XXX: this really doesn't belong in here, but env.h is conveniently
|
||||
* included from all source modules *after* system headers, so it
|
||||
* allows us to be lazy. See Makefile for more details.
|
||||
*/
|
||||
#ifdef RUMP_ACTION
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
#include <rump/rumpclient.h>
|
||||
#endif /* RUMP_ACTION */
|
||||
|
||||
#endif /* _IFCONFIG_ENV_H */
|
||||
99
sbin/ifconfig/ether.c
Normal file
99
sbin/ifconfig/ether.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* $NetBSD: ether.c,v 1.2 2012/11/01 13:43:23 pgoyette Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ether.c,v 1.2 2012/11/01 13:43:23 pgoyette Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_ether.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "parse.h"
|
||||
#include "extern.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
static void ether_status(prop_dictionary_t, prop_dictionary_t);
|
||||
static void ether_constructor(void) __attribute__((constructor));
|
||||
|
||||
static status_func_t status;
|
||||
|
||||
#define MAX_PRINT_LEN 55
|
||||
|
||||
void
|
||||
ether_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct eccapreq eccr;
|
||||
char fbuf[BUFSIZ];
|
||||
char *bp;
|
||||
|
||||
memset(&eccr, 0, sizeof(eccr));
|
||||
|
||||
if (direct_ioctl(env, SIOCGETHERCAP, &eccr) == -1)
|
||||
return;
|
||||
|
||||
if (eccr.eccr_capabilities != 0) {
|
||||
(void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS,
|
||||
eccr.eccr_capabilities, MAX_PRINT_LEN);
|
||||
bp = fbuf;
|
||||
while (*bp != '\0') {
|
||||
printf("\tec_capabilities=%s\n", &bp[2]);
|
||||
bp += strlen(bp) + 1;
|
||||
}
|
||||
(void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS,
|
||||
eccr.eccr_capenable, MAX_PRINT_LEN);
|
||||
bp = fbuf;
|
||||
while (*bp != '\0') {
|
||||
printf("\tec_enabled=%s\n", &bp[2]);
|
||||
bp += strlen(bp) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ether_constructor(void)
|
||||
{
|
||||
|
||||
status_func_init(&status, ether_status);
|
||||
register_status(&status);
|
||||
}
|
||||
93
sbin/ifconfig/extern.h
Normal file
93
sbin/ifconfig/extern.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* $NetBSD: extern.h,v 1.14 2009/08/07 18:53:37 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _IFCONFIG_EXTERN_H
|
||||
#define _IFCONFIG_EXTERN_H
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include "util.h"
|
||||
|
||||
#define RIDADDR 0
|
||||
#define ADDR 1
|
||||
#define MASK 2
|
||||
#define DSTADDR 3
|
||||
|
||||
typedef void (*usage_cb_t)(prop_dictionary_t);
|
||||
typedef void (*status_cb_t)(prop_dictionary_t, prop_dictionary_t);
|
||||
typedef void (*statistics_cb_t)(prop_dictionary_t);
|
||||
|
||||
enum flag_type {
|
||||
FLAG_T_MOD = 0
|
||||
, FLAG_T_CMD = 1
|
||||
};
|
||||
|
||||
typedef enum flag_type flag_type_t;
|
||||
|
||||
struct statistics_func {
|
||||
SIMPLEQ_ENTRY(statistics_func) f_next;
|
||||
statistics_cb_t f_func;
|
||||
};
|
||||
|
||||
struct usage_func {
|
||||
SIMPLEQ_ENTRY(usage_func) f_next;
|
||||
usage_cb_t f_func;
|
||||
};
|
||||
|
||||
struct status_func {
|
||||
SIMPLEQ_ENTRY(status_func) f_next;
|
||||
status_cb_t f_func;
|
||||
};
|
||||
|
||||
struct cmdloop_branch {
|
||||
SIMPLEQ_ENTRY(cmdloop_branch) b_next;
|
||||
struct parser *b_parser;
|
||||
};
|
||||
|
||||
|
||||
typedef struct statistics_func statistics_func_t;
|
||||
typedef struct status_func status_func_t;
|
||||
typedef struct usage_func usage_func_t;
|
||||
typedef struct cmdloop_branch cmdloop_branch_t;
|
||||
|
||||
void cmdloop_branch_init(cmdloop_branch_t *, struct parser *);
|
||||
int register_family(struct afswtch *);
|
||||
int register_cmdloop_branch(cmdloop_branch_t *);
|
||||
void statistics_func_init(statistics_func_t *, statistics_cb_t);
|
||||
void status_func_init(status_func_t *, status_cb_t);
|
||||
void usage_func_init(usage_func_t *, usage_cb_t);
|
||||
int register_statistics(statistics_func_t *);
|
||||
int register_status(status_func_t *);
|
||||
int register_usage(usage_func_t *);
|
||||
int register_flag(int);
|
||||
bool get_flag(int);
|
||||
|
||||
extern bool lflag, Nflag, vflag, zflag;
|
||||
|
||||
#endif /* _IFCONFIG_EXTERN_H */
|
||||
1375
sbin/ifconfig/ieee80211.c
Normal file
1375
sbin/ifconfig/ieee80211.c
Normal file
File diff suppressed because it is too large
Load Diff
920
sbin/ifconfig/ifconfig.8
Normal file
920
sbin/ifconfig/ifconfig.8
Normal file
|
|
@ -0,0 +1,920 @@
|
|||
.\" $NetBSD: ifconfig.8,v 1.109 2014/10/20 14:50:09 roy Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd October 12, 2014
|
||||
.Dt IFCONFIG 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ifconfig
|
||||
.Nd configure network interface parameters
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl N
|
||||
.Ar interface address_family
|
||||
.Oo
|
||||
.Ar address
|
||||
.Op Ar dest_address
|
||||
.Oc
|
||||
.Op Ar parameters
|
||||
.Nm
|
||||
.Op Fl hLmNvz
|
||||
.Ar interface
|
||||
.Op Ar protocol_family
|
||||
.Nm
|
||||
.Fl a
|
||||
.Op Fl bdhLNmsuvz
|
||||
.Op Ar protocol_family
|
||||
.Nm
|
||||
.Fl l
|
||||
.Op Fl bdsu
|
||||
.Nm
|
||||
.Fl s
|
||||
.Ar interface
|
||||
.Nm
|
||||
.Fl w
|
||||
.Ar secs
|
||||
.Nm
|
||||
.Fl C
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is used to assign an address
|
||||
to a network interface and/or configure
|
||||
network interface parameters.
|
||||
.Nm
|
||||
must be used at boot time to define the network address
|
||||
of each interface present on a machine; it may also be used at
|
||||
a later time to redefine an interface's address
|
||||
or other operating parameters.
|
||||
.Pp
|
||||
Available operands for
|
||||
.Nm :
|
||||
.Bl -tag -width Ds
|
||||
.It Ar address
|
||||
For the
|
||||
.Tn DARPA-Internet
|
||||
family,
|
||||
the address is either a host name present in the host name data
|
||||
base,
|
||||
.Xr hosts 5 ,
|
||||
or a
|
||||
.Tn DARPA
|
||||
Internet address expressed in the Internet standard
|
||||
.Dq dot notation .
|
||||
For the Xerox Network Systems(tm) family,
|
||||
addresses are
|
||||
.Ar net:a.b.c.d.e.f ,
|
||||
where
|
||||
.Ar net
|
||||
is the assigned network number
|
||||
.Pq in decimal ,
|
||||
and each of the six bytes of the host number,
|
||||
.Ar a
|
||||
through
|
||||
.Ar f ,
|
||||
are specified in hexadecimal.
|
||||
The host number may be omitted on Ethernet interfaces,
|
||||
which use the hardware physical address,
|
||||
and on interfaces other than the first.
|
||||
For the
|
||||
.Tn ISO
|
||||
family, addresses are specified as a long hexadecimal string,
|
||||
as in the Xerox family.
|
||||
However, two consecutive dots imply a zero
|
||||
byte, and the dots are optional, if the user wishes to
|
||||
.Pq carefully
|
||||
count out long strings of digits in network byte order.
|
||||
.It Ar address_family
|
||||
Specifies the
|
||||
.Ar address_family
|
||||
which affects interpretation of the remaining parameters.
|
||||
Since an interface can receive transmissions in differing protocols
|
||||
with different naming schemes, specifying the address family is recommended.
|
||||
The address or protocol families currently
|
||||
supported are
|
||||
.Dq inet ,
|
||||
.Dq inet6 ,
|
||||
.Dq atalk ,
|
||||
.Dq iso ,
|
||||
and
|
||||
.Dq link .
|
||||
.It Ar interface
|
||||
The
|
||||
.Ar interface
|
||||
parameter is a string of the form
|
||||
.Dq name unit ,
|
||||
for example,
|
||||
.Dq en0
|
||||
.El
|
||||
.Pp
|
||||
The following parameters may be set with
|
||||
.Nm :
|
||||
.Bl -tag -width dest_addressxx
|
||||
.It Cm active
|
||||
This keyword applies when
|
||||
.Nm
|
||||
adds or modifies any link-layer address.
|
||||
It indicates that
|
||||
.Nm
|
||||
should
|
||||
.Dq activate
|
||||
the address.
|
||||
Activation makes an address the default source for transmissions
|
||||
on the interface.
|
||||
You may not delete the active address from an interface.
|
||||
You must activate some other address, first.
|
||||
.It Cm advbase Ar n
|
||||
If the driver is a
|
||||
.Xr carp 4
|
||||
pseudo-device, set the base advertisement interval to
|
||||
.Ar n
|
||||
seconds.
|
||||
This ia an 8-bit number; the default value is 1 second.
|
||||
.It Cm advskew Ar n
|
||||
If the driver is a
|
||||
.Xr carp 4
|
||||
pseudo-device, skew the advertisement interval by
|
||||
.Ar n .
|
||||
This is an 8-bit number; the default value is 0.
|
||||
.Pp
|
||||
Taken together the
|
||||
.Cm advbase
|
||||
indicate how frequently, in seconds, the host will advertise the fact that it
|
||||
considers itself the master of the virtual host.
|
||||
The formula is
|
||||
.Cm advbase
|
||||
+
|
||||
.Pf ( Cm advskew
|
||||
/ 256).
|
||||
If the master does not advertise within three times this interval, this host
|
||||
will begin advertising as master.
|
||||
.It Cm alias
|
||||
Establish an additional network address for this interface.
|
||||
This is sometimes useful when changing network numbers, and
|
||||
one wishes to accept packets addressed to the old interface.
|
||||
.It Fl alias
|
||||
Remove the specified network address alias.
|
||||
.It Cm arp
|
||||
Enable the use of the Address Resolution Protocol in mapping
|
||||
between network level addresses and link level addresses
|
||||
.Pq default .
|
||||
This is currently implemented for mapping between
|
||||
.Tn DARPA
|
||||
Internet
|
||||
addresses and Ethernet addresses.
|
||||
.It Fl arp
|
||||
Disable the use of the Address Resolution Protocol.
|
||||
.It Cm anycast
|
||||
.Pq inet6 only
|
||||
Set the IPv6 anycast address bit.
|
||||
.It Fl anycast
|
||||
.Pq inet6 only
|
||||
Clear the IPv6 anycast address bit.
|
||||
.It Cm broadcast Ar mask
|
||||
.Pq Inet only
|
||||
Specify the address to use to represent broadcasts to the
|
||||
network.
|
||||
The default broadcast address is the address with a host part of all 1's.
|
||||
.It Cm carpdev Ar iface
|
||||
If the driver is a
|
||||
.Xr carp 4
|
||||
pseudo-device, attach it to
|
||||
.Ar iface .
|
||||
If not specified, the kernel will attempt to select an interface with
|
||||
a subnet matching that of the carp interface.
|
||||
.It Cm debug
|
||||
Enable driver dependent debugging code; usually, this turns on
|
||||
extra console error logging.
|
||||
.It Fl debug
|
||||
Disable driver dependent debugging code.
|
||||
.It Cm delete
|
||||
Remove the network address specified.
|
||||
This would be used if you incorrectly specified an alias, or it
|
||||
was no longer needed.
|
||||
If you have incorrectly set an NS address having the side effect
|
||||
of specifying the host portion, removing all NS addresses will
|
||||
allow you to respecify the host portion.
|
||||
.Cm delete
|
||||
does not work for IPv6 addresses.
|
||||
Use
|
||||
.Fl alias
|
||||
with explicit IPv6 address instead.
|
||||
.It Ar dest_address
|
||||
Specify the address of the correspondent on the other end
|
||||
of a point to point link.
|
||||
.It Cm down
|
||||
Mark an interface ``down''.
|
||||
When an interface is
|
||||
marked ``down'', the system will not attempt to
|
||||
transmit messages through that interface.
|
||||
If possible, the interface will be reset to disable reception as well.
|
||||
This action does not automatically disable routes using the interface.
|
||||
.It Cm ipdst
|
||||
This is used to specify an Internet host who is willing to receive
|
||||
ip packets encapsulating NS packets bound for a remote network.
|
||||
An apparent point to point link is constructed, and
|
||||
the address specified will be taken as the NS address and network
|
||||
of the destination.
|
||||
IP encapsulation of
|
||||
.Tn CLNP
|
||||
packets is done differently.
|
||||
.It Cm media Ar type
|
||||
Set the media type of the interface to
|
||||
.Ar type .
|
||||
Some interfaces support the mutually exclusive use of one of several
|
||||
different physical media connectors.
|
||||
For example, a 10Mb/s Ethernet
|
||||
interface might support the use of either
|
||||
.Tn AUI
|
||||
or twisted pair connectors.
|
||||
Setting the media type to
|
||||
.Dq 10base5
|
||||
or
|
||||
.Dq AUI
|
||||
would change the currently active connector to the AUI port.
|
||||
Setting it to
|
||||
.Dq 10baseT
|
||||
or
|
||||
.Dq UTP
|
||||
would activate twisted pair.
|
||||
Refer to the interfaces' driver
|
||||
specific man page for a complete list of the available types
|
||||
and the
|
||||
.Xr ifmedia 4
|
||||
manual page for a list of media types.
|
||||
See the
|
||||
.Fl m
|
||||
flag below.
|
||||
.It Cm mediaopt Ar opts
|
||||
Set the specified media options on the interface.
|
||||
.Ar opts
|
||||
is a comma delimited list of options to apply to the interface.
|
||||
Refer to the interfaces' driver specific man page for a complete
|
||||
list of available options.
|
||||
Also see the
|
||||
.Xr ifmedia 4
|
||||
manual page for a list of media options.
|
||||
.It Fl mediaopt Ar opts
|
||||
Disable the specified media options on the interface.
|
||||
.It Cm mode Ar mode
|
||||
If the driver supports the media selection system, set the specified
|
||||
operating mode on the interface to
|
||||
.Ar mode .
|
||||
For IEEE 802.11 wireless interfaces that support multiple operating modes
|
||||
this directive is used to select between 802.11a
|
||||
.Pq Dq 11a ,
|
||||
802.11b
|
||||
.Pq Dq 11b ,
|
||||
and 802.11g
|
||||
.Pq Dq 11g
|
||||
operating modes.
|
||||
.It Cm instance Ar minst
|
||||
Set the media instance to
|
||||
.Ar minst .
|
||||
This is useful for devices which have multiple physical layer interfaces
|
||||
.Pq PHYs .
|
||||
Setting the instance on such devices may not be strictly required
|
||||
by the network interface driver as the driver may take care of this
|
||||
automatically; see the driver's manual page for more information.
|
||||
.It Cm metric Ar n
|
||||
Set the routing metric of the interface to
|
||||
.Ar n ,
|
||||
default 0.
|
||||
The routing metric is used by the routing protocol
|
||||
.Pq Xr routed 8 .
|
||||
Higher metrics have the effect of making a route
|
||||
less favorable; metrics are counted as addition hops
|
||||
to the destination network or host.
|
||||
.It Cm mtu Ar n
|
||||
Set the maximum transmission unit of the interface to
|
||||
.Ar n .
|
||||
Most interfaces don't support this option.
|
||||
.It Cm netmask Ar mask
|
||||
.Pq inet, inet6, and ISO
|
||||
Specify how much of the address to reserve for subdividing
|
||||
networks into sub-networks.
|
||||
The mask includes the network part of the local address
|
||||
and the subnet part, which is taken from the host field of the address.
|
||||
The mask can be specified as a single hexadecimal number
|
||||
with a leading 0x, with a dot-notation Internet address,
|
||||
or with a pseudo-network name listed in the network table
|
||||
.Xr networks 5 .
|
||||
The mask contains 1's for the bit positions in the 32-bit address
|
||||
which are to be used for the network and subnet parts,
|
||||
and 0's for the host part.
|
||||
The mask should contain at least the standard network portion,
|
||||
and the subnet field should be contiguous with the network
|
||||
portion.
|
||||
.Pp
|
||||
For INET and INET6 addresses, the netmask can also be given with
|
||||
slash-notation after the address
|
||||
.Pq e.g 192.168.17.3/24 .
|
||||
.\" see
|
||||
.\" Xr eon 5 .
|
||||
.It Cm nsellength Ar n
|
||||
.Pf ( Tn ISO
|
||||
only)
|
||||
This specifies a trailing number of bytes for a received
|
||||
.Tn NSAP
|
||||
used for local identification, the remaining leading part of which is
|
||||
taken to be the
|
||||
.Tn NET
|
||||
.Pq Network Entity Title .
|
||||
The default value is 1, which is conformant to US
|
||||
.Tn GOSIP .
|
||||
When an ISO address is set in an ifconfig command,
|
||||
it is really the
|
||||
.Tn NSAP
|
||||
which is being specified.
|
||||
For example, in
|
||||
.Tn US GOSIP ,
|
||||
20 hex digits should be
|
||||
specified in the
|
||||
.Tn ISO NSAP
|
||||
to be assigned to the interface.
|
||||
There is some evidence that a number different from 1 may be useful
|
||||
for
|
||||
.Tn AFI
|
||||
37 type addresses.
|
||||
.It Cm state Ar state
|
||||
Explicitly force the
|
||||
.Xr carp 4
|
||||
pseudo-device to enter this state.
|
||||
Valid states are
|
||||
.Ar init ,
|
||||
.Ar backup ,
|
||||
and
|
||||
.Ar master .
|
||||
.It Cm frag Ar threshold
|
||||
.Pq IEEE 802.11 devices only
|
||||
Configure the fragmentation threshold for IEEE 802.11-based wireless
|
||||
network interfaces.
|
||||
.It Cm rts Ar threshold
|
||||
.Pq IEEE 802.11 devices only
|
||||
Configure the RTS/CTS threshold for IEEE 802.11-based wireless
|
||||
network interfaces.
|
||||
This controls the number of bytes used for the RTS/CTS handshake boundary.
|
||||
The
|
||||
.Ar threshold
|
||||
can be any value between 0 and 2347.
|
||||
The default is 2347, which indicates the RTS/CTS mechanism should not be used.
|
||||
.It Cm ssid Ar id
|
||||
.Pq IEEE 802.11 devices only
|
||||
Configure the Service Set Identifier (a.k.a. the network name)
|
||||
for IEEE 802.11-based wireless network interfaces.
|
||||
The
|
||||
.Ar id
|
||||
can either be any text string up to 32 characters in length,
|
||||
or a series of up to 64 hexadecimal digits preceded by
|
||||
.Dq 0x .
|
||||
Setting
|
||||
.Ar id
|
||||
to the empty string allows the interface to connect to any available
|
||||
access point.
|
||||
.It Cm nwid Ar id
|
||||
Synonym for
|
||||
.Dq ssid .
|
||||
.It Cm hidessid
|
||||
.Pq IEEE 802.11 devices only
|
||||
When operating as an access point, do not broadcast the SSID
|
||||
in beacon frames or respond to probe request frames unless
|
||||
they are directed to the ap (i.e., they include the ap's SSID).
|
||||
By default, the SSID is included in beacon frames and
|
||||
undirected probe request frames are answered.
|
||||
.It Fl hidessid
|
||||
.Pq IEEE 802.11 devices only
|
||||
When operating as an access point, broadcast the SSID
|
||||
in beacon frames and answer and respond to undirected probe
|
||||
request frames (default).
|
||||
.It Cm nwkey Ar key
|
||||
.Pq IEEE 802.11 devices only
|
||||
Enable WEP encryption for IEEE 802.11-based wireless network interfaces
|
||||
with the
|
||||
.Ar key .
|
||||
The
|
||||
.Ar key
|
||||
can either be a string, a series of hexadecimal digits preceded by
|
||||
.Dq 0x ,
|
||||
or a set of keys in the form
|
||||
.Ar n:k1,k2,k3,k4 ,
|
||||
where
|
||||
.Ar n
|
||||
specifies which of keys will be used for all transmitted packets,
|
||||
and four keys,
|
||||
.Ar k1
|
||||
through
|
||||
.Ar k4 ,
|
||||
are configured as WEP keys.
|
||||
Note that the order must be match within same network if multiple keys
|
||||
are used.
|
||||
For IEEE 802.11 wireless network, the length of each key is restricted to
|
||||
40 bits, i.e. 5-character string or 10 hexadecimal digits,
|
||||
while the WaveLAN/IEEE Gold cards accept the 104 bits
|
||||
.Pq 13 characters
|
||||
key.
|
||||
.It Cm nwkey Cm persist
|
||||
.Pq IEEE 802.11 devices only
|
||||
Enable WEP encryption for IEEE 802.11-based wireless network interfaces
|
||||
with the persistent key written in the network card.
|
||||
.It Cm nwkey Cm persist: Ns Ar key
|
||||
.Pq IEEE 802.11 devices only
|
||||
Write the
|
||||
.Ar key
|
||||
to the persistent memory of the network card, and
|
||||
enable WEP encryption for IEEE 802.11-based wireless network interfaces
|
||||
with the
|
||||
.Ar key .
|
||||
.It Fl nwkey
|
||||
.Pq IEEE 802.11 devices only
|
||||
Disable WEP encryption for IEEE 802.11-based wireless network interfaces.
|
||||
.It Cm apbridge
|
||||
.Pq IEEE 802.11 devices only
|
||||
When operating as an access point, pass packets between
|
||||
wireless clients directly (default).
|
||||
.It Fl apbridge
|
||||
.Pq IEEE 802.11 devices only
|
||||
When operating as an access point, pass packets through
|
||||
the system so that they can be forwared using some other mechanism.
|
||||
Disabling the internal bridging is useful when traffic
|
||||
is to be processed with packet filtering.
|
||||
.It Cm pass Ar passphrase
|
||||
If the driver is a
|
||||
.Xr carp 4
|
||||
pseudo-device, set the authentication key to
|
||||
.Ar passphrase .
|
||||
There is no passphrase by default
|
||||
.It Cm powersave
|
||||
.Pq IEEE 802.11 devices only
|
||||
Enable 802.11 power saving mode.
|
||||
.It Fl powersave
|
||||
.Pq IEEE 802.11 devices only
|
||||
Disable 802.11 power saving mode.
|
||||
.It Cm powersavesleep Ar duration
|
||||
.Pq IEEE 802.11 devices only
|
||||
Set the receiver sleep duration in milliseconds for 802.11 power saving mode.
|
||||
.It Cm bssid Ar bssid
|
||||
.Pq IEEE 802.11 devices only
|
||||
Set the desired BSSID for IEEE 802.11-based wireless network interfaces.
|
||||
.It Fl bssid
|
||||
.Pq IEEE 802.11 devices only
|
||||
Unset the desired BSSID for IEEE 802.11-based wireless network interfaces.
|
||||
The interface will automatically select a BSSID in this mode, which is
|
||||
the default.
|
||||
.It Cm chan Ar chan
|
||||
.Pq IEEE 802.11 devices only
|
||||
Select the channel
|
||||
.Pq radio frequency
|
||||
to be used for IEEE 802.11-based wireless network interfaces.
|
||||
.It Fl chan
|
||||
.Pq IEEE 802.11 devices only
|
||||
Unset the desired channel to be used
|
||||
for IEEE 802.11-based wireless network interfaces.
|
||||
It doesn't affect the channel to be created for IBSS or hostap mode.
|
||||
.It Cm list scan
|
||||
.Pq IEEE 802.11 devices only
|
||||
Display the access points and/or ad-hoc neighbors
|
||||
located in the vicinity.
|
||||
The
|
||||
.Fl v
|
||||
flag may be used to display long SSIDs.
|
||||
.Fl v
|
||||
also causes received information elements to be displayed symbolically.
|
||||
The interface must be up before any scanning operation.
|
||||
Only the super-user can use this command.
|
||||
.It Cm tunnel Ar src_addr Ns Oo Ar ,src_port Oc Ar dest_addr Ns Oo Ar ,dest_port
|
||||
.Oc
|
||||
.Pq IP tunnel devices only
|
||||
Configure the physical source and destination address for IP tunnel
|
||||
interfaces, including
|
||||
.Xr gif 4 .
|
||||
The arguments
|
||||
.Ar src_addr
|
||||
and
|
||||
.Ar dest_addr
|
||||
are interpreted as the outer source/destination for the encapsulating
|
||||
IPv4/IPv6 header.
|
||||
.Pp
|
||||
On a
|
||||
.Xr gre 4
|
||||
interface in UDP mode, the arguments
|
||||
.Ar src_port
|
||||
and
|
||||
.Ar dest_port
|
||||
are interpreted as the outer source/destination port for the encapsulating
|
||||
UDP header.
|
||||
.It Cm deletetunnel
|
||||
Unconfigure the physical source and destination address for IP tunnel
|
||||
interfaces previously configured with
|
||||
.Cm tunnel .
|
||||
.It Cm create
|
||||
Create the specified network pseudo-device.
|
||||
.It Cm destroy
|
||||
Destroy the specified network pseudo-device.
|
||||
.It Cm pltime Ar n
|
||||
.Pq inet6 only
|
||||
Set preferred lifetime for the address.
|
||||
.It Cm prefixlen Ar n
|
||||
.Pq inet and inet6 only
|
||||
Effect is similar to
|
||||
.Cm netmask .
|
||||
but you can specify by prefix length by digits.
|
||||
.It Cm deprecated
|
||||
.Pq inet6 only
|
||||
Set the IPv6 deprecated address bit.
|
||||
.It Fl deprecated
|
||||
.Pq inet6 only
|
||||
Clear the IPv6 deprecated address bit.
|
||||
.It Cm eui64
|
||||
.Pq inet6 only
|
||||
Fill interface index
|
||||
.Pq lowermost 64bit of an IPv6 address
|
||||
automatically.
|
||||
.It Cm link[0-2]
|
||||
Enable special processing of the link level of the interface.
|
||||
These three options are interface specific in actual effect, however,
|
||||
they are in general used to select special modes of operation.
|
||||
An example
|
||||
of this is to enable SLIP compression, or to select the connector type
|
||||
for some Ethernet cards.
|
||||
Refer to the man page for the specific driver
|
||||
for more information.
|
||||
.It Fl link[0-2]
|
||||
Disable special processing at the link level with the specified interface.
|
||||
.It Cm linkstr
|
||||
Set a link-level string parameter for the interface.
|
||||
This functionality varies from interface to interface.
|
||||
Refer to the man page for the specific driver
|
||||
for more information.
|
||||
.It Fl linkstr
|
||||
Remove an interface link-level string parameter.
|
||||
.It Cm up
|
||||
Mark an interface ``up''.
|
||||
This may be used to enable an interface after an ``ifconfig down.''
|
||||
It happens automatically when setting the first address on an interface.
|
||||
If the interface was reset when previously marked down,
|
||||
the hardware will be re-initialized.
|
||||
.It Cm vhid Ar n
|
||||
If the driver is a
|
||||
.Xr carp 4
|
||||
pseudo-device, set the virtual host ID to
|
||||
.Ar n .
|
||||
Acceptable values are 1 to 255.
|
||||
.It Cm vlan Ar vid
|
||||
If the interface is a
|
||||
.Xr vlan 4
|
||||
pseudo-interface, set the VLAN identifier to
|
||||
.Ar vid .
|
||||
These are the first 12 bits (0-4095) from a 16-bit integer used
|
||||
to create an 802.1Q VLAN header for packets sent from the
|
||||
.Xr vlan 4
|
||||
interface.
|
||||
Note that
|
||||
.Cm vlan
|
||||
and
|
||||
.Cm vlanif
|
||||
must be set at the same time.
|
||||
.It Cm vlanif Ar iface
|
||||
If the interface is a
|
||||
.Xr vlan 4
|
||||
pseudo-interface, associate the physical interface
|
||||
.Ar iface
|
||||
with it.
|
||||
Packets transmitted through the
|
||||
.Xr vlan 4
|
||||
interface will be diverted to the specified physical interface
|
||||
.Ar iface
|
||||
with 802.1Q VLAN encapsulation.
|
||||
Packets with 802.1Q encapsulation received
|
||||
by the physical interface with the correct VLAN tag will be diverted to the
|
||||
associated
|
||||
.Xr vlan 4
|
||||
pseudo-interface.
|
||||
The VLAN interface is assigned a copy of the physical
|
||||
interface's flags and
|
||||
.Tn Ethernet
|
||||
address.
|
||||
If the
|
||||
.Xr vlan 4
|
||||
interface already has a physical interface associated with it, this command
|
||||
will fail.
|
||||
To change the association to another physical interface, the
|
||||
existing association must be cleared first.
|
||||
Note that
|
||||
.Cm vlanif
|
||||
and
|
||||
.Cm vlan
|
||||
must be set at the same time.
|
||||
.It Cm -vlanif Ar iface
|
||||
Dissociate
|
||||
.Ar iface
|
||||
from the
|
||||
.Xr vlan 4
|
||||
interface.
|
||||
.It Cm agrport Ar iface
|
||||
Add
|
||||
.Ar iface
|
||||
to the
|
||||
.Xr agr 4
|
||||
interface.
|
||||
.It Cm -agrport Ar iface
|
||||
Remove
|
||||
.Ar iface
|
||||
from the
|
||||
.Xr agr 4
|
||||
interface.
|
||||
.It Cm vltime Ar n
|
||||
.Pq inet6 only
|
||||
Set valid lifetime for the address.
|
||||
.It Cm ip4csum
|
||||
Shorthand of
|
||||
.Dq ip4csum-tx ip4csum-rx
|
||||
.It Cm -ip4csum
|
||||
Shorthand of
|
||||
.Dq -ip4csum-tx -ip4csum-rx
|
||||
.It Cm tcp4csum
|
||||
Shorthand of
|
||||
.Dq tcp4csum-tx tcp4csum-rx
|
||||
.It Cm -tcp4csum
|
||||
Shorthand of
|
||||
.Dq -tcp4csum-tx -tcp4csum-rx
|
||||
.It Cm udp4csum
|
||||
Shorthand of
|
||||
.Dq udp4csum-tx udp4csum-rx
|
||||
.It Cm -udp4csum
|
||||
Shorthand of
|
||||
.Dq -udp4csum-tx -udp4csum-rx
|
||||
.It Cm tcp6csum
|
||||
Shorthand of
|
||||
.Dq tcp6csum-tx tcp6csum-rx
|
||||
.It Cm -tcp6csum
|
||||
Shorthand of
|
||||
.Dq -tcp6csum-tx -tcp6csum-rx
|
||||
.It Cm udp6csum
|
||||
Shorthand of
|
||||
.Dq udp6csum-tx udp6csum-rx
|
||||
.It Cm -udp6csum
|
||||
Shorthand of
|
||||
.Dq -udp6csum-tx -udp6csum-rx
|
||||
.It Cm ip4csum-tx
|
||||
Enable hardware-assisted IPv4 header checksums for the out-bound direction.
|
||||
.It Cm -ip4csum-tx
|
||||
Disable hardware-assisted IPv4 header checksums for the out-bound direction.
|
||||
.It Cm ip4csum-rx
|
||||
Enable hardware-assisted IPv4 header checksums for the in-bound direction.
|
||||
.It Cm -ip4csum-rx
|
||||
Disable hardware-assisted IPv4 header checksums for the in-bound direction.
|
||||
.It Cm tcp4csum-tx
|
||||
Enable hardware-assisted TCP/IPv4 checksums for the out-bound direction.
|
||||
.It Cm -tcp4csum-tx
|
||||
Disable hardware-assisted TCP/IPv4 checksums for the out-bound direction.
|
||||
.It Cm tcp4csum-rx
|
||||
Enable hardware-assisted TCP/IPv4 checksums for the in-bound direction.
|
||||
.It Cm -tcp4csum-rx
|
||||
Disable hardware-assisted TCP/IPv4 checksums for the in-bound direction.
|
||||
.It Cm udp4csum-tx
|
||||
Enable hardware-assisted UDP/IPv4 checksums for the out-bound direction.
|
||||
.It Cm -udp4csum-tx
|
||||
Disable hardware-assisted UDP/IPv4 checksums for the out-bound direction.
|
||||
.It Cm udp4csum-rx
|
||||
Enable hardware-assisted UDP/IPv4 checksums for the in-bound direction.
|
||||
.It Cm -udp4csum-rx
|
||||
Disable hardware-assisted UDP/IPv4 checksums for the in-bound direction.
|
||||
.It Cm tcp6csum-tx
|
||||
Enable hardware-assisted TCP/IPv6 checksums for the out-bound direction.
|
||||
.It Cm -tcp6csum-tx
|
||||
Disable hardware-assisted TCP/IPv6 checksums for the out-bound direction.
|
||||
.It Cm tcp6csum-rx
|
||||
Enable hardware-assisted TCP/IPv6 checksums for the in-bound direction.
|
||||
.It Cm -tcp6csum-rx
|
||||
Disable hardware-assisted TCP/IPv6 checksums for the in-bound direction.
|
||||
.It Cm udp6csum-tx
|
||||
Enable hardware-assisted UDP/IPv6 checksums for the out-bound direction.
|
||||
.It Cm -udp6csum-tx
|
||||
Disable hardware-assisted UDP/IPv6 checksums for the out-bound direction.
|
||||
.It Cm udp6csum-rx
|
||||
Enable hardware-assisted UDP/IPv6 checksums for the in-bound direction.
|
||||
.It Cm -udp6csum-rx
|
||||
Disable hardware-assisted UDP/IPv6 checksums for the in-bound direction.
|
||||
.It Cm tso4
|
||||
Enable hardware-assisted TCP/IPv4 segmentation on interfaces that
|
||||
support it.
|
||||
.It Cm -tso4
|
||||
Disable hardware-assisted TCP/IPv4 segmentation on interfaces that
|
||||
support it.
|
||||
.It Cm tso6
|
||||
Enable hardware-assisted TCP/IPv6 segmentation on interfaces that
|
||||
support it.
|
||||
.It Cm -tso6
|
||||
Disable hardware-assisted TCP/IPv6 segmentation on interfaces that
|
||||
support it.
|
||||
.It Cm maxupd Ar n
|
||||
If the driver is a
|
||||
.Xr pfsync 4
|
||||
pseudo-device, indicate the maximum number
|
||||
of updates for a single state which can be collapsed into one.
|
||||
This is an 8-bit number; the default value is 128.
|
||||
.It Cm syncdev Ar iface
|
||||
If the driver is a
|
||||
.Xr pfsync 4
|
||||
pseudo-device, use the specified interface
|
||||
to send and receive pfsync state synchronisation messages.
|
||||
.It Fl syncdev
|
||||
If the driver is a
|
||||
.Xr pfsync 4
|
||||
pseudo-device, stop sending pfsync state
|
||||
synchronisation messages over the network.
|
||||
.It Cm syncpeer Ar peer_address
|
||||
If the driver is a
|
||||
.Xr pfsync 4
|
||||
pseudo-device, make the pfsync link point-to-point rather than using
|
||||
multicast to broadcast the state synchronisation messages.
|
||||
The peer_address is the IP address of the other host taking part in
|
||||
the pfsync cluster.
|
||||
With this option,
|
||||
.Xr pfsync 4
|
||||
traffic can be protected using
|
||||
.Xr ipsec 4 .
|
||||
.It Fl syncpeer
|
||||
If the driver is a
|
||||
.Xr pfsync 4
|
||||
pseudo-device, broadcast the packets using multicast.
|
||||
.El
|
||||
.Pp
|
||||
.Nm
|
||||
displays the current configuration for a network interface
|
||||
when no optional parameters are supplied.
|
||||
If a protocol family is specified,
|
||||
.Nm
|
||||
will report only the details specific to that protocol
|
||||
family.
|
||||
.Pp
|
||||
If the
|
||||
.Fl s
|
||||
flag is passed before an interface name,
|
||||
.Nm
|
||||
will attempt to query the interface for its media status.
|
||||
If the
|
||||
interface supports reporting media status, and it reports that it does
|
||||
not appear to be connected to a network,
|
||||
.Nm
|
||||
will exit with status of 1
|
||||
.Pq false ;
|
||||
otherwise, it will exit with a
|
||||
zero
|
||||
.Pq true
|
||||
exit status.
|
||||
Not all interface drivers support media
|
||||
status reporting.
|
||||
.Pp
|
||||
If the
|
||||
.Fl m
|
||||
flag is passed before an interface name,
|
||||
.Nm
|
||||
will display all of the supported media for the specified interface.
|
||||
If the
|
||||
.Fl L
|
||||
flag is supplied, address lifetime is displayed for IPv6 addresses,
|
||||
as time offset string.
|
||||
.Pp
|
||||
Optionally, the
|
||||
.Fl a
|
||||
flag may be used instead of an interface name.
|
||||
This flag instructs
|
||||
.Nm
|
||||
to display information about all interfaces in the system.
|
||||
This is also the default behaviour when no arguments are given to
|
||||
.Nm
|
||||
on the command line.
|
||||
When
|
||||
.Fl a
|
||||
is used, the output can be modified by adding more flags:
|
||||
.Fl d
|
||||
limits this to interfaces that are down,
|
||||
.Fl u
|
||||
limits this to interfaces that are up,
|
||||
.Fl b
|
||||
limits this to broadcast interfaces, and
|
||||
.Fl s
|
||||
omits interfaces which appear not to be connected to a network.
|
||||
.Pp
|
||||
The
|
||||
.Fl l
|
||||
flag may be used to list all available interfaces on the system, with
|
||||
no other additional information.
|
||||
Use of this flag is mutually exclusive
|
||||
with all other flags and commands, except for
|
||||
.Fl d
|
||||
.Pq only list interfaces that are down ,
|
||||
.Fl u
|
||||
.Pq only list interfaces that are up ,
|
||||
.Fl s
|
||||
.Pq only list interfaces that may be connected ,
|
||||
.Fl b
|
||||
.Pq only list broadcast interfaces .
|
||||
.Pp
|
||||
The
|
||||
.Fl C
|
||||
flag may be used to list all of the interface cloners available on
|
||||
the system, with no additional information.
|
||||
Use of this flag is
|
||||
mutually exclusive with all other flags and commands.
|
||||
.Pp
|
||||
The
|
||||
.Fl v
|
||||
flag prints statistics on packets sent and received on the given
|
||||
interface.
|
||||
If
|
||||
.Fl h
|
||||
is used in conjunction with
|
||||
.Fl v ,
|
||||
the byte statistics will be printed in "human-readable" format.
|
||||
The
|
||||
.Fl z
|
||||
flag is identical to the
|
||||
.Fl v
|
||||
flag except that it zeros the interface input and output statistics
|
||||
after printing them.
|
||||
.Pp
|
||||
The
|
||||
.Fl w
|
||||
flag may be used to wait
|
||||
.Ar seconds
|
||||
seconds for the
|
||||
.Cm tentative
|
||||
flag to be removed from all addresses.
|
||||
0 seconds means to wait indefinitely until all addresses no longer have the
|
||||
.Cm tentative
|
||||
flag.
|
||||
.Pp
|
||||
The
|
||||
.Fl N
|
||||
flag is just the opposite of the
|
||||
.Fl n
|
||||
flag in
|
||||
.Xr netstat 1
|
||||
or in
|
||||
.Xr route 8 :
|
||||
it tells
|
||||
.Nm
|
||||
to try to resolve numbers to hostnames or to service names.
|
||||
The default
|
||||
.Nm
|
||||
behavior is to print numbers instead of names.
|
||||
.Pp
|
||||
Only the super-user may modify the configuration of a network interface.
|
||||
.Sh EXAMPLES
|
||||
Add a link-layer (MAC) address to an Ethernet:
|
||||
.Pp
|
||||
.Ic ifconfig sip0 link 00:11:22:33:44:55
|
||||
.Pp
|
||||
Add and activate a link-layer (MAC) address:
|
||||
.Pp
|
||||
.Ic ifconfig sip0 link 00:11:22:33:44:55 active
|
||||
.Sh DIAGNOSTICS
|
||||
Messages indicating the specified interface does not exist, the
|
||||
requested address is unknown, or the user is not privileged and
|
||||
tried to alter an interface's configuration.
|
||||
.Sh SEE ALSO
|
||||
.Xr netstat 1 ,
|
||||
.Xr agr 4 ,
|
||||
.Xr carp 4 ,
|
||||
.Xr ifmedia 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr pfsync 4 ,
|
||||
.Xr vlan 4 ,
|
||||
.Xr ifconfig.if 5 ,
|
||||
.\" .Xr eon 5 ,
|
||||
.Xr rc 8 ,
|
||||
.Xr routed 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
1476
sbin/ifconfig/ifconfig.c
Normal file
1476
sbin/ifconfig/ifconfig.c
Normal file
File diff suppressed because it is too large
Load Diff
47
sbin/ifconfig/ifconfig_hostops.c
Normal file
47
sbin/ifconfig/ifconfig_hostops.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* $NetBSD: ifconfig_hostops.c,v 1.1 2010/12/13 17:35:08 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ifconfig_hostops.c,v 1.1 2010/12/13 17:35:08 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "prog_ops.h"
|
||||
|
||||
const struct prog_ops prog_ops = {
|
||||
.op_socket = socket,
|
||||
.op_ioctl = ioctl,
|
||||
.op_read = read,
|
||||
.op_close = close,
|
||||
};
|
||||
52
sbin/ifconfig/ifconfig_rumpops.c
Normal file
52
sbin/ifconfig/ifconfig_rumpops.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* $NetBSD: ifconfig_rumpops.c,v 1.1 2010/12/13 17:35:08 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ifconfig_rumpops.c,v 1.1 2010/12/13 17:35:08 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
#include <rump/rumpclient.h>
|
||||
|
||||
#include "prog_ops.h"
|
||||
|
||||
const struct prog_ops prog_ops = {
|
||||
.op_init = rumpclient_init,
|
||||
|
||||
.op_socket = rump_sys_socket,
|
||||
.op_ioctl = rump_sys_ioctl,
|
||||
.op_read = rump_sys_read,
|
||||
.op_close = rump_sys_close,
|
||||
};
|
||||
464
sbin/ifconfig/media.c
Normal file
464
sbin/ifconfig/media.c
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: media.c,v 1.6 2011/08/29 14:35:00 joerg Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <prop/proplib.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "media.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
static void init_current_media(prop_dictionary_t, prop_dictionary_t);
|
||||
static void media_constructor(void) __attribute__((constructor));
|
||||
static int setmedia(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setmediainst(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setmediamode(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setmediaopt(prop_dictionary_t, prop_dictionary_t);
|
||||
static int unsetmediaopt(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
/*
|
||||
* Media stuff. Whenever a media command is first performed, the
|
||||
* currently select media is grabbed for this interface. If `media'
|
||||
* is given, the current media word is modifed. `mediaopt' commands
|
||||
* only modify the set and clear words. They then operate on the
|
||||
* current media word later.
|
||||
*/
|
||||
static int media_current;
|
||||
static int mediaopt_set;
|
||||
static int mediaopt_clear;
|
||||
|
||||
static struct usage_func usage;
|
||||
|
||||
static const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
|
||||
|
||||
static const struct ifmedia_status_description ifm_status_descriptions[] =
|
||||
IFM_STATUS_DESCRIPTIONS;
|
||||
|
||||
static struct pstr mediamode = PSTR_INITIALIZER1(&mediamode, "mediamode",
|
||||
setmediamode, "mediamode", false, &command_root.pb_parser);
|
||||
|
||||
static struct pinteger mediainst = PINTEGER_INITIALIZER1(&mediainst,
|
||||
"mediainst", 0, IFM_INST_MAX, 10, setmediainst, "mediainst",
|
||||
&command_root.pb_parser);
|
||||
|
||||
static struct pstr unmediaopt = PSTR_INITIALIZER1(&unmediaopt, "-mediaopt",
|
||||
unsetmediaopt, "unmediaopt", false, &command_root.pb_parser);
|
||||
|
||||
static struct pstr mediaopt = PSTR_INITIALIZER1(&mediaopt, "mediaopt",
|
||||
setmediaopt, "mediaopt", false, &command_root.pb_parser);
|
||||
|
||||
static struct pstr media = PSTR_INITIALIZER1(&media, "media", setmedia, "media",
|
||||
false, &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst mediakw[] = {
|
||||
{.k_word = "instance", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_act = "media", .k_deact = "mediainst",
|
||||
.k_nextparser = &mediainst.pi_parser}
|
||||
, {.k_word = "inst", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_act = "media", .k_deact = "mediainst",
|
||||
.k_nextparser = &mediainst.pi_parser}
|
||||
, {.k_word = "media", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_deact = "media", .k_altdeact = "anymedia",
|
||||
.k_nextparser = &media.ps_parser}
|
||||
, {.k_word = "mediaopt", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_deact = "mediaopt", .k_altdeact = "instance",
|
||||
.k_nextparser = &mediaopt.ps_parser}
|
||||
, {.k_word = "-mediaopt", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_deact = "unmediaopt", .k_altdeact = "media",
|
||||
.k_nextparser = &unmediaopt.ps_parser}
|
||||
, {.k_word = "mode", .k_key = "anymedia", .k_type = KW_T_BOOL,
|
||||
.k_bool = true, .k_deact = "mode",
|
||||
.k_nextparser = &mediamode.ps_parser}
|
||||
};
|
||||
|
||||
struct pkw kwmedia = PKW_INITIALIZER(&kwmedia, "media keywords", NULL, NULL,
|
||||
mediakw, __arraycount(mediakw), NULL);
|
||||
|
||||
__dead static void
|
||||
media_error(int type, const char *val, const char *opt)
|
||||
{
|
||||
errx(EXIT_FAILURE, "unknown %s media %s: %s",
|
||||
get_media_type_string(type), opt, val);
|
||||
}
|
||||
|
||||
void
|
||||
init_current_media(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
const char *ifname;
|
||||
struct ifmediareq ifmr;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "getifname");
|
||||
|
||||
/*
|
||||
* If we have not yet done so, grab the currently-selected
|
||||
* media.
|
||||
*/
|
||||
|
||||
if (prop_dictionary_get(env, "initmedia") == NULL) {
|
||||
memset(&ifmr, 0, sizeof(ifmr));
|
||||
|
||||
if (direct_ioctl(env, SIOCGIFMEDIA, &ifmr) == -1) {
|
||||
/*
|
||||
* If we get E2BIG, the kernel is telling us
|
||||
* that there are more, so we can ignore it.
|
||||
*/
|
||||
if (errno != E2BIG)
|
||||
err(EXIT_FAILURE, "SIOCGIFMEDIA");
|
||||
}
|
||||
|
||||
if (!prop_dictionary_set_bool(oenv, "initmedia", true)) {
|
||||
err(EXIT_FAILURE, "%s: prop_dictionary_set_bool",
|
||||
__func__);
|
||||
}
|
||||
media_current = ifmr.ifm_current;
|
||||
}
|
||||
|
||||
/* Sanity. */
|
||||
if (IFM_TYPE(media_current) == 0)
|
||||
errx(EXIT_FAILURE, "%s: no link type?", ifname);
|
||||
}
|
||||
|
||||
void
|
||||
process_media_commands(prop_dictionary_t env)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (prop_dictionary_get(env, "media") == NULL &&
|
||||
prop_dictionary_get(env, "mediaopt") == NULL &&
|
||||
prop_dictionary_get(env, "unmediaopt") == NULL &&
|
||||
prop_dictionary_get(env, "mediamode") == NULL) {
|
||||
/* Nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Media already set up, and commands sanity-checked. Set/clear
|
||||
* any options, and we're ready to go.
|
||||
*/
|
||||
media_current |= mediaopt_set;
|
||||
media_current &= ~mediaopt_clear;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_media = media_current;
|
||||
|
||||
if (direct_ioctl(env, SIOCSIFMEDIA, &ifr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSIFMEDIA");
|
||||
}
|
||||
|
||||
static int
|
||||
setmedia(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
int type, subtype, inst;
|
||||
prop_data_t data;
|
||||
char *val;
|
||||
|
||||
init_current_media(env, oenv);
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "media");
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only one media command may be given. */
|
||||
/* Must not come after mode commands */
|
||||
/* Must not come after mediaopt commands */
|
||||
|
||||
/*
|
||||
* No need to check if `instance' has been issued; setmediainst()
|
||||
* craps out if `media' has not been specified.
|
||||
*/
|
||||
|
||||
type = IFM_TYPE(media_current);
|
||||
inst = IFM_INST(media_current);
|
||||
|
||||
val = strndup(prop_data_data_nocopy(data), prop_data_size(data));
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
|
||||
/* Look up the subtype. */
|
||||
subtype = get_media_subtype(type, val);
|
||||
if (subtype == -1)
|
||||
media_error(type, val, "subtype");
|
||||
|
||||
/* Build the new current media word. */
|
||||
media_current = IFM_MAKEWORD(type, subtype, 0, inst);
|
||||
|
||||
/* Media will be set after other processing is complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setmediaopt(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
char *invalid;
|
||||
prop_data_t data;
|
||||
char *val;
|
||||
|
||||
init_current_media(env, oenv);
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "mediaopt");
|
||||
assert(data != NULL);
|
||||
|
||||
/* Can only issue `mediaopt' once. */
|
||||
/* Can't issue `mediaopt' if `instance' has already been issued. */
|
||||
|
||||
val = strndup(prop_data_data_nocopy(data), prop_data_size(data));
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
|
||||
mediaopt_set = get_media_options(media_current, val, &invalid);
|
||||
free(val);
|
||||
if (mediaopt_set == -1)
|
||||
media_error(media_current, invalid, "option");
|
||||
|
||||
/* Media will be set after other processing is complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unsetmediaopt(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
char *invalid, *val;
|
||||
prop_data_t data;
|
||||
|
||||
init_current_media(env, oenv);
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "unmediaopt");
|
||||
if (data == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = strndup(prop_data_data_nocopy(data), prop_data_size(data));
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* No need to check for A_MEDIAINST, since the test for A_MEDIA
|
||||
* implicitly checks for A_MEDIAINST.
|
||||
*/
|
||||
|
||||
mediaopt_clear = get_media_options(media_current, val, &invalid);
|
||||
free(val);
|
||||
if (mediaopt_clear == -1)
|
||||
media_error(media_current, invalid, "option");
|
||||
|
||||
/* Media will be set after other processing is complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setmediainst(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
int type, subtype, options;
|
||||
int64_t inst;
|
||||
bool rc;
|
||||
|
||||
init_current_media(env, oenv);
|
||||
|
||||
rc = prop_dictionary_get_int64(env, "mediainst", &inst);
|
||||
assert(rc);
|
||||
|
||||
/* Can only issue `instance' once. */
|
||||
/* Must have already specified `media' */
|
||||
|
||||
type = IFM_TYPE(media_current);
|
||||
subtype = IFM_SUBTYPE(media_current);
|
||||
options = IFM_OPTIONS(media_current);
|
||||
|
||||
media_current = IFM_MAKEWORD(type, subtype, options, inst);
|
||||
|
||||
/* Media will be set after other processing is complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setmediamode(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
int type, subtype, options, inst, mode;
|
||||
prop_data_t data;
|
||||
char *val;
|
||||
|
||||
init_current_media(env, oenv);
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "mediamode");
|
||||
assert(data != NULL);
|
||||
|
||||
type = IFM_TYPE(media_current);
|
||||
subtype = IFM_SUBTYPE(media_current);
|
||||
options = IFM_OPTIONS(media_current);
|
||||
inst = IFM_INST(media_current);
|
||||
|
||||
val = strndup(prop_data_data_nocopy(data), prop_data_size(data));
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
|
||||
mode = get_media_mode(type, val);
|
||||
if (mode == -1)
|
||||
media_error(type, val, "mode");
|
||||
|
||||
free(val);
|
||||
|
||||
media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode;
|
||||
|
||||
/* Media will be set after other processing is complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
print_media_word(int ifmw, const char *opt_sep)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
printf("%s", get_media_subtype_string(ifmw));
|
||||
|
||||
/* Find mode. */
|
||||
if (IFM_MODE(ifmw) != 0) {
|
||||
str = get_media_mode_string(ifmw);
|
||||
if (str != NULL)
|
||||
printf(" mode %s", str);
|
||||
}
|
||||
|
||||
/* Find options. */
|
||||
for (; (str = get_media_option_string(&ifmw)) != NULL; opt_sep = ",")
|
||||
printf("%s%s", opt_sep, str);
|
||||
|
||||
if (IFM_INST(ifmw) != 0)
|
||||
printf(" instance %d", IFM_INST(ifmw));
|
||||
}
|
||||
|
||||
void
|
||||
media_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct ifmediareq ifmr;
|
||||
int af, i, s;
|
||||
int *media_list;
|
||||
const char *ifname;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "getifname");
|
||||
if ((af = getaf(env)) == -1)
|
||||
af = AF_UNSPEC;
|
||||
|
||||
/* get out early if the family is unsupported by the kernel */
|
||||
if ((s = getsock(af)) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
|
||||
memset(&ifmr, 0, sizeof(ifmr));
|
||||
estrlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
|
||||
|
||||
if (prog_ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
|
||||
/*
|
||||
* Interface doesn't support SIOC{G,S}IFMEDIA.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifmr.ifm_count == 0) {
|
||||
warnx("%s: no media types?", ifname);
|
||||
return;
|
||||
}
|
||||
|
||||
media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
|
||||
if (media_list == NULL)
|
||||
err(EXIT_FAILURE, "malloc");
|
||||
ifmr.ifm_ulist = media_list;
|
||||
|
||||
if (prog_ioctl(s, SIOCGIFMEDIA, &ifmr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCGIFMEDIA");
|
||||
|
||||
printf("\tmedia: %s ", get_media_type_string(ifmr.ifm_current));
|
||||
print_media_word(ifmr.ifm_current, " ");
|
||||
if (ifmr.ifm_active != ifmr.ifm_current) {
|
||||
printf(" (");
|
||||
print_media_word(ifmr.ifm_active, " ");
|
||||
printf(")");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (ifmr.ifm_status & IFM_STATUS_VALID) {
|
||||
const struct ifmedia_status_description *ifms;
|
||||
int bitno, found = 0;
|
||||
|
||||
printf("\tstatus: ");
|
||||
for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
|
||||
for (ifms = ifm_status_descriptions;
|
||||
ifms->ifms_valid != 0; ifms++) {
|
||||
if (ifms->ifms_type !=
|
||||
IFM_TYPE(ifmr.ifm_current) ||
|
||||
ifms->ifms_valid !=
|
||||
ifm_status_valid_list[bitno])
|
||||
continue;
|
||||
printf("%s%s", found ? ", " : "",
|
||||
IFM_STATUS_DESC(ifms, ifmr.ifm_status));
|
||||
found = 1;
|
||||
|
||||
/*
|
||||
* For each valid indicator bit, there's
|
||||
* only one entry for each media type, so
|
||||
* terminate the inner loop now.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
printf("unknown");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (get_flag('m')) {
|
||||
int type, printed_type;
|
||||
|
||||
for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) {
|
||||
for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) {
|
||||
if (IFM_TYPE(media_list[i]) != type)
|
||||
continue;
|
||||
if (printed_type == 0) {
|
||||
printf("\tsupported %s media:\n",
|
||||
get_media_type_string(type));
|
||||
printed_type = 1;
|
||||
}
|
||||
printf("\t\tmedia ");
|
||||
print_media_word(media_list[i], " mediaopt ");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(media_list);
|
||||
}
|
||||
|
||||
static void
|
||||
media_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] "
|
||||
"[ instance minst ]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
media_constructor(void)
|
||||
{
|
||||
if (register_flag('m') != 0)
|
||||
err(EXIT_FAILURE, __func__);
|
||||
usage_func_init(&usage, media_usage);
|
||||
register_usage(&usage);
|
||||
}
|
||||
16
sbin/ifconfig/media.h
Normal file
16
sbin/ifconfig/media.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* $NetBSD: media.h,v 1.1 2008/07/02 07:44:15 dyoung Exp $ */
|
||||
|
||||
#ifndef _IFCONFIG_MEDIA_H
|
||||
#define _IFCONFIG_MEDIA_H
|
||||
|
||||
#include <prop/proplib.h>
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
extern struct pkw kwmedia;
|
||||
|
||||
void print_media_word(int, const char *);
|
||||
void process_media_commands(prop_dictionary_t);
|
||||
void media_status(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
#endif /* _IFCONFIG_MEDIA_H */
|
||||
995
sbin/ifconfig/parse.c
Normal file
995
sbin/ifconfig/parse.c
Normal file
|
|
@ -0,0 +1,995 @@
|
|||
/* $NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/param.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netatalk/at.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dbg_warnx(__fmt, ...) warnx(__fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define dbg_warnx(__fmt, ...) /* empty */
|
||||
#endif
|
||||
|
||||
static int parser_default_init(struct parser *);
|
||||
static int pbranch_init(struct parser *);
|
||||
static int pkw_init(struct parser *);
|
||||
|
||||
static int pterm_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int paddr_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int pbranch_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int piface_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int pstr_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int pinteger_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
static int pkw_match(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
|
||||
const struct parser_methods pterm_methods = {
|
||||
.pm_match = pterm_match
|
||||
, .pm_init = NULL
|
||||
};
|
||||
|
||||
const struct parser_methods pstr_methods = {
|
||||
.pm_match = pstr_match
|
||||
, .pm_init = parser_default_init
|
||||
};
|
||||
|
||||
const struct parser_methods pinteger_methods = {
|
||||
.pm_match = pinteger_match
|
||||
, .pm_init = parser_default_init
|
||||
};
|
||||
|
||||
const struct parser_methods paddr_methods = {
|
||||
.pm_match = paddr_match
|
||||
, .pm_init = parser_default_init
|
||||
};
|
||||
|
||||
const struct parser_methods piface_methods = {
|
||||
.pm_match = piface_match
|
||||
, .pm_init = parser_default_init
|
||||
};
|
||||
|
||||
const struct parser_methods pbranch_methods = {
|
||||
.pm_match = pbranch_match
|
||||
, .pm_init = pbranch_init
|
||||
};
|
||||
|
||||
const struct parser_methods pkw_methods = {
|
||||
.pm_match = pkw_match
|
||||
, .pm_init = pkw_init
|
||||
};
|
||||
|
||||
static int
|
||||
match_setenv(const struct match *im, struct match *om, const char *key,
|
||||
prop_object_t o)
|
||||
{
|
||||
if (im == NULL)
|
||||
om->m_env = prop_dictionary_create();
|
||||
else
|
||||
om->m_env = prop_dictionary_copy(im->m_env);
|
||||
|
||||
if (om->m_env == NULL)
|
||||
goto delobj;
|
||||
|
||||
if (key != NULL && !prop_dictionary_set(om->m_env, key, o))
|
||||
goto deldict;
|
||||
|
||||
if (o != NULL)
|
||||
prop_object_release((prop_object_t)o);
|
||||
|
||||
return 0;
|
||||
deldict:
|
||||
prop_object_release((prop_object_t)om->m_env);
|
||||
om->m_env = NULL;
|
||||
delobj:
|
||||
prop_object_release((prop_object_t)o);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
pstr_match(const struct parser *p, const struct match *im, struct match *om,
|
||||
int argidx, const char *arg)
|
||||
{
|
||||
prop_object_t o;
|
||||
const struct pstr *ps = (const struct pstr *)p;
|
||||
uint8_t buf[128];
|
||||
int len;
|
||||
|
||||
if (arg == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = (int)sizeof(buf);
|
||||
if (get_string(arg, NULL, buf, &len, ps->ps_hexok) == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
o = (prop_object_t)prop_data_create_data(buf, len);
|
||||
|
||||
if (o == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (match_setenv(im, om, ps->ps_key, o) == -1)
|
||||
return -1;
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = p->p_nextparser;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pinteger_match(const struct parser *p, const struct match *im, struct match *om,
|
||||
int argidx, const char *arg)
|
||||
{
|
||||
prop_object_t o;
|
||||
const struct pinteger *pi = (const struct pinteger *)p;
|
||||
char *end;
|
||||
int64_t val;
|
||||
|
||||
if (arg == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = strtoimax(arg, &end, pi->pi_base);
|
||||
if ((val == INTMAX_MIN || val == INTMAX_MAX) && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
if (*end != '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (val < pi->pi_min || val > pi->pi_max) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
o = (prop_object_t)prop_number_create_integer(val);
|
||||
|
||||
if (o == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (match_setenv(im, om, pi->pi_key, o) == -1)
|
||||
return -1;
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = p->p_nextparser;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_linkaddr(const char *addr, struct sockaddr_storage *ss)
|
||||
{
|
||||
static const size_t maxlen =
|
||||
sizeof(*ss) - offsetof(struct sockaddr_dl, sdl_data[0]);
|
||||
enum {
|
||||
LLADDR_S_INITIAL = 0,
|
||||
LLADDR_S_ONE_OCTET = 1,
|
||||
LLADDR_S_TWO_OCTETS = 2,
|
||||
LLADDR_S_COLON = 3
|
||||
} state = LLADDR_S_INITIAL;
|
||||
uint8_t octet = 0, val;
|
||||
struct sockaddr_dl *sdl;
|
||||
const char *p;
|
||||
size_t i;
|
||||
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
ss->ss_family = AF_LINK;
|
||||
sdl = (struct sockaddr_dl *)ss;
|
||||
|
||||
for (i = 0, p = addr; i < maxlen; p++) {
|
||||
dbg_warnx("%s.%d: *p == %c, state %d", __func__, __LINE__, *p,
|
||||
state);
|
||||
if (*p == '\0') {
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
if (state != LLADDR_S_ONE_OCTET &&
|
||||
state != LLADDR_S_TWO_OCTETS)
|
||||
return -1;
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
sdl->sdl_data[i++] = octet;
|
||||
sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data)
|
||||
+ i * sizeof(sdl->sdl_data[0]);
|
||||
sdl->sdl_alen = i;
|
||||
return 0;
|
||||
}
|
||||
if (*p == ':') {
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
if (state != LLADDR_S_ONE_OCTET &&
|
||||
state != LLADDR_S_TWO_OCTETS)
|
||||
return -1;
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
sdl->sdl_data[i++] = octet;
|
||||
state = LLADDR_S_COLON;
|
||||
continue;
|
||||
}
|
||||
if ('a' <= *p && *p <= 'f')
|
||||
val = 10 + *p - 'a';
|
||||
else if ('A' <= *p && *p <= 'F')
|
||||
val = 10 + *p - 'A';
|
||||
else if ('0' <= *p && *p <= '9')
|
||||
val = *p - '0';
|
||||
else
|
||||
return -1;
|
||||
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
if (state == LLADDR_S_ONE_OCTET) {
|
||||
state = LLADDR_S_TWO_OCTETS;
|
||||
octet <<= 4;
|
||||
octet |= val;
|
||||
} else if (state != LLADDR_S_INITIAL && state != LLADDR_S_COLON)
|
||||
return -1;
|
||||
else {
|
||||
state = LLADDR_S_ONE_OCTET;
|
||||
octet = val;
|
||||
}
|
||||
dbg_warnx("%s.%d", __func__, __LINE__);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
paddr_match(const struct parser *p, const struct match *im, struct match *om,
|
||||
int argidx, const char *arg0)
|
||||
{
|
||||
unsigned int net, node;
|
||||
int nread;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_at sat;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
} u;
|
||||
const struct paddr *pa = (const struct paddr *)p;
|
||||
prop_data_t d;
|
||||
prop_object_t o;
|
||||
int64_t af0;
|
||||
int af, rc;
|
||||
struct paddr_prefix *pfx, *mask;
|
||||
const struct sockaddr *sa = NULL;
|
||||
struct addrinfo hints, *result = NULL;
|
||||
char *arg, *end, *plen = NULL, *servname0;
|
||||
const char *servname;
|
||||
long prefixlen = -1;
|
||||
size_t len;
|
||||
|
||||
if (arg0 == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pa->pa_activator != NULL &&
|
||||
prop_dictionary_get(im->m_env, pa->pa_activator) == NULL)
|
||||
return -1;
|
||||
|
||||
if (pa->pa_deactivator != NULL &&
|
||||
prop_dictionary_get(im->m_env, pa->pa_deactivator) != NULL)
|
||||
return -1;
|
||||
|
||||
if (!prop_dictionary_get_int64(im->m_env, "af", &af0))
|
||||
af = AF_UNSPEC;
|
||||
else
|
||||
af = af0;
|
||||
|
||||
memset(&u, 0, sizeof(u));
|
||||
|
||||
switch (af) {
|
||||
case AF_UNSPEC:
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
if ((arg = strdup(arg0)) == NULL)
|
||||
return -1;
|
||||
|
||||
servname0 = arg;
|
||||
(void)strsep(&servname0, ",");
|
||||
servname = (servname0 == NULL) ? "0" : servname0;
|
||||
|
||||
if (pa->pa_maskkey == NULL)
|
||||
;
|
||||
else if ((plen = strrchr(arg, '/')) != NULL)
|
||||
*plen++ = '\0';
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
|
||||
for (;;) {
|
||||
rc = getaddrinfo(arg, servname, &hints, &result);
|
||||
if (rc == 0) {
|
||||
if (result->ai_next == NULL)
|
||||
sa = result->ai_addr;
|
||||
else
|
||||
errno = EMLINK;
|
||||
break;
|
||||
} else if ((hints.ai_flags & AI_NUMERICHOST) != 0 &&
|
||||
(af == AF_INET || af == AF_UNSPEC) &&
|
||||
inet_aton(arg, &u.sin.sin_addr) == 1) {
|
||||
u.sin.sin_family = AF_INET;
|
||||
u.sin.sin_len = sizeof(u.sin);
|
||||
sa = &u.sa;
|
||||
break;
|
||||
} else if ((hints.ai_flags & AI_NUMERICHOST) == 0 ||
|
||||
rc != EAI_NONAME) {
|
||||
errno = ENOENT;
|
||||
break;
|
||||
}
|
||||
hints.ai_flags &= ~AI_NUMERICHOST;
|
||||
}
|
||||
|
||||
|
||||
if (plen == NULL)
|
||||
prefixlen = -1;
|
||||
else {
|
||||
prefixlen = strtol(plen, &end, 10);
|
||||
if (end != NULL && *end != '\0')
|
||||
sa = NULL;
|
||||
if (prefixlen < 0 || prefixlen >= UINT8_MAX) {
|
||||
errno = ERANGE;
|
||||
sa = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(arg);
|
||||
if (sa != NULL || af != AF_UNSPEC)
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
case AF_APPLETALK:
|
||||
if (sscanf(arg0, "%u.%u%n", &net, &node, &nread) == 2 &&
|
||||
net != 0 && net <= 0xffff && node != 0 && node <= 0xfe &&
|
||||
arg0[nread] == '\0') {
|
||||
u.sat.sat_family = AF_APPLETALK;
|
||||
u.sat.sat_len = sizeof(u.sat);
|
||||
u.sat.sat_addr.s_net = htons(net);
|
||||
u.sat.sat_addr.s_node = node;
|
||||
sa = &u.sa;
|
||||
}
|
||||
break;
|
||||
case AF_LINK:
|
||||
if (parse_linkaddr(arg0, &u.ss) == -1)
|
||||
sa = NULL;
|
||||
else
|
||||
sa = &u.sa;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sa == NULL)
|
||||
return -1;
|
||||
|
||||
len = offsetof(struct paddr_prefix, pfx_addr) + sa->sa_len;
|
||||
|
||||
if ((pfx = malloc(len)) == NULL)
|
||||
return -1;
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sa->sa_len; i++)
|
||||
printf(" %02x", ((const uint8_t *)sa)[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
pfx->pfx_len = (int16_t)prefixlen;
|
||||
memcpy(&pfx->pfx_addr, sa, sa->sa_len);
|
||||
af = sa->sa_family;
|
||||
|
||||
if (result != NULL)
|
||||
freeaddrinfo(result);
|
||||
|
||||
o = (prop_object_t)prop_data_create_data(pfx, len);
|
||||
|
||||
free(pfx);
|
||||
|
||||
if (o == NULL)
|
||||
return -1;
|
||||
|
||||
if (match_setenv(im, om, pa->pa_addrkey, o) == -1)
|
||||
return -1;
|
||||
|
||||
if (pa->pa_maskkey != NULL && plen != NULL) {
|
||||
size_t masklen;
|
||||
|
||||
if ((mask = prefixlen_to_mask(af, prefixlen)) == NULL) {
|
||||
err(EXIT_FAILURE, "%s: prefixlen_to_mask(%d, %ld)",
|
||||
__func__, af, prefixlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
masklen = paddr_prefix_size(mask);
|
||||
|
||||
d = prop_data_create_data(mask, masklen);
|
||||
free(mask);
|
||||
|
||||
if (d == NULL) {
|
||||
err(EXIT_FAILURE, "%s: prop_data_create_data",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = prop_dictionary_set(om->m_env, pa->pa_maskkey,
|
||||
(prop_object_t)d) ? 0 : -1;
|
||||
|
||||
prop_object_release((prop_object_t)d);
|
||||
|
||||
if (rc != 0) {
|
||||
err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = p->p_nextparser;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pterm_match(const struct parser *p, const struct match *im,
|
||||
struct match *om, int argidx, const char *arg)
|
||||
{
|
||||
const struct pterm *pt = (const struct pterm *)p;
|
||||
prop_bool_t b;
|
||||
|
||||
if (arg != NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
b = prop_bool_create(true);
|
||||
|
||||
if (match_setenv(im, om, pt->pt_key, (prop_object_t)b) == -1)
|
||||
return -1;
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
piface_match(const struct parser *p, const struct match *im,
|
||||
struct match *om, int argidx, const char *arg)
|
||||
{
|
||||
const struct piface *pif = (const struct piface *)p;
|
||||
prop_object_t o;
|
||||
|
||||
if (arg == NULL || strlen(arg) > IFNAMSIZ) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((o = (prop_object_t)prop_string_create_cstring(arg)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (match_setenv(im, om, pif->pif_key, o) == -1)
|
||||
return -1;
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = p->p_nextparser;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
match_cleanup(struct match *dst)
|
||||
{
|
||||
if (dst->m_env != NULL)
|
||||
prop_object_release((prop_object_t)dst->m_env);
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
}
|
||||
|
||||
static void
|
||||
match_copy(struct match *dst, const struct match *src)
|
||||
{
|
||||
match_cleanup(dst);
|
||||
|
||||
prop_object_retain((prop_object_t)src->m_env);
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
static int
|
||||
pbranch_match(const struct parser *p, const struct match *im,
|
||||
struct match *om, int argidx, const char *arg)
|
||||
{
|
||||
const struct parser *nextp;
|
||||
struct branch *b;
|
||||
const struct pbranch *pb = (const struct pbranch *)p;
|
||||
struct match tmpm;
|
||||
int nforbid = 0, nmatch = 0, rc;
|
||||
parser_match_t matchfunc;
|
||||
|
||||
memset(&tmpm, 0, sizeof(tmpm));
|
||||
|
||||
SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) {
|
||||
nextp = b->b_nextparser;
|
||||
dbg_warnx("%s: b->b_nextparser %p [%s]", __func__,
|
||||
nextp, nextp ? nextp->p_name : "(null)");
|
||||
if (nextp == NULL) {
|
||||
if (arg == NULL) {
|
||||
nmatch++;
|
||||
match_setenv(im, om, NULL, NULL);
|
||||
om->m_nextparser = NULL;
|
||||
om->m_parser = p;
|
||||
om->m_argidx = argidx;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
matchfunc = nextp->p_methods->pm_match;
|
||||
rc = (*matchfunc)(nextp, im, &tmpm, argidx, arg);
|
||||
if (rc == 0) {
|
||||
match_copy(om, &tmpm);
|
||||
match_cleanup(&tmpm);
|
||||
nmatch++;
|
||||
dbg_warnx("%s: branch %s ok", __func__, nextp->p_name);
|
||||
if (pb->pb_match_first)
|
||||
break;
|
||||
} else if (rc == 1) {
|
||||
nforbid++;
|
||||
if (pb->pb_match_first)
|
||||
break;
|
||||
} else {
|
||||
dbg_warnx("%s: fail branch %s", __func__,
|
||||
nextp->p_name);
|
||||
}
|
||||
}
|
||||
switch (nmatch) {
|
||||
case 0:
|
||||
errno = ENOENT;
|
||||
return (nforbid == 0) ? -1 : 1;
|
||||
case 1:
|
||||
dbg_warnx("%s: branch ok", __func__);
|
||||
return 0;
|
||||
default:
|
||||
match_cleanup(om);
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pkw_match(const struct parser *p, const struct match *im,
|
||||
struct match *om, int argidx, const char *arg)
|
||||
{
|
||||
prop_object_t o = NULL;
|
||||
struct kwinst *k;
|
||||
union kwval *u = NULL;
|
||||
const struct pkw *pk = (const struct pkw *)p;
|
||||
|
||||
if (arg == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) {
|
||||
if (k->k_act != NULL &&
|
||||
prop_dictionary_get(im->m_env, k->k_act) == NULL)
|
||||
continue;
|
||||
|
||||
if (k->k_neg && arg[0] == '-' &&
|
||||
strcmp(k->k_word, arg + 1) == 0)
|
||||
u = &k->k_negu;
|
||||
else if (strcmp(k->k_word, arg) == 0)
|
||||
u = &k->k_u;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (k->k_altdeact != NULL &&
|
||||
prop_dictionary_get(im->m_env, k->k_altdeact) != NULL)
|
||||
return 1;
|
||||
|
||||
if (k->k_deact != NULL &&
|
||||
prop_dictionary_get(im->m_env, k->k_deact) != NULL)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
if (k == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
switch (k->k_type) {
|
||||
case KW_T_NONE:
|
||||
break;
|
||||
case KW_T_BOOL:
|
||||
o = (prop_object_t)prop_bool_create(u->u_bool);
|
||||
if (o == NULL)
|
||||
goto err;
|
||||
break;
|
||||
case KW_T_INT:
|
||||
o = (prop_object_t)prop_number_create_integer(u->u_sint);
|
||||
if (o == NULL)
|
||||
goto err;
|
||||
break;
|
||||
case KW_T_UINT:
|
||||
o = (prop_object_t)prop_number_create_unsigned_integer(
|
||||
u->u_uint);
|
||||
if (o == NULL)
|
||||
goto err;
|
||||
break;
|
||||
case KW_T_OBJ:
|
||||
o = u->u_obj;
|
||||
break;
|
||||
case KW_T_STR:
|
||||
o = (prop_object_t)prop_string_create_cstring_nocopy(u->u_str);
|
||||
if (o == NULL)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
errx(EXIT_FAILURE, "unknown keyword type %d", k->k_type);
|
||||
}
|
||||
|
||||
if (match_setenv(im, om, (o == NULL) ? NULL : k->k_key, o) == -1)
|
||||
return -1;
|
||||
|
||||
om->m_argidx = argidx;
|
||||
om->m_parser = p;
|
||||
om->m_nextparser = k->k_nextparser;
|
||||
om->m_exec = k->k_exec;
|
||||
return 0;
|
||||
err:
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct paddr *
|
||||
paddr_create(const char *name, parser_exec_t pexec, const char *addrkey,
|
||||
const char *maskkey, struct parser *next)
|
||||
{
|
||||
struct paddr *pa;
|
||||
|
||||
if ((pa = calloc(sizeof(*pa), 1)) == NULL)
|
||||
return NULL;
|
||||
|
||||
pa->pa_parser.p_methods = &paddr_methods;
|
||||
pa->pa_parser.p_exec = pexec;
|
||||
pa->pa_parser.p_name = name;
|
||||
pa->pa_parser.p_nextparser = next;
|
||||
|
||||
pa->pa_addrkey = addrkey;
|
||||
pa->pa_maskkey = maskkey;
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
struct piface *
|
||||
piface_create(const char *name, parser_exec_t pexec, const char *defkey,
|
||||
struct parser *defnext)
|
||||
{
|
||||
struct piface *pif;
|
||||
|
||||
if ((pif = calloc(sizeof(*pif), 1)) == NULL)
|
||||
return NULL;
|
||||
|
||||
pif->pif_parser.p_methods = &piface_methods;
|
||||
pif->pif_parser.p_exec = pexec;
|
||||
pif->pif_parser.p_name = name;
|
||||
pif->pif_parser.p_nextparser = defnext;
|
||||
|
||||
pif->pif_key = defkey;
|
||||
|
||||
return pif;
|
||||
}
|
||||
|
||||
int
|
||||
pbranch_addbranch(struct pbranch *pb, struct parser *p)
|
||||
{
|
||||
struct branch *b;
|
||||
|
||||
if ((b = malloc(sizeof(*b))) == NULL)
|
||||
return -1;
|
||||
b->b_nextparser = p;
|
||||
SIMPLEQ_INSERT_HEAD(&pb->pb_branches, b, b_next);
|
||||
pb->pb_parser.p_initialized = false;
|
||||
return parser_init(&pb->pb_parser);
|
||||
}
|
||||
|
||||
int
|
||||
pbranch_setbranches(struct pbranch *pb, const struct branch *brs, size_t nbr)
|
||||
{
|
||||
struct branch *b;
|
||||
size_t i;
|
||||
|
||||
dbg_warnx("%s: nbr %zu", __func__, nbr);
|
||||
|
||||
while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) {
|
||||
SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next);
|
||||
free(b);
|
||||
}
|
||||
|
||||
for (i = 0; i < nbr; i++) {
|
||||
if ((b = malloc(sizeof(*b))) == NULL)
|
||||
goto err;
|
||||
*b = brs[i];
|
||||
dbg_warnx("%s: b->b_nextparser %p [%s]", __func__,
|
||||
b->b_nextparser, b->b_nextparser ? b->b_nextparser->p_name
|
||||
: "(null)");
|
||||
SIMPLEQ_INSERT_TAIL(&pb->pb_branches, b, b_next);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) {
|
||||
SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next);
|
||||
free(b);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
pbranch_init(struct parser *p)
|
||||
{
|
||||
struct branch *b;
|
||||
struct pbranch *pb = (struct pbranch *)p;
|
||||
struct parser *np;
|
||||
|
||||
if (pb->pb_nbrinit == 0)
|
||||
;
|
||||
else if (pbranch_setbranches(pb, pb->pb_brinit, pb->pb_nbrinit) == -1)
|
||||
return -1;
|
||||
|
||||
pb->pb_nbrinit = 0;
|
||||
|
||||
SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) {
|
||||
np = b->b_nextparser;
|
||||
if (np != NULL && parser_init(np) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pbranch *
|
||||
pbranch_create(const char *name, const struct branch *brs, size_t nbr,
|
||||
bool match_first)
|
||||
{
|
||||
struct pbranch *pb;
|
||||
|
||||
dbg_warnx("%s: nbr %zu", __func__, nbr);
|
||||
|
||||
if ((pb = calloc(1, sizeof(*pb))) == NULL)
|
||||
return NULL;
|
||||
|
||||
pb->pb_parser.p_methods = &pbranch_methods;
|
||||
pb->pb_parser.p_name = name;
|
||||
|
||||
SIMPLEQ_INIT(&pb->pb_branches);
|
||||
|
||||
if (pbranch_setbranches(pb, brs, nbr) == -1)
|
||||
goto post_pb_err;
|
||||
|
||||
pb->pb_match_first = match_first;
|
||||
return pb;
|
||||
post_pb_err:
|
||||
free(pb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
parser_default_init(struct parser *p)
|
||||
{
|
||||
struct parser *np;
|
||||
|
||||
np = p->p_nextparser;
|
||||
if (np != NULL && parser_init(np) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pkw_setwords(struct pkw *pk, parser_exec_t defexec, const char *defkey,
|
||||
const struct kwinst *kws, size_t nkw, struct parser *defnext)
|
||||
{
|
||||
struct kwinst *k;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nkw; i++) {
|
||||
if (kws[i].k_word == NULL)
|
||||
continue;
|
||||
if ((k = malloc(sizeof(*k))) == NULL)
|
||||
goto post_pk_err;
|
||||
*k = kws[i];
|
||||
if (k->k_nextparser == NULL)
|
||||
k->k_nextparser = defnext;
|
||||
if (k->k_key == NULL)
|
||||
k->k_key = defkey;
|
||||
if (k->k_exec == NULL)
|
||||
k->k_exec = defexec;
|
||||
SIMPLEQ_INSERT_TAIL(&pk->pk_keywords, k, k_next);
|
||||
}
|
||||
return 0;
|
||||
|
||||
post_pk_err:
|
||||
while ((k = SIMPLEQ_FIRST(&pk->pk_keywords)) != NULL) {
|
||||
SIMPLEQ_REMOVE_HEAD(&pk->pk_keywords, k_next);
|
||||
free(k);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
pkw_init(struct parser *p)
|
||||
{
|
||||
struct kwinst *k;
|
||||
struct pkw *pk = (struct pkw *)p;
|
||||
struct parser *np;
|
||||
|
||||
if (pk->pk_nkwinit == 0)
|
||||
;
|
||||
else if (pkw_setwords(pk, pk->pk_execinit, pk->pk_keyinit,
|
||||
pk->pk_kwinit, pk->pk_nkwinit, pk->pk_nextinit) == -1)
|
||||
return -1;
|
||||
|
||||
pk->pk_nkwinit = 0;
|
||||
|
||||
SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) {
|
||||
np = k->k_nextparser;
|
||||
if (np != NULL && parser_init(np) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pkw *
|
||||
pkw_create(const char *name, parser_exec_t defexec, const char *defkey,
|
||||
const struct kwinst *kws, size_t nkw, struct parser *defnext)
|
||||
{
|
||||
struct pkw *pk;
|
||||
|
||||
if ((pk = calloc(1, sizeof(*pk))) == NULL)
|
||||
return NULL;
|
||||
|
||||
pk->pk_parser.p_methods = &pkw_methods;
|
||||
pk->pk_parser.p_exec = defexec;
|
||||
pk->pk_parser.p_name = name;
|
||||
|
||||
SIMPLEQ_INIT(&pk->pk_keywords);
|
||||
|
||||
if (pkw_setwords(pk, defexec, defkey, kws, nkw, defnext) == -1)
|
||||
goto err;
|
||||
|
||||
return pk;
|
||||
err:
|
||||
free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
parse(int argc, char **argv, const struct parser *p0, struct match *matches,
|
||||
size_t *nmatch, int *narg)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct match *lastm = NULL, *m = matches;
|
||||
const struct parser *p = p0;
|
||||
|
||||
for (i = 0; i < argc && p != NULL; i++) {
|
||||
if ((size_t)(m - matches) >= *nmatch) {
|
||||
errno = EFBIG;
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
rc = (*p->p_methods->pm_match)(p, lastm, m, i, argv[i]);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
p = m->m_nextparser;
|
||||
lastm = m++;
|
||||
}
|
||||
for (; (size_t)(m - matches) < *nmatch && p != NULL; ) {
|
||||
rc = (*p->p_methods->pm_match)(p, lastm, m, i, NULL);
|
||||
if (rc != 0)
|
||||
break;
|
||||
p = m->m_nextparser;
|
||||
lastm = m++;
|
||||
}
|
||||
out:
|
||||
*nmatch = m - matches;
|
||||
*narg = i;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
matches_exec(const struct match *matches, prop_dictionary_t oenv, size_t nmatch)
|
||||
{
|
||||
size_t i;
|
||||
int rc = 0;
|
||||
const struct match *m;
|
||||
parser_exec_t pexec;
|
||||
prop_dictionary_t d;
|
||||
|
||||
for (i = 0; i < nmatch; i++) {
|
||||
m = &matches[i];
|
||||
dbg_warnx("%s.%d: i %zu", __func__, __LINE__, i);
|
||||
pexec = (m->m_parser->p_exec != NULL)
|
||||
? m->m_parser->p_exec : m->m_exec;
|
||||
if (pexec == NULL)
|
||||
continue;
|
||||
dbg_warnx("%s.%d: m->m_parser->p_name %s", __func__, __LINE__,
|
||||
m->m_parser->p_name);
|
||||
d = prop_dictionary_augment(m->m_env, oenv);
|
||||
rc = (*pexec)(d, oenv);
|
||||
prop_object_release((prop_object_t)d);
|
||||
if (rc == -1)
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
parser_init(struct parser *p)
|
||||
{
|
||||
if (p->p_initialized)
|
||||
return 0;
|
||||
p->p_initialized = true;
|
||||
if (p->p_methods->pm_init == NULL)
|
||||
return 0;
|
||||
return (*p->p_methods->pm_init)(p);
|
||||
}
|
||||
284
sbin/ifconfig/parse.h
Normal file
284
sbin/ifconfig/parse.h
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
#ifndef _IFCONFIG_PARSE_H
|
||||
#define _IFCONFIG_PARSE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/queue.h>
|
||||
#include <prop/proplib.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
struct match;
|
||||
struct parser;
|
||||
|
||||
extern struct pbranch command_root;
|
||||
|
||||
typedef int (*parser_exec_t)(prop_dictionary_t, prop_dictionary_t);
|
||||
typedef int (*parser_match_t)(const struct parser *, const struct match *,
|
||||
struct match *, int, const char *);
|
||||
typedef int (*parser_init_t)(struct parser *);
|
||||
|
||||
struct match {
|
||||
prop_dictionary_t m_env;
|
||||
const struct parser *m_nextparser;
|
||||
const struct parser *m_parser;
|
||||
int m_argidx;
|
||||
parser_exec_t m_exec;
|
||||
};
|
||||
|
||||
/* method table */
|
||||
struct parser_methods {
|
||||
parser_match_t pm_match;
|
||||
parser_init_t pm_init;
|
||||
};
|
||||
|
||||
struct parser {
|
||||
const struct parser_methods *p_methods;
|
||||
parser_exec_t p_exec;
|
||||
const char *p_name;
|
||||
struct parser *p_nextparser;
|
||||
bool p_initialized;
|
||||
};
|
||||
|
||||
struct branch {
|
||||
SIMPLEQ_ENTRY(branch) b_next;
|
||||
struct parser *b_nextparser;
|
||||
};
|
||||
|
||||
struct pbranch {
|
||||
struct parser pb_parser;
|
||||
SIMPLEQ_HEAD(, branch) pb_branches;
|
||||
bool pb_match_first;
|
||||
const struct branch *pb_brinit;
|
||||
size_t pb_nbrinit;
|
||||
};
|
||||
|
||||
struct pterm {
|
||||
struct parser pt_parser;
|
||||
const char *pt_key;
|
||||
};
|
||||
|
||||
extern const struct parser_methods paddr_methods;
|
||||
extern const struct parser_methods pbranch_methods;
|
||||
extern const struct parser_methods piface_methods;
|
||||
extern const struct parser_methods pinteger_methods;
|
||||
extern const struct parser_methods pstr_methods;
|
||||
extern const struct parser_methods pkw_methods;
|
||||
extern const struct parser_methods pterm_methods;
|
||||
|
||||
#define PTERM_INITIALIZER(__pt, __name, __exec, __key) \
|
||||
{ \
|
||||
.pt_parser = {.p_name = (__name), .p_methods = &pterm_methods, \
|
||||
.p_exec = (__exec)}, \
|
||||
.pt_key = (__key) \
|
||||
}
|
||||
|
||||
#define PBRANCH_INITIALIZER(__pb, __name, __brs, __nbr, __match_first) \
|
||||
{ \
|
||||
.pb_parser = {.p_name = (__name), .p_methods = &pbranch_methods},\
|
||||
.pb_branches = SIMPLEQ_HEAD_INITIALIZER((__pb)->pb_branches), \
|
||||
.pb_brinit = (__brs), \
|
||||
.pb_nbrinit = (__nbr), \
|
||||
.pb_match_first = (__match_first) \
|
||||
}
|
||||
|
||||
#define PSTR_INITIALIZER(__ps, __name, __defexec, __defkey, __defnext) \
|
||||
PSTR_INITIALIZER1((__ps), (__name), (__defexec), (__defkey), \
|
||||
true, (__defnext))
|
||||
|
||||
#define PSTR_INITIALIZER1(__ps, __name, __defexec, __defkey, __defhexok,\
|
||||
__defnext) \
|
||||
{ \
|
||||
.ps_parser = {.p_name = (__name), .p_methods = &pstr_methods, \
|
||||
.p_exec = (__defexec), \
|
||||
.p_nextparser = (__defnext)}, \
|
||||
.ps_key = (__defkey), \
|
||||
.ps_hexok = (__defhexok) \
|
||||
}
|
||||
|
||||
#define PADDR_INITIALIZER(__pa, __name, __defexec, __addrkey, \
|
||||
__maskkey, __activator, __deactivator, __defnext) \
|
||||
{ \
|
||||
.pa_parser = {.p_name = (__name), .p_methods = &paddr_methods, \
|
||||
.p_exec = (__defexec), \
|
||||
.p_nextparser = (__defnext)}, \
|
||||
.pa_addrkey = (__addrkey), \
|
||||
.pa_maskkey = (__maskkey), \
|
||||
.pa_activator = (__activator), \
|
||||
.pa_deactivator = (__deactivator), \
|
||||
}
|
||||
|
||||
#define PIFACE_INITIALIZER(__pif, __name, __defexec, __defkey, __defnext)\
|
||||
{ \
|
||||
.pif_parser = {.p_name = (__name), .p_methods = &piface_methods,\
|
||||
.p_exec = (__defexec), \
|
||||
.p_nextparser = (__defnext)}, \
|
||||
.pif_key = (__defkey) \
|
||||
}
|
||||
|
||||
#define PINTEGER_INITIALIZER1(__pi, __name, __min, __max, __base, \
|
||||
__defexec, __defkey, __defnext) \
|
||||
{ \
|
||||
.pi_parser = {.p_name = (__name), .p_methods = &pinteger_methods,\
|
||||
.p_exec = (__defexec), \
|
||||
.p_nextparser = (__defnext), \
|
||||
.p_initialized = false}, \
|
||||
.pi_min = (__min), \
|
||||
.pi_max = (__max), \
|
||||
.pi_base = (__base), \
|
||||
.pi_key = (__defkey) \
|
||||
}
|
||||
|
||||
#define PINTEGER_INITIALIZER(__pi, __name, __base, __defexec, __defkey, \
|
||||
__defnext) \
|
||||
PINTEGER_INITIALIZER1(__pi, __name, INTMAX_MIN, INTMAX_MAX, \
|
||||
__base, __defexec, __defkey, __defnext)
|
||||
|
||||
#define PKW_INITIALIZER(__pk, __name, __defexec, __defkey, __kws, __nkw,\
|
||||
__defnext) \
|
||||
{ \
|
||||
.pk_parser = {.p_name = (__name), \
|
||||
.p_exec = (__defexec), \
|
||||
.p_methods = &pkw_methods, \
|
||||
.p_initialized = false}, \
|
||||
.pk_keywords = SIMPLEQ_HEAD_INITIALIZER((__pk)->pk_keywords), \
|
||||
.pk_kwinit = (__kws), \
|
||||
.pk_nkwinit = (__nkw), \
|
||||
.pk_keyinit = (__defkey), \
|
||||
.pk_nextinit = (__defnext) \
|
||||
}
|
||||
|
||||
#define IFKW(__word, __flag) \
|
||||
{ \
|
||||
.k_word = (__word), .k_neg = true, .k_type = KW_T_INT, \
|
||||
.k_int = (__flag), \
|
||||
.k_negint = -(__flag) \
|
||||
}
|
||||
|
||||
#define KW_T_NONE 0
|
||||
#define KW_T_OBJ 1
|
||||
#define KW_T_INT 2
|
||||
#define KW_T_STR 3
|
||||
#define KW_T_BOOL 4
|
||||
#define KW_T_UINT 5
|
||||
|
||||
struct kwinst {
|
||||
SIMPLEQ_ENTRY(kwinst) k_next;
|
||||
int k_type;
|
||||
const char *k_word;
|
||||
const char *k_key;
|
||||
const char *k_act;
|
||||
const char *k_deact;
|
||||
const char *k_altdeact;
|
||||
parser_exec_t k_exec;
|
||||
union kwval {
|
||||
int64_t u_sint;
|
||||
uint64_t u_uint;
|
||||
const char *u_str;
|
||||
prop_object_t u_obj;
|
||||
bool u_bool;
|
||||
} k_u, k_negu;
|
||||
#define k_int k_u.u_sint
|
||||
#define k_uint k_u.u_uint
|
||||
#define k_str k_u.u_str
|
||||
#define k_obj k_u.u_obj
|
||||
#define k_bool k_u.u_bool
|
||||
|
||||
#define k_negint k_negu.u_sint
|
||||
#define k_neguint k_negu.u_uint
|
||||
#define k_negstr k_negu.u_str
|
||||
#define k_negobj k_negu.u_obj
|
||||
#define k_negbool k_negu.u_bool
|
||||
|
||||
bool k_neg; /* allow negative form, -keyword */
|
||||
struct parser *k_nextparser;
|
||||
};
|
||||
|
||||
struct pkw {
|
||||
struct parser pk_parser;
|
||||
const char *pk_key;
|
||||
const char *pk_keyinit;
|
||||
const struct kwinst *pk_kwinit;
|
||||
size_t pk_nkwinit;
|
||||
SIMPLEQ_HEAD(, kwinst) pk_keywords;
|
||||
};
|
||||
|
||||
#define pk_nextinit pk_parser.p_nextparser
|
||||
#define pk_execinit pk_parser.p_exec
|
||||
|
||||
struct pstr {
|
||||
struct parser ps_parser;
|
||||
const char *ps_key;
|
||||
bool ps_hexok;
|
||||
};
|
||||
|
||||
struct pinteger {
|
||||
struct parser pi_parser;
|
||||
int64_t pi_min;
|
||||
int64_t pi_max;
|
||||
int pi_base;
|
||||
const char *pi_key;
|
||||
};
|
||||
|
||||
struct intrange {
|
||||
SIMPLEQ_ENTRY(intrange) r_next;
|
||||
int64_t r_bottom;
|
||||
int64_t r_top;
|
||||
struct parser *r_nextparser;
|
||||
};
|
||||
|
||||
struct pranges {
|
||||
struct parser pr_parser;
|
||||
SIMPLEQ_HEAD(, intrange) pr_ranges;
|
||||
};
|
||||
|
||||
struct paddr_prefix {
|
||||
int16_t pfx_len;
|
||||
struct sockaddr pfx_addr;
|
||||
};
|
||||
|
||||
static inline size_t
|
||||
paddr_prefix_size(const struct paddr_prefix *pfx)
|
||||
{
|
||||
return offsetof(struct paddr_prefix, pfx_addr) + pfx->pfx_addr.sa_len;
|
||||
}
|
||||
|
||||
struct paddr {
|
||||
struct parser pa_parser;
|
||||
const char *pa_addrkey;
|
||||
const char *pa_maskkey;
|
||||
const char *pa_activator;
|
||||
const char *pa_deactivator;
|
||||
};
|
||||
|
||||
struct piface {
|
||||
struct parser pif_parser;
|
||||
const char *pif_key;
|
||||
};
|
||||
|
||||
struct prest {
|
||||
struct parser pr_parser;
|
||||
};
|
||||
|
||||
struct prest *prest_create(const char *);
|
||||
struct paddr *paddr_create(const char *, parser_exec_t, const char *,
|
||||
const char *, struct parser *);
|
||||
struct pstr *pstr_create(const char *, parser_exec_t, const char *,
|
||||
bool, struct parser *);
|
||||
struct piface *piface_create(const char *, parser_exec_t, const char *,
|
||||
struct parser *);
|
||||
struct pkw *pkw_create(const char *, parser_exec_t,
|
||||
const char *, const struct kwinst *, size_t, struct parser *);
|
||||
struct pranges *pranges_create(const char *, parser_exec_t, const char *,
|
||||
const struct intrange *, size_t, struct parser *);
|
||||
struct pbranch *pbranch_create(const char *, const struct branch *, size_t,
|
||||
bool);
|
||||
int pbranch_addbranch(struct pbranch *, struct parser *);
|
||||
int pbranch_setbranches(struct pbranch *, const struct branch *, size_t);
|
||||
|
||||
int parse(int, char **, const struct parser *, struct match *, size_t *, int *);
|
||||
|
||||
int matches_exec(const struct match *, prop_dictionary_t, size_t);
|
||||
int parser_init(struct parser *);
|
||||
|
||||
#endif /* _IFCONFIG_PARSE_H */
|
||||
229
sbin/ifconfig/pfsync.c
Normal file
229
sbin/ifconfig/pfsync.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/* $NetBSD: pfsync.c,v 1.1 2009/09/14 10:36:49 degroote Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: pfsync.c,v 1.1 2009/09/14 10:36:49 degroote Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pfsync.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "parse.h"
|
||||
#include "extern.h"
|
||||
|
||||
static status_func_t status;
|
||||
static usage_func_t usage;
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void pfsync_constructor(void) __attribute__((constructor));
|
||||
static void pfsync_status(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setpfsync_maxupd(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setpfsync_peer(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setpfsyncdev(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
struct pinteger parse_maxupd = PINTEGER_INITIALIZER1(&parse_maxupd, "maxupd",
|
||||
0, 255, 10, setpfsync_maxupd, "maxupd", &command_root.pb_parser);
|
||||
|
||||
struct piface pfsyncdev = PIFACE_INITIALIZER(&pfsyncdev, "syncdev", setpfsyncdev,
|
||||
"syncdev", &command_root.pb_parser);
|
||||
|
||||
struct paddr parse_sync_peer = PADDR_INITIALIZER(&parse_sync_peer, "syncpeer",
|
||||
setpfsync_peer, "syncpeer", NULL, NULL, NULL, &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst pfsynckw[] = {
|
||||
{.k_word = "maxupd", .k_nextparser = &parse_maxupd.pi_parser},
|
||||
{.k_word = "syncdev", .k_nextparser = &pfsyncdev.pif_parser},
|
||||
{.k_word = "-syncdev", .k_key = "syncdev", .k_type = KW_T_STR,
|
||||
.k_str = "", .k_exec = setpfsyncdev,
|
||||
.k_nextparser = &command_root.pb_parser},
|
||||
{.k_word = "syncpeer", .k_nextparser = &parse_sync_peer.pa_parser},
|
||||
{.k_word = "-syncpeer", .k_key = "syncpeer", .k_type = KW_T_STR,
|
||||
.k_str = "", .k_exec = setpfsync_peer,
|
||||
.k_nextparser = &command_root.pb_parser}
|
||||
};
|
||||
|
||||
struct pkw pfsync = PKW_INITIALIZER(&pfsync, "pfsync", NULL, NULL,
|
||||
pfsynckw, __arraycount(pfsynckw), NULL);
|
||||
|
||||
static void
|
||||
pfsync_set(prop_dictionary_t env, struct pfsyncreq *pfsyncr)
|
||||
{
|
||||
if (indirect_ioctl(env, SIOCSETPFSYNC, pfsyncr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSETPFSYNC");
|
||||
}
|
||||
|
||||
static int
|
||||
pfsync_get1(prop_dictionary_t env, struct pfsyncreq *pfsyncr)
|
||||
{
|
||||
memset(pfsyncr, 0, sizeof(*pfsyncr));
|
||||
|
||||
return indirect_ioctl(env, SIOCGETPFSYNC, pfsyncr);
|
||||
}
|
||||
|
||||
static void
|
||||
pfsync_get(prop_dictionary_t env, struct pfsyncreq *pfsyncr)
|
||||
{
|
||||
if (pfsync_get1(env, pfsyncr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCGETPFSYNC");
|
||||
}
|
||||
|
||||
static void
|
||||
pfsync_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct pfsyncreq pfsyncr;
|
||||
|
||||
if (pfsync_get1(env, &pfsyncr) == -1)
|
||||
return;
|
||||
|
||||
if (pfsyncr.pfsyncr_syncdev[0] != '\0') {
|
||||
printf("\tpfsync: syncdev: %s ", pfsyncr.pfsyncr_syncdev);
|
||||
if (pfsyncr.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP)
|
||||
printf("syncpeer: %s ",
|
||||
inet_ntoa(pfsyncr.pfsyncr_syncpeer));
|
||||
printf("maxupd: %d\n", pfsyncr.pfsyncr_maxupdates);
|
||||
}
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
setpfsync_maxupd(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct pfsyncreq pfsyncr;
|
||||
uint8_t maxupd;
|
||||
|
||||
if (!prop_dictionary_get_uint8(env, "maxupd", &maxupd)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfsync_get(env, &pfsyncr);
|
||||
|
||||
pfsyncr.pfsyncr_maxupdates = maxupd;
|
||||
|
||||
pfsync_set(env, &pfsyncr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
setpfsyncdev(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct pfsyncreq pfsyncr;
|
||||
const char *dev;
|
||||
|
||||
if (!prop_dictionary_get_cstring_nocopy(env, "syncdev", &dev)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfsync_get(env, &pfsyncr);
|
||||
|
||||
strlcpy(pfsyncr.pfsyncr_syncdev, dev, sizeof(pfsyncr.pfsyncr_syncdev));
|
||||
|
||||
pfsync_set(env, &pfsyncr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
setpfsync_peer(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct pfsyncreq pfsyncr;
|
||||
prop_data_t data;
|
||||
const struct paddr_prefix *peerpfx;
|
||||
const struct sockaddr_in *s;
|
||||
|
||||
data = (prop_data_t)prop_dictionary_get(env, "syncpeer");
|
||||
if (data == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfsync_get(env, &pfsyncr);
|
||||
|
||||
peerpfx = prop_data_data_nocopy(data);
|
||||
|
||||
if (peerpfx != NULL) {
|
||||
// Only AF_INET is supported for now
|
||||
if (peerpfx->pfx_addr.sa_family != AF_INET) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
s = (const struct sockaddr_in*)&peerpfx->pfx_addr;
|
||||
|
||||
memcpy(&pfsyncr.pfsyncr_syncpeer.s_addr, &s->sin_addr,
|
||||
MIN(sizeof(pfsyncr.pfsyncr_syncpeer.s_addr),
|
||||
peerpfx->pfx_addr.sa_len));
|
||||
} else {
|
||||
memset(&pfsyncr.pfsyncr_syncpeer.s_addr, 0,
|
||||
sizeof(pfsyncr.pfsyncr_syncpeer.s_addr));
|
||||
}
|
||||
|
||||
pfsync_set(env, &pfsyncr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pfsync_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\t[ maxupd n ] [ syncdev iface ] [syncpeer peer_addr]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
pfsync_constructor(void)
|
||||
{
|
||||
cmdloop_branch_init(&branch, &pfsync.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
status_func_init(&status, pfsync_status);
|
||||
usage_func_init(&usage, pfsync_usage);
|
||||
register_status(&status);
|
||||
register_usage(&usage);
|
||||
}
|
||||
61
sbin/ifconfig/prog_ops.h
Normal file
61
sbin/ifconfig/prog_ops.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* $NetBSD: prog_ops.h,v 1.3 2010/12/13 21:48:01 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROG_OPS_H_
|
||||
#define _PROG_OPS_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* ifconfig is compiled outside of src/sbin/ifconfig too */
|
||||
#ifndef CRUNCHOPS
|
||||
struct prog_ops {
|
||||
int (*op_init)(void);
|
||||
|
||||
int (*op_socket)(int, int, int);
|
||||
|
||||
int (*op_ioctl)(int, unsigned long, ...);
|
||||
ssize_t (*op_read)(int, void *, size_t);
|
||||
|
||||
int (*op_close)(int);
|
||||
};
|
||||
extern const struct prog_ops prog_ops;
|
||||
|
||||
#define prog_init prog_ops.op_init
|
||||
#define prog_socket prog_ops.op_socket
|
||||
#define prog_ioctl prog_ops.op_ioctl
|
||||
#define prog_read prog_ops.op_read
|
||||
#define prog_close prog_ops.op_close
|
||||
#else
|
||||
#define prog_init ((int (*)(void))NULL)
|
||||
#define prog_socket socket
|
||||
#define prog_ioctl ioctl
|
||||
#define prog_read read
|
||||
#define prog_close close
|
||||
#endif
|
||||
|
||||
#endif /* _PROG_OPS_H_ */
|
||||
204
sbin/ifconfig/tunnel.c
Normal file
204
sbin/ifconfig/tunnel.c
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/* $NetBSD: tunnel.c,v 1.20 2013/10/19 15:59:15 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: tunnel.c,v 1.20 2013/10/19 15:59:15 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#ifdef INET6
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
|
||||
static status_func_t status;
|
||||
static usage_func_t usage;
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void tunnel_constructor(void) __attribute__((constructor));
|
||||
static int settunnel(prop_dictionary_t, prop_dictionary_t);
|
||||
static int deletetunnel(prop_dictionary_t, prop_dictionary_t);
|
||||
static void tunnel_status(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
struct paddr tundst = PADDR_INITIALIZER(&tundst, "tundst", settunnel,
|
||||
"tundst", NULL, NULL, NULL, &command_root.pb_parser);
|
||||
|
||||
struct paddr tunsrc = PADDR_INITIALIZER(&tunsrc, "tunsrc", NULL,
|
||||
"tunsrc", NULL, NULL, NULL, &tundst.pa_parser);
|
||||
|
||||
static const struct kwinst tunnelkw[] = {
|
||||
{.k_word = "deletetunnel", .k_exec = deletetunnel,
|
||||
.k_nextparser = &command_root.pb_parser}
|
||||
, {.k_word = "tunnel", .k_nextparser = &tunsrc.pa_parser}
|
||||
};
|
||||
|
||||
struct pkw tunnel = PKW_INITIALIZER(&tunnel, "tunnel", NULL, NULL,
|
||||
tunnelkw, __arraycount(tunnelkw), NULL);
|
||||
|
||||
static int
|
||||
settunnel(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
const struct paddr_prefix *srcpfx, *dstpfx;
|
||||
struct if_laddrreq req;
|
||||
prop_data_t srcdata, dstdata;
|
||||
|
||||
srcdata = (prop_data_t)prop_dictionary_get(env, "tunsrc");
|
||||
dstdata = (prop_data_t)prop_dictionary_get(env, "tundst");
|
||||
|
||||
if (srcdata == NULL || dstdata == NULL) {
|
||||
warnx("%s.%d", __func__, __LINE__);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcpfx = prop_data_data_nocopy(srcdata);
|
||||
dstpfx = prop_data_data_nocopy(dstdata);
|
||||
|
||||
if (srcpfx->pfx_addr.sa_family != dstpfx->pfx_addr.sa_family)
|
||||
errx(EXIT_FAILURE,
|
||||
"source and destination address families do not match");
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memcpy(&req.addr, &srcpfx->pfx_addr,
|
||||
MIN(sizeof(req.addr), srcpfx->pfx_addr.sa_len));
|
||||
memcpy(&req.dstaddr, &dstpfx->pfx_addr,
|
||||
MIN(sizeof(req.dstaddr), dstpfx->pfx_addr.sa_len));
|
||||
|
||||
#ifdef INET6
|
||||
if (req.addr.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *s6, *d;
|
||||
|
||||
s6 = (struct sockaddr_in6 *)&req.addr;
|
||||
d = (struct sockaddr_in6 *)&req.dstaddr;
|
||||
if (s6->sin6_scope_id != d->sin6_scope_id) {
|
||||
errx(EXIT_FAILURE, "scope mismatch");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (IN6_IS_ADDR_MULTICAST(&d->sin6_addr) ||
|
||||
IN6_IS_ADDR_MULTICAST(&s6->sin6_addr))
|
||||
errx(EXIT_FAILURE, "tunnel src/dst is multicast");
|
||||
/* embed scopeid */
|
||||
inet6_putscopeid(s6, INET6_IS_ADDR_LINKLOCAL);
|
||||
inet6_putscopeid(d, INET6_IS_ADDR_LINKLOCAL);
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
if (direct_ioctl(env, SIOCSLIFPHYADDR, &req) == -1)
|
||||
warn("SIOCSLIFPHYADDR");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
deletetunnel(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
if (indirect_ioctl(env, SIOCDIFPHYADDR, NULL) == -1)
|
||||
err(EXIT_FAILURE, "SIOCDIFPHYADDR");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tunnel_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
char dstserv[sizeof(",65535")];
|
||||
char srcserv[sizeof(",65535")];
|
||||
char psrcaddr[NI_MAXHOST];
|
||||
char pdstaddr[NI_MAXHOST];
|
||||
const int niflag = Nflag ? 0 : (NI_NUMERICHOST|NI_NUMERICSERV);
|
||||
struct if_laddrreq req;
|
||||
const struct afswtch *afp;
|
||||
|
||||
psrcaddr[0] = pdstaddr[0] = '\0';
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
if (direct_ioctl(env, SIOCGLIFPHYADDR, &req) == -1)
|
||||
return;
|
||||
afp = lookup_af_bynum(req.addr.ss_family);
|
||||
#ifdef INET6
|
||||
if (req.addr.ss_family == AF_INET6)
|
||||
inet6_getscopeid((struct sockaddr_in6 *)&req.addr,
|
||||
INET6_IS_ADDR_LINKLOCAL);
|
||||
#endif /* INET6 */
|
||||
getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len,
|
||||
psrcaddr, sizeof(psrcaddr), &srcserv[1], sizeof(srcserv) - 1,
|
||||
niflag);
|
||||
|
||||
#ifdef INET6
|
||||
if (req.dstaddr.ss_family == AF_INET6)
|
||||
inet6_getscopeid((struct sockaddr_in6 *)&req.dstaddr,
|
||||
INET6_IS_ADDR_LINKLOCAL);
|
||||
#endif
|
||||
getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len,
|
||||
pdstaddr, sizeof(pdstaddr), &dstserv[1], sizeof(dstserv) - 1,
|
||||
niflag);
|
||||
|
||||
srcserv[0] = (strcmp(&srcserv[1], "0") == 0) ? '\0' : ',';
|
||||
dstserv[0] = (strcmp(&dstserv[1], "0") == 0) ? '\0' : ',';
|
||||
|
||||
printf("\ttunnel %s %s%s --> %s%s\n", afp ? afp->af_name : "???",
|
||||
psrcaddr, srcserv, pdstaddr, dstserv);
|
||||
}
|
||||
|
||||
static void
|
||||
tunnel_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
tunnel_constructor(void)
|
||||
{
|
||||
cmdloop_branch_init(&branch, &tunnel.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
status_func_init(&status, tunnel_status);
|
||||
usage_func_init(&usage, tunnel_usage);
|
||||
register_status(&status);
|
||||
register_usage(&usage);
|
||||
}
|
||||
346
sbin/ifconfig/util.c
Normal file
346
sbin/ifconfig/util.c
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
/* $NetBSD: util.c,v 1.17 2013/10/19 00:35:30 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: util.c,v 1.17 2013/10/19 00:35:30 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in.h> /* XXX */
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "util.h"
|
||||
#include "prog_ops.h"
|
||||
|
||||
int
|
||||
getsock(int naf)
|
||||
{
|
||||
static int oaf = -1, s;
|
||||
|
||||
if (oaf == naf || (oaf != -1 && naf == AF_UNSPEC))
|
||||
return s;
|
||||
|
||||
if (oaf != -1)
|
||||
prog_close(s);
|
||||
|
||||
if (naf == AF_UNSPEC)
|
||||
naf = AF_INET;
|
||||
|
||||
s = prog_socket(naf, SOCK_DGRAM, 0);
|
||||
if (s == -1)
|
||||
oaf = -1;
|
||||
else
|
||||
oaf = naf;
|
||||
return s;
|
||||
}
|
||||
|
||||
const char *
|
||||
get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp,
|
||||
bool hexok)
|
||||
{
|
||||
int len;
|
||||
bool hexstr;
|
||||
u_int8_t *p;
|
||||
|
||||
len = *lenp;
|
||||
p = buf;
|
||||
hexstr = hexok && val[0] == '0' && tolower((u_char)val[1]) == 'x';
|
||||
if (hexstr)
|
||||
val += 2;
|
||||
for (;;) {
|
||||
if (*val == '\0')
|
||||
break;
|
||||
if (sep != NULL && strchr(sep, *val) != NULL) {
|
||||
val++;
|
||||
break;
|
||||
}
|
||||
if (hexstr) {
|
||||
if (!isxdigit((u_char)val[0]) ||
|
||||
!isxdigit((u_char)val[1])) {
|
||||
warnx("bad hexadecimal digits");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (p >= buf + len) {
|
||||
if (hexstr)
|
||||
warnx("hexadecimal digits too long");
|
||||
else
|
||||
warnx("strings too long");
|
||||
return NULL;
|
||||
}
|
||||
if (hexstr) {
|
||||
#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
|
||||
*p++ = (tohex((u_char)val[0]) << 4) |
|
||||
tohex((u_char)val[1]);
|
||||
#undef tohex
|
||||
val += 2;
|
||||
} else
|
||||
*p++ = *val++;
|
||||
}
|
||||
len = p - buf;
|
||||
if (len < *lenp)
|
||||
memset(p, 0, *lenp - len);
|
||||
*lenp = len;
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
print_string(const u_int8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
bool hasspc;
|
||||
|
||||
i = 0;
|
||||
hasspc = false;
|
||||
if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
|
||||
for (; i < len; i++) {
|
||||
if (!isprint(buf[i]))
|
||||
break;
|
||||
if (isspace(buf[i]))
|
||||
hasspc = true;
|
||||
}
|
||||
}
|
||||
if (i == len) {
|
||||
if (hasspc || len == 0)
|
||||
printf("\"%.*s\"", len, buf);
|
||||
else
|
||||
printf("%.*s", len, buf);
|
||||
} else {
|
||||
printf("0x");
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x", buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct paddr_prefix *
|
||||
prefixlen_to_mask(int af, int plen)
|
||||
{
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} u;
|
||||
struct paddr_prefix *pfx;
|
||||
size_t addrlen;
|
||||
uint8_t *addr;
|
||||
int nbit;
|
||||
|
||||
memset(&u, 0, sizeof(u));
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
addrlen = sizeof(u.sin.sin_addr);
|
||||
addr = (uint8_t *)&u.sin.sin_addr;
|
||||
u.sa.sa_len = sizeof(u.sin);
|
||||
break;
|
||||
case AF_INET6:
|
||||
addrlen = sizeof(u.sin6.sin6_addr);
|
||||
addr = (uint8_t *)&u.sin6.sin6_addr;
|
||||
u.sa.sa_len = sizeof(u.sin6);
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
u.sa.sa_family = af;
|
||||
|
||||
if (plen < 0 || (size_t)plen > addrlen * NBBY) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (plen == 0)
|
||||
plen = addrlen * NBBY;
|
||||
|
||||
memset(addr, 0xff, (plen + NBBY - 1) / NBBY);
|
||||
|
||||
nbit = plen % NBBY;
|
||||
if (nbit != 0)
|
||||
addr[plen / NBBY] &= ~((uint8_t)0xff >> nbit);
|
||||
pfx = malloc(offsetof(struct paddr_prefix, pfx_addr) + u.sa.sa_len);
|
||||
if (pfx == NULL)
|
||||
return NULL;
|
||||
pfx->pfx_len = plen;
|
||||
memcpy(&pfx->pfx_addr, &u.sa, u.sa.sa_len);
|
||||
|
||||
return pfx;
|
||||
}
|
||||
|
||||
int
|
||||
direct_ioctl(prop_dictionary_t env, unsigned long cmd, void *data)
|
||||
{
|
||||
const char *ifname;
|
||||
int s;
|
||||
|
||||
if ((s = getsock(AF_UNSPEC)) == -1)
|
||||
err(EXIT_FAILURE, "getsock");
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "getifname");
|
||||
|
||||
estrlcpy(data, ifname, IFNAMSIZ);
|
||||
|
||||
return prog_ioctl(s, cmd, data);
|
||||
}
|
||||
|
||||
int
|
||||
indirect_ioctl(prop_dictionary_t env, unsigned long cmd, void *data)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
ifr.ifr_data = data;
|
||||
|
||||
return direct_ioctl(env, cmd, &ifr);
|
||||
}
|
||||
|
||||
void
|
||||
print_link_addresses(prop_dictionary_t env, bool print_active_only)
|
||||
{
|
||||
char hbuf[NI_MAXHOST];
|
||||
const char *ifname;
|
||||
int s;
|
||||
struct ifaddrs *ifa, *ifap;
|
||||
const struct sockaddr_dl *sdl;
|
||||
struct if_laddrreq iflr;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
err(EXIT_FAILURE, "%s: getifname", __func__);
|
||||
|
||||
if ((s = getsock(AF_LINK)) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
|
||||
if (getifaddrs(&ifap) == -1)
|
||||
err(EXIT_FAILURE, "%s: getifaddrs", __func__);
|
||||
|
||||
memset(&iflr, 0, sizeof(iflr));
|
||||
|
||||
strlcpy(iflr.iflr_name, ifname, sizeof(iflr.iflr_name));
|
||||
|
||||
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (strcmp(ifname, ifa->ifa_name) != 0)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
|
||||
sdl = satocsdl(ifa->ifa_addr);
|
||||
|
||||
memcpy(&iflr.addr, ifa->ifa_addr, MIN(ifa->ifa_addr->sa_len,
|
||||
sizeof(iflr.addr)));
|
||||
iflr.flags = IFLR_PREFIX;
|
||||
iflr.prefixlen = sdl->sdl_alen * NBBY;
|
||||
|
||||
if (prog_ioctl(s, SIOCGLIFADDR, &iflr) == -1)
|
||||
err(EXIT_FAILURE, "%s: ioctl", __func__);
|
||||
|
||||
if (((iflr.flags & IFLR_ACTIVE) != 0) != print_active_only)
|
||||
continue;
|
||||
|
||||
if (getnameinfo(ifa->ifa_addr, ifa->ifa_addr->sa_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0,
|
||||
Nflag ? 0 : NI_NUMERICHOST) == 0 &&
|
||||
hbuf[0] != '\0') {
|
||||
printf("\t%s %s\n",
|
||||
print_active_only ? "address:" : "link", hbuf);
|
||||
}
|
||||
}
|
||||
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 (prog_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;
|
||||
}
|
||||
33
sbin/ifconfig/util.h
Normal file
33
sbin/ifconfig/util.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _IFCONFIG_UTIL_H
|
||||
#define _IFCONFIG_UTIL_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
struct afswtch {
|
||||
const char *af_name;
|
||||
short af_af;
|
||||
void (*af_status)(prop_dictionary_t, prop_dictionary_t, bool);
|
||||
void (*af_addr_commit)(prop_dictionary_t, prop_dictionary_t);
|
||||
bool (*af_addr_tentative)(struct ifaddrs *);
|
||||
SIMPLEQ_ENTRY(afswtch) af_next;
|
||||
};
|
||||
|
||||
void print_link_addresses(prop_dictionary_t, bool);
|
||||
const char *get_string(const char *, const char *, u_int8_t *, int *, bool);
|
||||
const struct afswtch *lookup_af_byname(const char *);
|
||||
const struct afswtch *lookup_af_bynum(int);
|
||||
void print_string(const u_int8_t *, int);
|
||||
int getsock(int);
|
||||
struct paddr_prefix *prefixlen_to_mask(int, int);
|
||||
int direct_ioctl(prop_dictionary_t, unsigned long, void *);
|
||||
int indirect_ioctl(prop_dictionary_t, unsigned long, void *);
|
||||
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 */
|
||||
190
sbin/ifconfig/vlan.c
Normal file
190
sbin/ifconfig/vlan.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* $NetBSD: vlan.c,v 1.14 2014/09/15 06:46:04 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: vlan.c,v 1.14 2014/09/15 06:46:04 ozaki-r Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <net/if_vlanvar.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "extern.h"
|
||||
#include "util.h"
|
||||
|
||||
static status_func_t status;
|
||||
static usage_func_t usage;
|
||||
static cmdloop_branch_t branch;
|
||||
|
||||
static void vlan_constructor(void) __attribute__((constructor));
|
||||
static void vlan_status(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
static int setvlan(prop_dictionary_t, prop_dictionary_t);
|
||||
static int setvlanif(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
struct pinteger vlantag = PINTEGER_INITIALIZER1(&vlantag, "VLAN tag",
|
||||
0, USHRT_MAX, 10, setvlan, "vlantag", &command_root.pb_parser);
|
||||
|
||||
struct piface vlanif = PIFACE_INITIALIZER(&vlanif, "vlanif", setvlanif,
|
||||
"vlanif", &command_root.pb_parser);
|
||||
|
||||
static const struct kwinst vlankw[] = {
|
||||
{.k_word = "vlan", .k_nextparser = &vlantag.pi_parser}
|
||||
, {.k_word = "vlanif", .k_act = "vlantag",
|
||||
.k_nextparser = &vlanif.pif_parser}
|
||||
, {.k_word = "-vlanif", .k_key = "vlanif", .k_type = KW_T_STR,
|
||||
.k_str = "", .k_exec = setvlanif}
|
||||
};
|
||||
|
||||
struct pkw vlan = PKW_INITIALIZER(&vlan, "vlan", NULL, NULL,
|
||||
vlankw, __arraycount(vlankw), NULL);
|
||||
|
||||
static int
|
||||
checkifname(prop_dictionary_t env)
|
||||
{
|
||||
const char *ifname;
|
||||
|
||||
if ((ifname = getifname(env)) == NULL)
|
||||
return 1;
|
||||
|
||||
return strncmp(ifname, "vlan", 4) != 0 ||
|
||||
!isdigit((unsigned char)ifname[4]);
|
||||
}
|
||||
|
||||
static int
|
||||
getvlan(prop_dictionary_t env, struct vlanreq *vlr, bool quiet)
|
||||
{
|
||||
memset(vlr, 0, sizeof(*vlr));
|
||||
|
||||
if (checkifname(env)) {
|
||||
if (quiet)
|
||||
return -1;
|
||||
errx(EXIT_FAILURE, "valid only with vlan(4) interfaces");
|
||||
}
|
||||
|
||||
if (indirect_ioctl(env, SIOCGETVLAN, vlr) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setvlan(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct vlanreq vlr;
|
||||
int64_t tag;
|
||||
|
||||
if (getvlan(env, &vlr, false) == -1)
|
||||
err(EXIT_FAILURE, "%s: getvlan", __func__);
|
||||
|
||||
if (!prop_dictionary_get_int64(env, "vlantag", &tag)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
vlr.vlr_tag = tag;
|
||||
|
||||
if (indirect_ioctl(env, SIOCSETVLAN, &vlr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSETVLAN");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setvlanif(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct vlanreq vlr;
|
||||
const char *parent;
|
||||
int64_t tag;
|
||||
|
||||
if (getvlan(env, &vlr, false) == -1)
|
||||
err(EXIT_FAILURE, "%s: getsock", __func__);
|
||||
|
||||
if (!prop_dictionary_get_cstring_nocopy(env, "vlanif", &parent)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
strlcpy(vlr.vlr_parent, parent, sizeof(vlr.vlr_parent));
|
||||
if (strcmp(parent, "") == 0)
|
||||
;
|
||||
else if (!prop_dictionary_get_int64(env, "vlantag", &tag)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
} else
|
||||
vlr.vlr_tag = (unsigned short)tag;
|
||||
|
||||
if (indirect_ioctl(env, SIOCSETVLAN, &vlr) == -1)
|
||||
err(EXIT_FAILURE, "SIOCSETVLAN");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vlan_status(prop_dictionary_t env, prop_dictionary_t oenv)
|
||||
{
|
||||
struct vlanreq vlr;
|
||||
|
||||
if (getvlan(env, &vlr, true) == -1)
|
||||
return;
|
||||
|
||||
if (vlr.vlr_tag || vlr.vlr_parent[0] != '\0')
|
||||
printf("\tvlan: %d parent: %s\n",
|
||||
vlr.vlr_tag, vlr.vlr_parent[0] == '\0' ?
|
||||
"<none>" : vlr.vlr_parent);
|
||||
}
|
||||
|
||||
static void
|
||||
vlan_usage(prop_dictionary_t env)
|
||||
{
|
||||
fprintf(stderr, "\t[ vlan n vlanif i ] [ -vlanif i ]\n");
|
||||
}
|
||||
|
||||
static void
|
||||
vlan_constructor(void)
|
||||
{
|
||||
cmdloop_branch_init(&branch, &vlan.pk_parser);
|
||||
register_cmdloop_branch(&branch);
|
||||
status_func_init(&status, vlan_status);
|
||||
usage_func_init(&usage, vlan_usage);
|
||||
register_status(&status);
|
||||
register_usage(&usage);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user