Commit 7ee94551 authored by Matthieu Boutier's avatar Matthieu Boutier Committed by Juliusz Chroboczek

Implement if_eui64 for BSD.

parent eb92f09d
...@@ -50,6 +50,10 @@ THE SOFTWARE. ...@@ -50,6 +50,10 @@ THE SOFTWARE.
#include "kernel.h" #include "kernel.h"
#include "util.h" #include "util.h"
static int get_sdl(struct sockaddr_dl *sdl, char *ifname);
static const unsigned char v4prefix[16] = static const unsigned char v4prefix[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
...@@ -58,10 +62,78 @@ int export_table = -1, import_table = -1; ...@@ -58,10 +62,78 @@ int export_table = -1, import_table = -1;
int int
if_eui64(char *ifname, int ifindex, unsigned char *eui) if_eui64(char *ifname, int ifindex, unsigned char *eui)
{ {
errno = ENOSYS; struct sockaddr_dl sdl;
return -1; char *tmp = NULL;
if (get_sdl(&sdl, ifname) < 0) {
return -1;
}
tmp = sdl.sdl_data + sdl.sdl_nlen;
if (sdl.sdl_alen == 8) {
memcpy(eui, tmp, 8);
eui[0] ^= 2;
} else if (sdl.sdl_alen == 6) {
memcpy(eui, tmp, 3);
eui[3] = 0xFF;
eui[4] = 0xFE;
memcpy(eui+5, tmp+3, 3);
} else {
return -1;
}
return 0;
} }
/* fill sdl with the structure corresponding to ifname.
Warning: make a syscall (and get all interfaces).
return -1 if an error occurs, 0 otherwise. */
static int
get_sdl(struct sockaddr_dl *sdl, char *ifname)
{
int mib[6];
size_t buf_len = 0;
int offset = 0;
char *buffer = NULL;
struct if_msghdr *ifm = NULL;
struct sockaddr_dl *tmp_sdl = NULL;
int rc;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
rc = sysctl(mib, 6, NULL, &buf_len, NULL, 0);
if(rc < 0)
return -1;
buffer = (char *)malloc(buf_len);
rc = sysctl(mib, 6, buffer, &buf_len, NULL, 0);
if(rc < 0)
goto fail;
offset = 0;
while (offset < (int) buf_len) {
ifm = (struct if_msghdr *) &buffer[offset];
switch (ifm->ifm_type) {
case RTM_IFINFO:
tmp_sdl = (struct sockaddr_dl *) (ifm + 1);
if (strncmp(ifname, tmp_sdl->sdl_data, tmp_sdl->sdl_nlen) == 0
&& strlen(ifname) == tmp_sdl->sdl_nlen) {
memcpy(sdl, tmp_sdl, sizeof(struct sockaddr_dl));
return 0;
}
default:
break;
}
offset += ifm->ifm_msglen;
}
fail:
free(buffer);
return -1;
}
/* KAME said : "Following two macros are highly depending on KAME Release" */ /* KAME said : "Following two macros are highly depending on KAME Release" */
#define IN6_LINKLOCAL_IFINDEX(a) ((a).s6_addr[2] << 8 | (a).s6_addr[3]) #define IN6_LINKLOCAL_IFINDEX(a) ((a).s6_addr[2] << 8 | (a).s6_addr[3])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment