git: 6d204407ec6e - main - ifconfig: fix ifconfig IFX inet[6] ADDR -alias
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 25 May 2023 15:03:57 UTC
The branch main has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=6d204407ec6eb3403306578a2550a92b8560d92b commit 6d204407ec6eb3403306578a2550a92b8560d92b Author: Alexander V. Chernikov <melifaro@FreeBSD.org> AuthorDate: 2023-05-25 14:50:57 +0000 Commit: Alexander V. Chernikov <melifaro@FreeBSD.org> CommitDate: 2023-05-25 15:03:35 +0000 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 --- sbin/ifconfig/af_inet.c | 14 ++++++++++++++ sbin/ifconfig/af_inet6.c | 14 ++++++++++++++ sbin/ifconfig/ifconfig.c | 11 ++++------- sbin/ifconfig/ifconfig.h | 2 ++ 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 @@ -201,6 +201,12 @@ static struct sockaddr_in *sintab[] = { SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr) }; +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) { @@ -256,6 +262,13 @@ static struct in_px *sintab_nl[] = { &in_add.brd_addr, /* BRDADDR*/ }; +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) { @@ -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 @@ -421,6 +421,13 @@ static struct in6_px *sin6tab_nl[] = { &in6_add.dst_addr, /* DSTADDR*/ }; +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) { @@ -504,6 +511,12 @@ static struct sockaddr_in6 *sin6tab[] = { &in6_addreq.ifra_prefixmask, &in6_addreq.ifra_dstaddr }; +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) { @@ -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;