Export the functionality of SIOCSIFLLADDR with if_setlladdr()

and add some more rigorous sanity checking in the process.

Reviewed by:	freebsd-net
This commit is contained in:
Archie Cobbs 2000-08-15 00:48:38 +00:00
parent a05f06d79f
commit 66ce51cec7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64651
2 changed files with 51 additions and 25 deletions

View File

@ -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 @@ ifioctl(so, cmd, data, p)
{
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 @@ ifioctl(so, cmd, data, p)
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)
@ -1339,6 +1318,52 @@ if_delmulti(ifp, sa)
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 *
ifmaof_ifpforaddr(sa, ifp)
struct sockaddr *sa;

View File

@ -340,6 +340,7 @@ int if_delmulti __P((struct ifnet *, struct sockaddr *));
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() */