Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F171476902
D40182.id122214.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D40182.id122214.diff
View Options
diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -55,8 +55,26 @@
#include "ifconfig.h"
#include "ifconfig_netlink.h"
+#ifdef WITHOUT_NETLINK
static struct in_aliasreq in_addreq;
static struct ifreq in_ridreq;
+#else
+struct in_px {
+ struct in_addr addr;
+ int plen;
+ bool addrset;
+ bool maskset;
+};
+struct in_pdata {
+ struct in_px addr;
+ struct in_px dst_addr;
+ struct in_px brd_addr;
+ uint32_t flags;
+ uint32_t vhid;
+};
+static struct in_pdata in_add, in_del;
+#endif
+
static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
extern char *f_inet, *f_addr;
@@ -182,6 +200,8 @@
}
#endif
+
+#ifdef WITHOUT_NETLINK
#define SIN(x) ((struct sockaddr_in *) &(x))
static struct sockaddr_in *sintab[] = {
SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
@@ -233,14 +253,156 @@
errx(1, "%s: bad value", s);
}
+#else
+
+static struct in_px *sintab_nl[] = {
+ &in_del.addr, /* RIDADDR */
+ &in_add.addr, /* ADDR */
+ NULL, /* MASK */
+ &in_add.dst_addr, /* DSTADDR*/
+ &in_add.brd_addr, /* BRDADDR*/
+};
+
+static void
+in_getip(const char *addr_str, struct in_addr *ip)
+{
+ struct hostent *hp;
+ struct netent *np;
+
+ if (inet_aton(addr_str, ip))
+ return;
+ if ((hp = gethostbyname(addr_str)) != NULL)
+ bcopy(hp->h_addr, (char *)ip,
+ MIN((size_t)hp->h_length, sizeof(ip)));
+ else if ((np = getnetbyname(addr_str)) != NULL)
+ *ip = inet_makeaddr(np->n_net, INADDR_ANY);
+ else
+ errx(1, "%s: bad value", addr_str);
+}
+
+static void
+in_getaddr(const char *s, int which)
+{
+ struct in_px *px = sintab_nl[which];
+
+ if (which == MASK) {
+ struct in_px *px_addr = sintab_nl[ADDR];
+ struct in_addr mask = {};
+
+ in_getip(s, &mask);
+ px_addr->plen = __bitcount32(mask.s_addr);
+ px_addr->maskset = true;
+ return;
+ }
+
+ if (which == ADDR) {
+ char *p = NULL;
+
+ if((p = strrchr(s, '/')) != NULL) {
+ const char *errstr;
+ /* address is `name/masklen' */
+ int masklen;
+ *p = '\0';
+ if (!isdigit(*(p + 1)))
+ errstr = "invalid";
+ else
+ masklen = (int)strtonum(p + 1, 0, 32, &errstr);
+ if (errstr != NULL) {
+ *p = '/';
+ errx(1, "%s: bad value (width %s)", s, errstr);
+ }
+ px->plen = masklen;
+ px->maskset = true;
+ }
+ }
+
+ in_getip(s, &px->addr);
+ px->addrset = true;
+}
+
+
+static int
+in_exec_nl(struct io_handler *h, int action, void *data)
+{
+ struct in_pdata *pdata = (struct in_pdata *)data;
+ struct snl_writer nw = {};
+
+ snl_init_writer(h->ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, action);
+ struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+
+ ifahdr->ifa_family = AF_INET;
+ ifahdr->ifa_prefixlen = pdata->addr.plen;
+ ifahdr->ifa_index = if_nametoindex_nl(h->ss, name);
+
+ snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &pdata->addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->dst_addr.addrset)
+ snl_add_msg_attr_ip4(&nw, IFA_ADDRESS, &pdata->dst_addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->brd_addr.addrset)
+ snl_add_msg_attr_ip4(&nw, IFA_BROADCAST, &pdata->brd_addr.addr);
+
+ int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD);
+ snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags);
+ if (pdata->vhid != 0)
+ snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
+ snl_end_attr_nested(&nw, off);
+
+ if (!snl_finalize_msg(&nw) || !snl_send_message(h->ss, hdr))
+ return (0);
+
+ struct snl_errmsg_data e = {};
+ snl_read_reply_code(h->ss, hdr->nlmsg_seq, &e);
+ if (e.error_str != NULL)
+ warnx("%s(): %s", __func__, e.error_str);
+
+ return (e.error);
+}
+
+static void
+in_setdefaultmask_nl(void)
+{
+ struct in_px *px = sintab_nl[ADDR];
+
+ in_addr_t i = ntohl(px->addr.s_addr);
+
+ /*
+ * If netmask isn't supplied, use historical default.
+ * This is deprecated for interfaces other than loopback
+ * or point-to-point; warn in other cases. In the future
+ * we should return an error rather than warning.
+ */
+ if (IN_CLASSA(i))
+ px->plen = IN_CLASSA_NSHIFT;
+ else if (IN_CLASSB(i))
+ px->plen = IN_CLASSB_NSHIFT;
+ else
+ px->plen = IN_CLASSC_NSHIFT;
+ px->maskset = true;
+}
+#endif
+
+static void
+warn_nomask(ifflags)
+{
+ if ((ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
+ warnx("WARNING: setting interface address without mask "
+ "is deprecated,\ndefault mask may not be correct.");
+ }
+}
+
static void
in_postproc(int s, const struct afswtch *afp, int newaddr, int ifflags)
{
- if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 &&
- newaddr && (ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
- warnx("WARNING: setting interface address without mask "
- "is deprecated,\ndefault mask may not be correct.");
+#ifdef WITHOUT_NETLINK
+ if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 && newaddr) {
+ warn_nomask(ifflags);
+ }
+#else
+ if (sintab_nl[ADDR]->addrset && !sintab_nl[ADDR]->maskset && newaddr) {
+ warn_nomask(ifflags);
+ in_setdefaultmask_nl();
}
+#endif
}
static void
@@ -288,10 +450,13 @@
static void
in_set_vhid(int vhid)
{
+#ifdef WITHOUT_NETLINK
in_addreq.ifra_vhid = vhid;
+#else
+ in_add.vhid = (uint32_t)vhid;
+#endif
}
-
static struct afswtch af_inet = {
.af_name = "inet",
.af_af = AF_INET,
@@ -305,10 +470,19 @@
.af_status_tunnel = in_status_tunnel,
.af_settunnel = in_set_tunnel,
.af_setvhid = in_set_vhid,
+#ifdef WITHOUT_NETLINK
.af_difaddr = SIOCDIFADDR,
.af_aifaddr = SIOCAIFADDR,
.af_ridreq = &in_ridreq,
.af_addreq = &in_addreq,
+ .af_exec = af_exec_ioctl,
+#else
+ .af_difaddr = NL_RTM_DELADDR,
+ .af_aifaddr = NL_RTM_NEWADDR,
+ .af_ridreq = &in_del,
+ .af_addreq = &in_add,
+ .af_exec = in_exec_nl,
+#endif
};
static __constructor void
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -59,10 +59,30 @@
#include "ifconfig.h"
#include "ifconfig_netlink.h"
+#ifndef WITHOUT_NETLINK
+struct in6_px {
+ struct in6_addr addr;
+ int plen;
+ bool set;
+};
+struct in6_pdata {
+ struct in6_px addr;
+ struct in6_px dst_addr;
+ struct in6_addrlifetime lifetime;
+ uint32_t flags;
+ uint32_t vhid;
+};
+
+static struct in6_pdata in6_del;
+static struct in6_pdata in6_add = {
+ .lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME },
+};
+#else
static struct in6_ifreq in6_ridreq;
static struct in6_aliasreq in6_addreq =
{ .ifra_flags = 0,
.ifra_lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } };
+#endif
static int ip6lifetime;
static int prefix(void *, int);
@@ -80,8 +100,16 @@
setifprefixlen(const char *addr, int dummy __unused, int s,
const struct afswtch *afp)
{
+#ifdef WITHOUT_NETLINK
if (afp->af_getprefix != NULL)
afp->af_getprefix(addr, MASK);
+#else
+ int plen = strtol(addr, NULL, 10);
+
+ if ((plen < 0) || (plen > 128))
+ errx(1, "%s: bad value", addr);
+ in6_add.addr.plen = plen;
+#endif
explicit_prefix = 1;
}
@@ -92,10 +120,17 @@
if (afp->af_af != AF_INET6)
err(1, "address flags can be set only for inet6 addresses");
+#ifdef WITHOUT_NETLINK
if (flag < 0)
in6_addreq.ifra_flags &= ~(-flag);
else
in6_addreq.ifra_flags |= flag;
+#else
+ if (flag < 0)
+ in6_add.flags &= ~(-flag);
+ else
+ in6_add.flags |= flag;
+#endif
}
static void
@@ -105,6 +140,11 @@
struct timespec now;
time_t newval;
char *ep;
+#ifdef WITHOUT_NETLINK
+ struct in6_addrlifetime *lifetime = &in6_addreq.ifra_lifetime;
+#else
+ struct in6_addrlifetime *lifetime = &in6_add.lifetime;
+#endif
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
newval = (time_t)strtoul(val, &ep, 0);
@@ -113,11 +153,11 @@
if (afp->af_af != AF_INET6)
errx(1, "%s not allowed for the AF", cmd);
if (strcmp(cmd, "vltime") == 0) {
- in6_addreq.ifra_lifetime.ia6t_expire = now.tv_sec + newval;
- in6_addreq.ifra_lifetime.ia6t_vltime = newval;
+ lifetime->ia6t_expire = now.tv_sec + newval;
+ lifetime->ia6t_vltime = newval;
} else if (strcmp(cmd, "pltime") == 0) {
- in6_addreq.ifra_lifetime.ia6t_preferred = now.tv_sec + newval;
- in6_addreq.ifra_lifetime.ia6t_pltime = newval;
+ lifetime->ia6t_preferred = now.tv_sec + newval;
+ lifetime->ia6t_pltime = newval;
}
}
@@ -146,7 +186,11 @@
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
+#ifdef WITHOUT_NETLINK
in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
+#else
+ in6 = &in6_add.addr.addr;
+#endif
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
errx(EXIT_FAILURE, "interface index is already filled");
if (getifaddrs(&ifap) != 0)
@@ -374,8 +418,92 @@
putchar('\n');
}
+
+static struct in6_px *sin6tab_nl[] = {
+ &in6_del.addr, /* RIDADDR */
+ &in6_add.addr, /* ADDR */
+ NULL, /* MASK */
+ &in6_add.dst_addr, /* DSTADDR*/
+};
+
+static void
+in6_getaddr(const char *addr_str, int which)
+{
+ struct in6_px *px = sin6tab_nl[which];
+
+ newaddr &= 1;
+
+ px->set = true;
+ px->plen = 128;
+ if (which == ADDR) {
+ char *p = NULL;
+ if((p = strrchr(addr_str, '/')) != NULL) {
+ *p = '\0';
+ int plen = strtol(p + 1, NULL, 10);
+ if (plen < 0 || plen > 128)
+ errx(1, "%s: bad value", p + 1);
+ px->plen = plen;
+ explicit_prefix = 1;
+ }
+ }
+
+ struct addrinfo hints = { .ai_family = AF_INET6 };
+ struct addrinfo *res;
+
+ int error = getaddrinfo(addr_str, NULL, &hints, &res);
+ if (error != 0) {
+ if (inet_pton(AF_INET6, addr_str, &px->addr) != 1)
+ errx(1, "%s: bad value", addr_str);
+ } else {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
+ px->addr = sin6->sin6_addr;
+ freeaddrinfo(res);
+ }
+}
+
+static int
+in6_exec_nl(struct io_handler *h, int action, void *data)
+{
+ struct in6_pdata *pdata = (struct in6_pdata *)data;
+ struct snl_writer nw = {};
+
+ snl_init_writer(h->ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, action);
+ struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+
+ ifahdr->ifa_family = AF_INET6;
+ ifahdr->ifa_prefixlen = pdata->addr.plen;
+ ifahdr->ifa_index = if_nametoindex_nl(h->ss, name);
+
+ snl_add_msg_attr_ip6(&nw, IFA_LOCAL, &pdata->addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->dst_addr.set)
+ snl_add_msg_attr_ip6(&nw, IFA_ADDRESS, &pdata->dst_addr.addr);
+
+ struct ifa_cacheinfo ci = {
+ .ifa_prefered = pdata->lifetime.ia6t_pltime,
+ .ifa_valid = pdata->lifetime.ia6t_vltime,
+ };
+ snl_add_msg_attr(&nw, IFA_CACHEINFO, sizeof(ci), &ci);
+
+ int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD);
+ snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags);
+ if (pdata->vhid != 0)
+ snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
+ snl_end_attr_nested(&nw, off);
+
+ if (!snl_finalize_msg(&nw) || !snl_send_message(h->ss, hdr))
+ return (0);
+
+ struct snl_errmsg_data e = {};
+ snl_read_reply_code(h->ss, hdr->nlmsg_seq, &e);
+
+ return (e.error);
+}
#endif
+#ifdef WITHOUT_NETLINK
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
static struct sockaddr_in6 *sin6tab[] = {
SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
@@ -463,6 +591,7 @@
return(0);
return (plen);
}
+#endif
static char *
sec2str(time_t total)
@@ -558,7 +687,11 @@
static void
in6_set_vhid(int vhid)
{
+#ifdef WITHOUT_NETLINK
in6_addreq.ifra_vhid = vhid;
+#else
+ in6_add.vhid = (uint32_t)vhid;
+#endif
}
static struct cmd inet6_cmds[] = {
@@ -606,16 +739,27 @@
.af_status_nl = in6_status_nl,
#endif
.af_getaddr = in6_getaddr,
+#ifdef WITHOUT_NETLINK
.af_getprefix = in6_getprefix,
+#endif
.af_other_status = nd6_status,
.af_postproc = in6_postproc,
.af_status_tunnel = in6_status_tunnel,
.af_settunnel = in6_set_tunnel,
.af_setvhid = in6_set_vhid,
+#ifdef WITHOUT_NETLINK
.af_difaddr = SIOCDIFADDR_IN6,
.af_aifaddr = SIOCAIFADDR_IN6,
.af_ridreq = &in6_addreq,
.af_addreq = &in6_addreq,
+ .af_exec = af_exec_ioctl,
+#else
+ .af_difaddr = NL_RTM_DELADDR,
+ .af_aifaddr = NL_RTM_NEWADDR,
+ .af_ridreq = &in6_add,
+ .af_addreq = &in6_add,
+ .af_exec = in6_exec_nl,
+#endif
};
static void
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -229,6 +229,7 @@
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static struct afswtch af_ether = {
.af_name = "ether",
@@ -241,6 +242,7 @@
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static struct afswtch af_lladdr = {
.af_name = "lladdr",
@@ -253,6 +255,7 @@
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static __constructor void
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -144,10 +144,15 @@
struct addrinfo;
enum {
- RIDADDR,
- ADDR,
- MASK,
- DSTADDR,
+ RIDADDR = 0,
+ ADDR = 1,
+ MASK = 2,
+ DSTADDR = 3,
+#ifdef WITHOUT_NETLINK
+ BRDADDR = 3,
+#else
+ BRDADDR = 4,
+#endif
};
struct snl_state;
@@ -164,6 +169,7 @@
typedef void af_setvhid_f(int vhid);
typedef void af_status_nl_f(struct ifconfig_args *args, struct io_handler *h,
if_link_t *link, if_addr_t *ifa);
+typedef int af_exec_f(struct io_handler *h, int action, void *data);
struct afswtch {
const char *af_name; /* as given on cmd line, e.g. "inet" */
@@ -190,6 +196,7 @@
void (*af_postproc)(int s, const struct afswtch *,
int newaddr, int ifflags);
af_setvhid_f *af_setvhid; /* Set CARP vhid for an address */
+ af_exec_f *af_exec; /* Handler to interact with kernel */
u_long af_difaddr; /* set dst if address ioctl */
u_long af_aifaddr; /* set if address ioctl */
void *af_ridreq; /* */
@@ -202,6 +209,7 @@
struct addrinfo *dstres);
};
void af_register(struct afswtch *);
+int af_exec_ioctl(struct io_handler *h, int action, void *data);
struct ifconfig_args {
bool all; /* Match everything */
@@ -259,7 +267,8 @@
struct sockaddr_dl;
bool match_ether(const struct sockaddr_dl *sdl);
bool match_if_flags(struct ifconfig_args *args, int if_flags);
-int ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp);
+int ifconfig(struct ifconfig_args *args, struct io_handler *h,
+ int iscreate, const struct afswtch *uafp);
bool group_member(const char *ifname, const char *match, const char *nomatch);
void print_ifcap(struct ifconfig_args *args, int s);
void tunnel_status(int s);
@@ -270,6 +279,9 @@
/* Netlink-related functions */
void list_interfaces_nl(struct ifconfig_args *args);
+int ifconfig_wrapper_nl(struct ifconfig_args *args, int iscreate,
+ const struct afswtch *uafp);
+uint32_t if_nametoindex_nl(struct snl_state *ss, const char *ifname);
/*
* XXX expose this so modules that neeed to know of any pending
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -112,6 +112,7 @@
static void status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
struct ifaddrs *ifa);
static _Noreturn void usage(void);
+static void Perrorc(const char *cmd, int error);
static int getifflags(const char *ifname, int us, bool err_ok);
@@ -541,6 +542,30 @@
verbose = args->verbose;
}
+static int
+ifconfig_wrapper(struct ifconfig_args *args, int iscreate,
+ const struct afswtch *uafp)
+{
+#ifdef WITHOUT_NETLINK
+ struct io_handler h = {};
+ return (ifconfig(args, &h, iscreate, uafp));
+#else
+ return (ifconfig_wrapper_nl(args, iscreate, uafp));
+#endif
+}
+
+static bool
+isargcreate(const char *arg)
+{
+ if (arg == NULL)
+ return (false);
+
+ if (strcmp(arg, "create") == 0 || strcmp(arg, "plumb") == 0)
+ return (true);
+
+ return (false);
+}
+
int
main(int ac, char *av[])
{
@@ -580,13 +605,12 @@
* right here as we would otherwise fail when trying
* to find the interface.
*/
- if (arg != NULL && (strcmp(arg, "create") == 0 ||
- strcmp(arg, "plumb") == 0)) {
+ if (isargcreate(arg)) {
iflen = strlcpy(name, args.ifname, sizeof(name));
if (iflen >= sizeof(name))
errx(1, "%s: cloning name too long",
args.ifname);
- ifconfig(args.argc, args.argv, 1, NULL);
+ ifconfig_wrapper(&args, 1, NULL);
exit(exit_code);
}
#ifdef JAIL
@@ -600,7 +624,7 @@
if (iflen >= sizeof(name))
errx(1, "%s: interface name too long",
args.ifname);
- ifconfig(args.argc, args.argv, 0, NULL);
+ ifconfig_wrapper(&args, 0, NULL);
exit(exit_code);
}
#endif
@@ -610,8 +634,7 @@
* Do not allow use `create` command as hostname if
* address family is not specified.
*/
- if (arg != NULL && (strcmp(arg, "create") == 0 ||
- strcmp(arg, "plumb") == 0)) {
+ if (isargcreate(arg)) {
if (args.argc == 1)
errx(1, "interface %s already exists",
args.ifname);
@@ -641,7 +664,7 @@
if (!(((flags & IFF_CANTCONFIG) != 0) ||
(args.downonly && (flags & IFF_UP) != 0) ||
(args.uponly && (flags & IFF_UP) == 0)))
- ifconfig(args.argc, args.argv, 0, args.afp);
+ ifconfig_wrapper(&args, 0, args.afp);
}
goto done;
}
@@ -769,7 +792,7 @@
ifindex++;
if (args->argc > 0)
- ifconfig(args->argc, args->argv, 0, args->afp);
+ ifconfig_wrapper(args, 0, args->afp);
else
status(args, sdl, ifa);
}
@@ -968,31 +991,42 @@
static const struct cmd setifdstaddr_cmd =
DEF_CMD("ifdstaddr", 0, setifdstaddr);
+int
+af_exec_ioctl(struct io_handler *h, int action, void *data)
+{
+ struct ifreq *req = (struct ifreq *)data;
+
+ strlcpy(req->ifr_name, name, sizeof(req->ifr_name));
+ if (ioctl(h->s, action, req) == 0)
+ return (0);
+ return (errno);
+}
+
static void
-delifaddr(int s, const struct afswtch *afp)
+delifaddr(struct io_handler *h, const struct afswtch *afp)
{
- if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
+ int error;
+
+ if (afp->af_exec == NULL) {
warnx("interface %s cannot change %s addresses!",
name, afp->af_name);
clearaddr = 0;
return;
}
- strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name,
- sizeof ifr.ifr_name);
- int ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
- if (ret < 0) {
- if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
+ afp->af_exec(h, afp->af_difaddr, afp->af_ridreq);
+ if (error != 0) {
+ if (error == EADDRNOTAVAIL && (doalias >= 0)) {
/* means no previous address for interface */
} else
- Perror("ioctl (SIOCDIFADDR)");
+ Perrorc("ioctl (SIOCDIFADDR)", error);
}
}
static void
-addifaddr(int s, const struct afswtch *afp)
+addifaddr(struct io_handler *h, const struct afswtch *afp)
{
- if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
+ if (afp->af_exec == NULL) {
warnx("interface %s cannot change %s addresses!",
name, afp->af_name);
newaddr = 0;
@@ -1000,21 +1034,24 @@
}
if (setaddr || setmask) {
- strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name,
- sizeof ifr.ifr_name);
- if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
- Perror("ioctl (SIOCAIFADDR)");
+ int error = afp->af_exec(h, afp->af_aifaddr, afp->af_addreq);
+ if (error != 0)
+ Perrorc("ioctl (SIOCAIFADDR)", error);
}
}
int
-ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
+ifconfig(struct ifconfig_args *args, struct io_handler *h, int iscreate,
+ const struct afswtch *uafp)
{
const struct afswtch *afp, *nafp;
const struct cmd *p;
struct callback *cb;
int s;
+ int argc = args->argc;
+ char *const *argv = args->argv;
+
strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
afp = NULL;
if (uafp != NULL)
@@ -1127,10 +1164,11 @@
/*
* Do deferred operations.
*/
+ h->s = s;
if (clearaddr)
- delifaddr(s, afp);
+ delifaddr(h, afp);
if (newaddr)
- addifaddr(s, afp);
+ addifaddr(h, afp);
close(s);
return(0);
@@ -1237,7 +1275,7 @@
const struct afswtch *afp)
{
if (afp->af_getaddr != NULL)
- afp->af_getaddr(addr, DSTADDR);
+ afp->af_getaddr(addr, BRDADDR);
}
static void
@@ -1713,8 +1751,8 @@
af_all_tunnel_status(s);
}
-void
-Perror(const char *cmd)
+static void
+Perrorc(const char *cmd, int error)
{
switch (errno) {
@@ -1727,10 +1765,16 @@
break;
default:
- err(1, "%s", cmd);
+ errc(1, error, "%s", cmd);
}
}
+void
+Perror(const char *cmd)
+{
+ Perrorc(cmd, errno);
+}
+
/*
* Print a value a la the %b format of the kernel's printf
*/
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
--- a/sbin/ifconfig/ifconfig_netlink.c
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -122,6 +122,22 @@
err(1, "unable to open netlink socket");
}
+int
+ifconfig_wrapper_nl(struct ifconfig_args *args, int iscreate,
+ const struct afswtch *uafp)
+{
+ struct snl_state ss = {};
+ struct io_handler h = { .ss = &ss };
+
+ nl_init_socket(&ss);
+
+ int error = ifconfig(args, &h, iscreate, uafp);
+
+ snl_free(&ss);
+
+ return (error);
+}
+
struct ifa {
struct ifa *next;
uint32_t count;
@@ -186,6 +202,29 @@
return (ifmap);
}
+uint32_t
+if_nametoindex_nl(struct snl_state *ss, const char *ifname)
+{
+ struct snl_writer nw = {};
+ struct snl_parsed_link_simple link = {};
+
+ snl_init_writer(ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK);
+ snl_reserve_msg_object(&nw, struct ifinfomsg);
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+ return (0);
+
+ hdr = snl_read_reply(ss, hdr->nlmsg_seq);
+ if (hdr->nlmsg_type != NL_RTM_NEWLINK)
+ return (0);
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, &link))
+ return (0);
+
+ return (link.ifi_index);
+}
+
static void
prepare_ifaddrs(struct snl_state *ss, struct ifmap *ifmap)
{
@@ -415,8 +454,11 @@
fputs(iface->link.ifla_ifname, stdout);
} else if (args->argc == 0)
status_nl(args, &h, iface);
- else
- ifconfig(args->argc, args->argv, 0, args->afp);
+ else {
+ struct io_handler hh = { .s = -1, .ss = &ss };
+
+ ifconfig(args, &hh, 0, args->afp);
+ }
}
if (args->namesonly)
printf("\n");
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Sep 12, 8:26 AM (7 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38779720
Default Alt Text
D40182.id122214.diff (22 KB)
Attached To
Mode
D40182: ifconfig: switch IPv4/IPv6 address manipulations to Netlink
Attached
Detach File
Event Timeline
Log In to Comment