diff --git a/address.h b/address.h index 7578f91..35ef05f 100644 --- a/address.h +++ b/address.h @@ -24,6 +24,7 @@ #include #include #include +#include struct address { socklen_t len; diff --git a/ether.h b/ether.h index ce3d663..8ec9669 100644 --- a/ether.h +++ b/ether.h @@ -22,7 +22,13 @@ #include -#define MAC_LEN 6 +#define EUI48 6 +#define EUI64 8 + +#define MAC_LEN EUI48 +#define GUID_LEN EUI64 + +#define GUID_OFFSET 36 typedef uint8_t eth_addr[MAC_LEN]; diff --git a/sk.c b/sk.c index 63ec206..0cf55c5 100644 --- a/sk.c +++ b/sk.c @@ -159,10 +159,55 @@ failed: return -1; } +static int sk_interface_guidaddr(const char *name, unsigned char *guid) +{ + char file_name[64], buf[64], addr[8]; + FILE *f; + char *err; + int res; + + snprintf(file_name, sizeof buf, "/sys/class/net/%s/address", name); + f = fopen(file_name, "r"); + if (!f) { + pr_err("failed to open %s: %m", buf); + return -1; + } + + /* Set the file position to the beginning of the GUID */ + res = fseek(f, GUID_OFFSET, SEEK_SET); + if (res) { + pr_err("fseek failed: %m"); + goto error; + } + + err = fgets(buf, sizeof buf, f); + if (err == NULL) { + pr_err("fseek failed: %m"); + goto error; + } + + res = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &addr[0], &addr[1], &addr[2], &addr[3], + &addr[4], &addr[5], &addr[6], &addr[7]); + if (res != GUID_LEN) { + pr_err("sscanf failed: %m"); + goto error; + } + + memcpy(guid, addr, GUID_LEN); + fclose(f); + + return 0; + +error: + fclose(f); + return -1; +} + int sk_interface_macaddr(const char *name, struct address *mac) { struct ifreq ifreq; - int err, fd; + int err, fd, type; memset(&ifreq, 0, sizeof(ifreq)); strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name) - 1); @@ -180,9 +225,23 @@ int sk_interface_macaddr(const char *name, struct address *mac) return -1; } + /* Get interface type */ + type = ifreq.ifr_hwaddr.sa_family; + switch (type) { + case ARPHRD_INFINIBAND: + err = sk_interface_guidaddr(name, mac->sll.sll_addr); + if (err) { + pr_err("fail to get address using sysfs: %m"); + return -1; + } + mac->sll.sll_halen = EUI64; + break; + default: + memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN); + mac->sll.sll_halen = EUI48; + } + mac->sll.sll_family = AF_PACKET; - mac->sll.sll_halen = MAC_LEN; - memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN); mac->len = sizeof(mac->sll); close(fd); return 0; diff --git a/util.c b/util.c index 2b880ff..62f2638 100644 --- a/util.c +++ b/util.c @@ -135,14 +135,32 @@ int generate_clock_identity(struct ClockIdentity *ci, const char *name) if (sk_interface_macaddr(name, &addr)) return -1; - ci->id[0] = addr.sll.sll_addr[0]; - ci->id[1] = addr.sll.sll_addr[1]; - ci->id[2] = addr.sll.sll_addr[2]; - ci->id[3] = 0xFF; - ci->id[4] = 0xFE; - ci->id[5] = addr.sll.sll_addr[3]; - ci->id[6] = addr.sll.sll_addr[4]; - ci->id[7] = addr.sll.sll_addr[5]; + + switch (addr.sll.sll_halen) { + case EUI48: + ci->id[0] = addr.sll.sll_addr[0]; + ci->id[1] = addr.sll.sll_addr[1]; + ci->id[2] = addr.sll.sll_addr[2]; + ci->id[3] = 0xFF; + ci->id[4] = 0xFE; + ci->id[5] = addr.sll.sll_addr[3]; + ci->id[6] = addr.sll.sll_addr[4]; + ci->id[7] = addr.sll.sll_addr[5]; + break; + case EUI64: + ci->id[0] = addr.sll.sll_addr[0]; + ci->id[1] = addr.sll.sll_addr[1]; + ci->id[2] = addr.sll.sll_addr[2]; + ci->id[3] = addr.sll.sll_addr[3]; + ci->id[4] = addr.sll.sll_addr[4]; + ci->id[5] = addr.sll.sll_addr[5]; + ci->id[6] = addr.sll.sll_addr[6]; + ci->id[7] = addr.sll.sll_addr[7]; + break; + default: + return -1; + } + return 0; }