Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Aug 2000 17:21:57 -0700 (PDT)
From:      Archie Cobbs <archie@whistle.com>
To:        freebsd-net@freebsd.org
Cc:        wpaul@freebsd.org, rwatson@freebsd.org
Subject:   SIOCSIFLLADDR ioctl() patch
Message-ID:  <200008120021.RAA51816@bubba.whistle.com>

next in thread | raw e-mail | index | archive | help
Anyone care to review this patch? I've tried to block a couple of
things that would crash the kernel, e.g., calling SIOCSIFLLADDR
on an interface type that doesn't use struct arpcom in ifp->if_softc.

The ulterior motive is to export if_setlladdr() so that ng_ether(4)
can hook into it. 

Thanks,
-Archie

P.S. Is IFT_8021_VLAN ever going to get promoted from if_vlan_var.h
     to if_types.h?

___________________________________________________________________________
Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com

Index: if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.91
diff -u -r1.91 if.c
--- if.c	2000/07/16 01:46:42	1.91
+++ if.c	2000/08/12 00:20:14
@@ -54,6 +54,7 @@
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <net/if_dl.h>
+#include <net/if_types.h>
 #include <net/radix.h>
 #include <net/route.h>
 
@@ -762,8 +763,6 @@
 {
 	register struct ifnet *ifp;
 	register struct ifreq *ifr;
-	register struct ifaddr *ifa;
-	struct sockaddr_dl *sdl;
 	struct ifstat *ifs;
 	int error;
 	short oif_flags;
@@ -917,29 +916,9 @@
 		error = suser(p);
 		if (error)
 			return (error);
-		ifa = ifnet_addrs[ifp->if_index - 1];
-		if (ifa == NULL)
-			return(EINVAL);
-		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
-		if (sdl == NULL)
-			return(EINVAL);
-		bcopy(ifr->ifr_addr.sa_data,
-		    ((struct arpcom *)ifp->if_softc)->ac_enaddr,
-		    ifr->ifr_addr.sa_len);
-		bcopy(ifr->ifr_addr.sa_data, LLADDR(sdl),
-		    ifr->ifr_addr.sa_len);
-		/*
-		 * If the interface is already up, we need
-		 * to re-init it in order to reprogram its
-		 * address filter.
-		 */
-		if (ifp->if_flags & IFF_UP) {
-			ifp->if_flags &= ~IFF_UP;
-			(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
-			ifp->if_flags |= IFF_UP;
-			(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
-		}
-		return(0);
+		return if_setlladdr(ifp,
+		    ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
+
 	default:
 		oif_flags = ifp->if_flags;
 		if (so->so_proto == 0)
@@ -1337,6 +1316,52 @@
 	free(ifma, M_IFMADDR);
 
 	return 0;
+}
+
+/*
+ * Set the link layer address on an interface.
+ *
+ * At this time we only support certain types of interfaces,
+ * and we don't allow the length of the address to change.
+ */
+int
+if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
+{
+	struct sockaddr_dl *sdl;
+	struct ifaddr *ifa;
+
+	ifa = ifnet_addrs[ifp->if_index - 1];
+	if (ifa == NULL)
+		return (EINVAL);
+	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+	if (sdl == NULL)
+		return (EINVAL);
+	if (len != sdl->sdl_alen)	/* don't allow length to change */
+		return (EINVAL);
+	switch (ifp->if_type) {
+	case IFT_ETHER:			/* these types use struct arpcom */
+	case IFT_FDDI:
+	case IFT_XETHER:
+	case IFT_ISO88025:
+	case IFT_PROPVIRTUAL:		/* XXX waiting for IFT_8021_VLAN */
+		bcopy(lladdr, ((struct arpcom *)ifp->if_softc)->ac_enaddr, len);
+		bcopy(lladdr, LLADDR(sdl), len);
+		break;
+	default:
+		return (ENODEV);
+	}
+	/*
+	 * If the interface is already up, we need
+	 * to re-init it in order to reprogram its
+	 * address filter.
+	 */
+	if ((ifp->if_flags & IFF_UP) != 0) {
+		ifp->if_flags &= ~IFF_UP;
+		(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
+		ifp->if_flags |= IFF_UP;
+		(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
+	}
+	return (0);
 }
 
 struct ifmultiaddr *
Index: if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.25
diff -u -r1.25 if_var.h
--- if_var.h	2000/07/13 22:54:30	1.25
+++ if_var.h	2000/08/12 00:20:14
@@ -340,6 +340,7 @@
 void	if_detach __P((struct ifnet *));
 void	if_down __P((struct ifnet *));
 void	if_route __P((struct ifnet *, int flag, int fam));
+int	if_setlladdr __P((struct ifnet *, const u_char *, int));
 void	if_unroute __P((struct ifnet *, int flag, int fam));
 void	if_up __P((struct ifnet *));
 /*void	ifinit __P((void));*/ /* declared in systm.h for main() */


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008120021.RAA51816>