aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-05-25 14:50:57 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-05-25 15:03:35 +0000
commit6d204407ec6eb3403306578a2550a92b8560d92b (patch)
tree022e78d2f096277d3d46a55d3dccbb576e2b797f
parent6c08fd3dc804c9c3064add3b9a6ff678a541d210 (diff)
downloadsrc-6d204407ec6eb3403306578a2550a92b8560d92b.tar.gz
src-6d204407ec6eb3403306578a2550a92b8560d92b.zip
ifconfig: fix ifconfig IFX inet[6] ADDR -alias
Internally, inet and inet6 family handlers store state for address addition and deletion separately, as, for example, "ifconfig lo0 inet 127.0.0.2/32" triggers a) deletion of the first interface address and b) addition of a new one. The current logic behind handling "-alias" being the last argument is to copy the address from "addition" state to the "deletion" state. It is done by the generic ifconfig code, which explicitly typecasts opaque handler state pointers to "struct ifreq", which doesn't work in the Netlink case. Fix this by introducing family-specific "af_copyaddr" handler, which removes the peeking & typecasting logic from the generic code. Reported by: otis Tested by: otis
-rw-r--r--sbin/ifconfig/af_inet.c14
-rw-r--r--sbin/ifconfig/af_inet6.c14
-rw-r--r--sbin/ifconfig/ifconfig.c11
-rw-r--r--sbin/ifconfig/ifconfig.h2
4 files changed, 34 insertions, 7 deletions
diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index 73decb229d0f..76787e62d908 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -202,6 +202,12 @@ static struct sockaddr_in *sintab[] = {
};
static void
+in_copyaddr(if_ctx *ctx, int to, int from)
+{
+ memcpy(sintab[to], sintab[from], sizeof(struct sockaddr_in));
+}
+
+static void
in_getaddr(const char *s, int which)
{
struct sockaddr_in *sin = sintab[which];
@@ -257,6 +263,13 @@ static struct in_px *sintab_nl[] = {
};
static void
+in_copyaddr(if_ctx *ctx, int to, int from)
+{
+ sintab_nl[to]->addr = sintab_nl[from]->addr;
+ sintab_nl[to]->addrset = sintab_nl[from]->addrset;
+}
+
+static void
in_getip(const char *addr_str, struct in_addr *ip)
{
struct hostent *hp;
@@ -537,6 +550,7 @@ static struct afswtch af_inet = {
.af_status = in_status_nl,
#endif
.af_getaddr = in_getaddr,
+ .af_copyaddr = in_copyaddr,
.af_postproc = in_postproc,
.af_status_tunnel = in_status_tunnel,
.af_settunnel = in_set_tunnel,
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index d5418b827789..f735afdc8797 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -422,6 +422,13 @@ static struct in6_px *sin6tab_nl[] = {
};
static void
+in6_copyaddr(if_ctx *ctx, int to, int from)
+{
+ sin6tab_nl[to]->addr = sin6tab_nl[from]->addr;
+ sin6tab_nl[to]->set = sin6tab_nl[from]->set;
+}
+
+static void
in6_getaddr(const char *addr_str, int which)
{
struct in6_px *px = sin6tab_nl[which];
@@ -505,6 +512,12 @@ static struct sockaddr_in6 *sin6tab[] = {
};
static void
+in6_copyaddr(if_ctx *ctx, int to, int from)
+{
+ memcpy(sin6tab[to], sin6tab[from], sizeof(struct sockaddr_in6));
+}
+
+static void
in6_getprefix(const char *plen, int which)
{
struct sockaddr_in6 *sin = sin6tab[which];
@@ -733,6 +746,7 @@ static struct afswtch af_inet6 = {
.af_status = in6_status_nl,
#endif
.af_getaddr = in6_getaddr,
+ .af_copyaddr = in6_copyaddr,
#ifdef WITHOUT_NETLINK
.af_getprefix = in6_getprefix,
#endif
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 8ae7920e6ea9..84df15a58ce1 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1327,19 +1327,16 @@ notealias(if_ctx *ctx, const char *addr, int param)
{
const struct afswtch *afp = ctx->afp;
-#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
- if (setaddr && doalias == 0 && param < 0)
- if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
- bcopy((caddr_t)rqtosa(af_addreq),
- (caddr_t)rqtosa(af_ridreq),
- rqtosa(af_addreq)->sa_len);
+ if (setaddr && doalias == 0 && param < 0) {
+ if (afp->af_copyaddr != NULL)
+ afp->af_copyaddr(ctx, RIDADDR, ADDR);
+ }
doalias = param;
if (param < 0) {
clearaddr = 1;
newaddr = 0;
} else
clearaddr = 0;
-#undef rqtosa
}
static void
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index 62dc0bdfe1f4..054e7a12f488 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -174,6 +174,7 @@ typedef void af_status_f(if_ctx *ctx, const struct ifaddrs *);
typedef void af_other_status_f(if_ctx *ctx);
typedef void af_postproc_f(if_ctx *ctx, int newaddr, int ifflags);
typedef int af_exec_f(if_ctx *ctx, unsigned long action, void *data);
+typedef void af_copyaddr_f(if_ctx *ctx, int to, int from);
struct afswtch {
const char *af_name; /* as given on cmd line, e.g. "inet" */
@@ -194,6 +195,7 @@ struct afswtch {
#endif
af_other_status_f *af_other_status;
void (*af_getaddr)(const char *, int);
+ af_copyaddr_f *af_copyaddr; /* Copy address between <RID|*>ADDR */
/* parse prefix method (IPv6) */
void (*af_getprefix)(const char *, int);
af_postproc_f *af_postproc;