#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/ethernet.h>
#include <err.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ifconfig.h"
static struct ifreq link_ridreq;
static void
link_status(int s __unused, const struct ifaddrs *ifa)
{
struct sockaddr_dl *sdl =
__DECONST(struct sockaddr_dl *, ifa->ifa_addr);
char addr[18], *p;
int n;
if (sdl == NULL || sdl->sdl_alen == 0)
return;
if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADDR_LEN) {
ether_ntoa_r((const struct ether_addr *)LLADDR(sdl), addr);
if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
p = addr;
while ((p = strchr(p, ':')) != NULL)
*p = '-';
}
printf("\tether %s\n", addr);
} else {
n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
printf("\tlladdr %s\n", link_ntoa(sdl) + n);
}
}
static void
link_getaddr(const char *addr, int which)
{
struct sockaddr_dl sdl;
struct sockaddr *sa = &link_ridreq.ifr_addr;
char *temp;
if (which != ADDR)
errx(1, "can't set link-level netmask or broadcast");
if ((temp = malloc(strlen(addr) + 2)) == NULL)
errx(1, "malloc failed");
temp[0] = ':';
strcpy(temp + 1, addr);
sdl.sdl_len = sizeof(sdl);
link_addr(temp, &sdl);
free(temp);
if (sdl.sdl_alen > sizeof(sa->sa_data))
errx(1, "malformed link-level address");
sa->sa_family = AF_LINK;
sa->sa_len = sdl.sdl_alen;
memcpy(sa->sa_data, LLADDR(&sdl), sdl.sdl_alen);
}
static struct afswtch af_link = {
.af_name = "link",
.af_af = AF_LINK,
.af_status = link_status,
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
};
static struct afswtch af_ether = {
.af_name = "ether",
.af_af = AF_LINK,
.af_status = link_status,
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
};
static struct afswtch af_lladdr = {
.af_name = "lladdr",
.af_af = AF_LINK,
.af_status = link_status,
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
};
__constructor(111)
static void
link_ctor(void)
{
af_register(&af_link);
af_register(&af_ether);
af_register(&af_lladdr);
}