changeset 5155:a0c82a0a4375 draft

if: ensure interface flags persist when setting a flag Otherwise we stupidly drop IFF_MULTICAST on Linux.
author Roy Marples <roy@marples.name>
date Mon, 20 Apr 2020 14:11:00 +0100
parents 8248b3a04908
children abb54c79cc7f
files src/if.c
diffstat 1 files changed, 6 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/if.c	Sun Apr 19 07:52:47 2020 +0100
+++ b/src/if.c	Mon Apr 20 14:11:00 2020 +0100
@@ -161,19 +161,17 @@
 if_setflag(struct interface *ifp, short setflag, short unsetflag)
 {
 	struct ifreq ifr = { .ifr_flags = 0 };
-	short f;
+	short oflags;
 
-	if (if_getflags(ifp) == -1)
+	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
 		return -1;
 
-	f = (short)ifp->flags;
-	if ((f & setflag) == setflag && (f & unsetflag) == 0)
-		return 0;
-
-	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+	oflags = ifr.ifr_flags;
 	ifr.ifr_flags |= setflag;
 	ifr.ifr_flags &= (short)~unsetflag;
-	if (if_ioctl(ifp->ctx, SIOCSIFFLAGS, &ifr, sizeof(ifr)) == -1)
+	if (ifr.ifr_flags != oflags &&
+	    if_ioctl(ifp->ctx, SIOCSIFFLAGS, &ifr, sizeof(ifr)) == -1)
 		return -1;
 
 	ifp->flags = (unsigned int)ifr.ifr_flags;