Skip to content

Commit

Permalink
add iothaddr
Browse files Browse the repository at this point in the history
  • Loading branch information
rd235 committed Jan 18, 2021
1 parent f571e58 commit 3ad6b66
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 3 deletions.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ include(CheckSymbolExists)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2 -O2 -pedantic -Wall -Wextra")
set(SYSTEM_IOTH_PATH ${CMAKE_INSTALL_FULL_LIBDIR}/ioth)

set(LIBS_REQUIRED fduserdata vdeplug)
set(HEADERS_REQUIRED nlinline+.h fduserdata.h libvdeplug.h)
set(LIBS_REQUIRED fduserdata vdeplug mhash)
set(HEADERS_REQUIRED nlinline+.h fduserdata.h libvdeplug.h mhash.h)
set(CMAKE_REQUIRED_QUIET TRUE)

foreach(THISLIB IN LISTS LIBS_REQUIRED)
Expand Down Expand Up @@ -41,6 +41,13 @@ set_target_properties(ioth PROPERTIES VERSION ${PROJECT_VERSION}
install(TARGETS ioth DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES ioth.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

add_library(iothaddr SHARED iothaddr.c)
target_link_libraries(iothaddr -lmhash)
set_target_properties(iothaddr PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
install(TARGETS iothaddr DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES iothaddr.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

configure_file(config.h.in config.h)

add_subdirectory(test)
Expand Down
30 changes: 29 additions & 1 deletion ioth.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef LIBIOTH_H
#define LIBIOTH_H
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
Expand Down Expand Up @@ -82,5 +83,32 @@ struct ioth_functions {
typeof(sendto) *sendto;
typeof(sendmsg) *sendmsg;
};
#endif

/* ------------------ MAC address conversions --------------- */

#define MAC_ADDRSTRLEN 18

/* This function converts a 6 byte MAC address family into a character string.
The buffer dst must be at least MAC_ADDRSTRLEN bytes */
static inline const char *ioth_ntomac(const void *src, char *dst, size_t size) {
const unsigned char *mac = src;
snprintf(dst, size, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return dst;
}

/* This function converts the character string src into a 6 byte MAC address.
src points to a characteer string in the form "xx:xx:xx:xx:xx:xx" or
"xx-xx-xx-xx-xx-xx" where xx is a sequence of two hexadecimal digits
(not case sensitive) */
static inline int ioth_macton(const char *src, void *dst) {
unsigned char *mac = dst;
if (sscanf(src, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5) != 6)
if (sscanf(src, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx",
mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5) != 6)
return 0;
return 1;
}

#endif
84 changes: 84 additions & 0 deletions iothaddr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* iothaddr.c: utility library for ioth address management
* hash (md5sum) based mac and ipv6 host address + eui64 conversion
*
* Copyright 2021 Renzo Davoli - Virtual Square Team
* University of Bologna - Italy
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*/

#include <mhash.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <iothaddr.h>

void iothaddr_hash(void *addr, const char *name, const char *passwd, uint32_t otiptime) {
struct in6_addr *addr6 = addr;
size_t namelen = strlen(name);
MHASH td;
char out[mhash_get_block_size(MHASH_MD5)];
int i;
memset(out, 0, mhash_get_block_size(MHASH_MD5));
if (name[namelen-1] == '.') namelen--;
td=mhash_init(MHASH_MD5);
mhash(td, name, namelen);
if (passwd != NULL)
mhash(td, passwd, strlen(passwd));
if (otiptime != 0) {
uint32_t otiptime_n = htonl(otiptime);
mhash(td, &otiptime_n, sizeof(otiptime_n));
}
mhash_deinit(td, out);
for (i=8; i<16; i++)
addr6->s6_addr[i] ^= out[i-8];
addr6->s6_addr[8] &= ~0x3; // locally adm, unicast
}

void iothaddr_hashmac(void *mac, const char *name, const char *passwd) {
unsigned char *umac = mac;
size_t namelen = strlen(name);
MHASH td;
char out[mhash_get_block_size(MHASH_MD5)];
int i;
memset(out, 0, mhash_get_block_size(MHASH_MD5));
if (name[namelen-1] == '.') namelen--;
td=mhash_init(MHASH_MD5);
mhash(td, name, namelen);
if (passwd != NULL)
mhash(td, passwd, strlen(passwd));
mhash_deinit(td, out);
for (i=0; i<3; i++)
umac[i] = out[i];
for (i=3; i<6; i++)
umac[i] = out[i+2];
umac[0] |= 0x2; // locally adm
umac[0] &= ~0x1; // unicast
}

void iothaddr_eui64(void *addr, void *mac) {
struct in6_addr *addr6 = addr;
unsigned char *umac = mac;
int i;
for (i=0; i<3; i++)
addr6->s6_addr[i + 8] = umac[i];
addr6->s6_addr[11] = 0xff;
addr6->s6_addr[12] = 0xfe;
for (i=3; i<6; i++)
addr6->s6_addr[i + 10] ^= umac[i];
addr6->s6_addr[8] ^= 0x2; // L bit has inverse meaning.
}

void iothaddr_hasheui64(void *addr, const char *name, const char *passwd) {
unsigned char mac[6];
iothaddr_hashmac(mac, name, passwd);
iothaddr_eui64(addr, mac);
}
54 changes: 54 additions & 0 deletions iothaddr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef IOTHADDR_H
#define IOTHADDR_H
#include <stdint.h>
#include <time.h>

/* hash based IPv6 address:
the rightmost 64 bits of the address are XORed with the first 64 bit of
the md5sum of the concatenation of:
* name
* passwd, if passwd != NULL
* the big-endian 4 byte representation of otiptime, if otiptime != 0.
bits 71 and 72 of addr are cleared (locally adm unicast address. */
/* e.g. addr: 2000:760::/64, name = "test.v2.cs.unibo.it", passwd = NULL, otiptime = 0
the md5sum of "test.v2.cs.unibo.it" is 69d62fac095a5a2ee4c2c79f211e57e3
The resulting address is 2000:760::68d6:2fac:95a:5a2e */
void iothaddr_hash(void *addr, const char *name, const char *passwd, uint32_t otiptime);

/* One Time IP address (OTIP), computation of otiptime:
((seconds since the epoch) / otip_period) + otip_offset.
otip_period is the address expiration period.
otip_offset can be used on servers to anticipate the validity of addresses to tolerate
negative drifts or clients' clocks. */
static inline uint32_t iothaddr_otiptime(int otip_period, int otip_offset) {
return (uint32_t) ((time(NULL) + otip_offset) / otip_period);
}

/* hash based mac address
Let H be the md5sum of the concatenation of:
* name
* passwd, if passwd != NULL.
The mac address is set to:
H'[0] : H[1] : H[2] : H[5] : H[6] : H[7]
(the first byte has the 7th bit set and the 8th cleared: locally adm unicast address)
e.g. name = "test.v2.cs.unibo.it", passwd = NULL
the md5sum of "test.v2.cs.unibo.it" is 69d62fac095a5a2ee4c2c79f211e57e3
the mac address is: 69:d6:2f:5a:5a:2e */
/* Hash based defined MAC address can avoid delays due to old info in arp tables
for process migration or restarting */
void iothaddr_hashmac(void *mac, const char *name, const char *passwd);

/* compute the EUI64 based IPv6 address from the mac address.
the rightmost 64 bits of the address are XORed with the EUI64 extension
of the 6 bytes mac address. */
void iothaddr_eui64(void *addr, void *mac);

/* compute the EUI64 based IPv6 address from the hash computed mac address.
This function computes iothaddr_eui64 on the result of iothaddr_hashmac */
/* e.g. addr: 2000:760::/64, name = "test.v2.cs.unibo.it", passwd = NULL
the md5sum of "test.v2.cs.unibo.it" is 69d62fac095a5a2ee4c2c79f211e57e3
the mac address is: 69:d6:2f:5a:5a:2e
The resulting address is 2000:760::68d6:2fff:fe5a:5a2e */
void iothaddr_hasheui64(void *addr, const char *name, const char *passwd);

#endif

0 comments on commit 3ad6b66

Please sign in to comment.