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:
parent
a05f06d79f
commit
66ce51cec7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64651
75
sys/net/if.c
75
sys/net/if.c
@ -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;
|
||||
|
@ -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() */
|
||||
|
Loading…
Reference in New Issue
Block a user