#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
#include <uuid/uuid.h>
#include <sys/sockio.h>
#include <libdlpi.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "etheraddr.h"
static boolean_t get_etheraddr(const char *linkname, void *arg);
int
arp_get(uuid_node_t *node)
{
struct utsname name;
struct arpreq ar;
struct hostent *hp;
struct sockaddr_in *sin;
int s;
if (uname(&name) == -1) {
return (-1);
}
(void) memset(&ar, 0, sizeof (ar));
ar.arp_pa.sa_family = AF_INET;
sin = (struct sockaddr_in *)&ar.arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr(name.nodename);
if (sin->sin_addr.s_addr == (in_addr_t)-1) {
hp = gethostbyname(name.nodename);
if (hp == NULL) {
return (-1);
}
(void) memcpy(&sin->sin_addr, hp->h_addr,
sizeof (sin->sin_addr));
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
return (-1);
}
if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
(void) close(s);
return (-1);
}
(void) close(s);
if (ar.arp_flags & ATF_COM) {
bcopy(&ar.arp_ha.sa_data, node, 6);
} else
return (-1);
return (0);
}
int
get_ethernet_address(uuid_node_t *node)
{
walker_arg_t state;
if (arp_get(node) == 0)
return (0);
state.wa_addrvalid = B_FALSE;
dlpi_walk(get_etheraddr, &state, 0);
if (state.wa_addrvalid)
bcopy(state.wa_etheraddr, node, state.wa_etheraddrlen);
return (state.wa_addrvalid ? 0 : -1);
}
static boolean_t
get_etheraddr(const char *linkname, void *arg)
{
int retval;
dlpi_handle_t dh;
walker_arg_t *statep = arg;
if (dlpi_open(linkname, &dh, 0) != DLPI_SUCCESS)
return (B_FALSE);
statep->wa_etheraddrlen = DLPI_PHYSADDR_MAX;
retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR,
statep->wa_etheraddr, &(statep->wa_etheraddrlen));
dlpi_close(dh);
if (retval == DLPI_SUCCESS) {
statep->wa_addrvalid = B_TRUE;
return (B_TRUE);
}
return (B_FALSE);
}