27 #include <netinet/in.h>
28 #include <linux/if_vlan.h>
29 #include <linux/if_ether.h>
30 #include <linux/if_packet.h>
31 #include <linux/if_tun.h>
32 #include <linux/if_arp.h>
33 #include <linux/sockios.h>
36 #include <sys/ioctl.h>
53 #include "libnetlink/include/libnetlink.h"
54 #include "libnetlink/include/ll_map.h"
55 #include "libnetlink/include/utils.h"
57 static struct rtnl_handle *nlh;
104 static void nlhandle_free(
void *data) {
105 struct rtnl_handle *nlh = data;
112 static struct rtnl_handle *nlhandle(
int subscriptions) {
113 struct rtnl_handle *nlh;
115 if (!(nlh =
objalloc(
sizeof(*nlh), nlhandle_free)) || (rtnl_open(nlh, 0))) {
142 if (!
objref(nlh) && !(nlh = nlhandle(0))) {
150 ifindex = ll_name_to_index(ifname);
159 static int delete_interface(
char *iface) {
164 if (
strlenzero(iface) || (strlen(iface) > IFNAMSIZ) ||
165 (!
objref(nlh) && !(nlh = nlhandle(0)))) {
175 if (!(req =
objalloc(
sizeof(*req), NULL))) {
180 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
181 req->
n.nlmsg_type = RTM_DELLINK;
182 req->
n.nlmsg_flags = NLM_F_REQUEST;
185 req->
i.ifi_index = ifindex;
188 ret = rtnl_talk(nlh, &req->
n, 0, 0, NULL);
202 char iface[IFNAMSIZ+1];
205 snprintf(iface, IFNAMSIZ,
"%s.%i", ifname, vid);
206 return (delete_interface(iface));
216 char iface[IFNAMSIZ+1];
217 struct rtattr *data, *linkinfo;
221 if (
strlenzero(ifname) || (strlen(ifname) > IFNAMSIZ) ||
222 (!
objref(nlh) && !(nlh = nlhandle(0)))) {
232 if (!(req =
objalloc(
sizeof(*req), NULL))) {
237 snprintf(iface, IFNAMSIZ,
"%s.%i", ifname, vid);
238 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
239 req->
n.nlmsg_type = RTM_NEWLINK;
240 req->
n.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST;
243 addattr_l(&req->
n,
sizeof(*req), IFLA_LINK, &ifindex,
sizeof(ifindex));
244 addattr_l(&req->
n,
sizeof(*req), IFLA_IFNAME, iface, strlen(iface));
247 linkinfo = NLMSG_TAIL(&req->
n);
248 addattr_l(&req->
n,
sizeof(*req), IFLA_LINKINFO, NULL, 0);
249 addattr_l(&req->
n,
sizeof(*req), IFLA_INFO_KIND, type, strlen(type));
252 data = NLMSG_TAIL(&req->
n);
253 addattr_l(&req->
n,
sizeof(*req), IFLA_INFO_DATA, NULL, 0);
254 addattr_l(&req->
n,
sizeof(*req), IFLA_VLAN_ID, &vid,
sizeof(vid));
256 data->rta_len = (
char *)NLMSG_TAIL(&req->
n) - (
char *)data;
257 linkinfo->rta_len = (
char *)NLMSG_TAIL(&req->
n) - (
char *)linkinfo;
260 ret = rtnl_talk(nlh, &req->
n, 0, 0, NULL);
274 return (delete_interface(ifname));
284 struct rtattr *data, *linkinfo;
285 unsigned char lmac[ETH_ALEN];
286 char *type =
"macvlan";
289 if (
strlenzero(ifname) || (strlen(ifname) > IFNAMSIZ) ||
290 strlenzero(macdev) || (strlen(macdev) > IFNAMSIZ) ||
291 (!
objref(nlh) && !(nlh = nlhandle(0)))) {
304 strncpy((
char *)lmac, (
char *)mac, ETH_ALEN);
307 if (!(req =
objalloc(
sizeof(*req), NULL))) {
312 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
313 req->
n.nlmsg_type = RTM_NEWLINK;
314 req->
n.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST;
317 addattr_l(&req->
n,
sizeof(*req), IFLA_LINK, &ifindex, 4);
318 addattr_l(&req->
n,
sizeof(*req), IFLA_IFNAME, macdev, strlen(macdev));
319 addattr_l(&req->
n,
sizeof(*req), IFLA_ADDRESS, lmac, ETH_ALEN);
322 linkinfo = NLMSG_TAIL(&req->
n);
323 addattr_l(&req->
n,
sizeof(*req), IFLA_LINKINFO, NULL, 0);
324 addattr_l(&req->
n,
sizeof(*req), IFLA_INFO_KIND, type, strlen(type));
327 data = NLMSG_TAIL(&req->
n);
328 addattr_l(&req->
n,
sizeof(*req), IFLA_INFO_DATA, NULL, 0);
329 addattr32(&req->
n,
sizeof(*req), IFLA_MACVLAN_MODE, MACVLAN_MODE_PRIVATE);
330 data->rta_len = (
char *)NLMSG_TAIL(&req->
n) - (
char *)data;
331 linkinfo->rta_len = (
char *)NLMSG_TAIL(&req->
n) - (
char *)linkinfo;
334 ret = rtnl_talk(nlh, &req->
n, 0, 0, NULL);
352 if (!
objref(nlh) && !(nlh = nlhandle(0))) {
356 flags = ll_index_to_flags(ifindex);
361 if (!(req =
objalloc(
sizeof(*req), NULL))) {
366 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
367 req->
n.nlmsg_type = RTM_NEWLINK;
368 req->
n.nlmsg_flags = NLM_F_REQUEST;
371 req->
i.ifi_index = ifindex;
372 req->
i.ifi_flags = flags;
373 req->
i.ifi_change = set | clear;
376 rtnl_talk(nlh, &req->
n, 0, 0, NULL);
391 if ((!
objref(nlh) && !(nlh = nlhandle(0)))) {
395 if (!(req =
objalloc(
sizeof(*req), NULL))) {
400 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
401 req->
n.nlmsg_type = RTM_NEWLINK;
402 req->
n.nlmsg_flags = NLM_F_REQUEST;
403 req->
i.ifi_index = ifindex;
406 addattr_l(&req->
n,
sizeof(*req), IFLA_ADDRESS, hwaddr, ETH_ALEN);
409 rtnl_talk(nlh, &req->
n, 0, 0, NULL);
424 if ((!
objref(nlh) && !(nlh = nlhandle(0)))) {
428 if (!(req =
objalloc(
sizeof(*req), NULL))) {
433 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifinfomsg));
434 req->
n.nlmsg_type = RTM_NEWLINK;
435 req->
n.nlmsg_flags = NLM_F_REQUEST;
436 req->
i.ifi_index = ifindex;
438 addattr_l(&req->
n,
sizeof(*req), IFLA_IFNAME, name, strlen((
char *)name));
441 rtnl_talk(nlh, &req->
n, 0, 0, NULL);
454 struct sockaddr_ll sll;
455 int proto = htons(protocol);
465 if ((fd = socket(PF_PACKET, SOCK_RAW, proto)) < 0) {
470 memset(&sll, 0,
sizeof(sll));
471 sll.sll_family = PF_PACKET;
472 sll.sll_protocol = proto;
473 sll.sll_ifindex = ifindex;
474 if (bind(fd, (
struct sockaddr *)&sll,
sizeof(sll)) < 0) {
475 perror(
"bind failed");
496 extern int create_tun(
const char *ifname,
const unsigned char *hwaddr,
int flags) {
499 char *tundev =
"/dev/net/tun";
502 if ((fd = open(tundev, O_RDWR)) < 0) {
507 memset(&ifr, 0,
sizeof(ifr));
508 ifr.ifr_flags = flags;
509 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
510 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0 ) {
511 perror(
"ioctl(TUNSETIFF) failed\n");
535 extern int ifdown(
const char *ifname,
int flags) {
553 extern int ifup(
const char *ifname,
int flags) {
571 extern int ifrename(
const char *oldname,
const char *newname) {
588 extern int ifhwaddr(
const char *ifname,
unsigned char *hwaddr) {
591 if (!hwaddr ||
strlenzero(ifname) || (strlen(ifname) > IFNAMSIZ) ||
592 (!
objref(nlh) && !(nlh = nlhandle(0)))) {
602 ll_index_to_addr(ifindex, hwaddr, ETH_ALEN);
616 if ((!
objref(nlh) && !(nlh = nlhandle(0)))) {
620 if (!(req =
objalloc(
sizeof(*req), NULL))) {
631 req->
n.nlmsg_len = NLMSG_LENGTH(
sizeof(
struct ifaddrmsg));
632 req->
n.nlmsg_type = RTM_NEWADDR;
633 req->
n.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
635 req->
i.ifa_scope = RT_SCOPE_HOST;
636 req->
i.ifa_index = ifindex;
638 get_prefix(&lcl, ipaddr, AF_UNSPEC);
639 req->
i.ifa_family = lcl.family;
640 req->
i.ifa_prefixlen = lcl.bitlen;
642 addattr_l(&req->
n,
sizeof(*req), IFA_LOCAL, &lcl.data, lcl.bytelen);
643 addattr_l(&req->
n,
sizeof(*req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
644 if (lcl.family == AF_INET) {
645 bcast = htonl((1 << (32 - lcl.bitlen)) - 1);
646 addattr32(&req->
n,
sizeof(*req), IFA_BROADCAST, lcl.data[0] | bcast);
650 rtnl_talk(nlh, &req->
n, 0, 0, NULL);
668 extern void eui48to64(
unsigned char *mac48,
unsigned char *eui64) {
669 eui64[0] = (mac48[0] & 0xFE) ^ 0x02;
689 unsigned char eui64[8];
690 unsigned char sha1[20];
691 unsigned char mac48[ETH_ALEN];
698 gettimeofday(&tv, NULL);
702 sha1sum2(sha1, (
void *)&ntpts,
sizeof(ntpts), (
void *)eui64,
sizeof(eui64));
705 memcpy(prefix + 1, sha1+15, 5);
718 int score_ipv4(
struct sockaddr_in *sa4,
char *ipaddr,
int iplen) {
722 addr = sa4->sin_addr.s_addr;
725 inet_ntop(AF_INET, &sa4->sin_addr, ipaddr, iplen);
728 if (!((0xa9fe0000 ^ ntohl(addr)) >> 16)) {
746 int score_ipv6(
struct sockaddr_in6 *sa6,
char *ipaddr,
int iplen) {
747 uint32_t *ipptr, match;
751 ipptr = sa6->sin6_addr.s6_addr32;
753 ipptr = (uint32_t*)sa6->sin6_addr.u.Word;
755 match = ntohl(ipptr[0]) >> 16;
758 if (!(0xFE80 ^ match) || !(0xFF ^ (match >> 8)) || !match) {
763 if (!(0xFC ^ (match >> 9))) {
765 }
else if (match == 2002) {
770 inet_ntop(AF_INET6, ipptr, ipaddr, iplen);
784 struct ifaddrs *ifaddr, *ifa;
785 struct sockaddr_in *ipv4addr;
786 int score = 0, nscore, iflen;
787 uint32_t subnet = 0, match;
788 char host[NI_MAXHOST] =
"", tmp[NI_MAXHOST];
790 if (!iface || getifaddrs(&ifaddr) == -1) {
794 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
795 iflen = strlen(iface);
796 if ((ifa->ifa_addr == NULL) || strncmp(ifa->ifa_name, iface, iflen) || (ifa->ifa_addr->sa_family != family)) {
801 if ((strlen(ifa->ifa_name) > iflen) && (ifa->ifa_name[iflen] !=
':')) {
805 switch (ifa->ifa_addr->sa_family) {
809 ipv4addr = (
struct sockaddr_in*)ifa->ifa_netmask;
810 match = ntohl(~ipv4addr->sin_addr.s_addr);
812 nscore =
score_ipv4((
struct sockaddr_in*)ifa->ifa_addr, tmp, NI_MAXHOST);
815 if ((nscore > score) || ((nscore == score) && (match > subnet))) {
818 strncpy(host, tmp, NI_MAXHOST);
822 nscore =
score_ipv6((
struct sockaddr_in6*)ifa->ifa_addr, tmp, NI_MAXHOST);
824 if (nscore > score) {
826 strncpy(host, tmp, NI_MAXHOST);
832 return (
strlenzero(host)) ? NULL : strdup(host);
struct nlmsghdr n
Netlink message header.
uint64_t tvtontp64(struct timeval *tv)
Convert a timeval struct to 64bit NTP time.
int strlenzero(const char *str)
Check if a string is zero length.
int ifrename(const char *oldname, const char *newname)
Rename interface helper.
int objref(void *data)
Reference a object.
ipv4_score
Order of precidence of ipv4.
Reseverd "private" ip addresses.
int objlock(void *data)
Lock the reference.
int set_interface_addr(int ifindex, const unsigned char *hwaddr)
Set interface MAC addr.
int interface_bind(char *iface, int protocol)
Bind to device fd may be a existing socket.
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
void closenetlink(void)
Close netlink socket on application termination.
int score_ipv6(struct sockaddr_in6 *sa6, char *ipaddr, int iplen)
Return a score for a IPv6 addrress.
int create_kernmac(char *ifname, char *macdev, unsigned char *mac)
Create a kernal MAC VLAN.
int ifhwaddr(const char *ifname, unsigned char *hwaddr)
Get MAC addr for interface.
void randhwaddr(unsigned char *addr)
create random MAC address
const char * get_ifipaddr(const char *iface, int family)
Find best IP adress for a interface.
int set_interface_ipaddr(char *ifname, char *ipaddr)
Set IP addr on interface.
int score_ipv4(struct sockaddr_in *sa4, char *ipaddr, int iplen)
Return a score for a IPv4 addrress.
DTS Application library API Include file.
void sha1sum2(unsigned char *buff, const void *data, unsigned long len, const void *data2, unsigned long len2)
Calculate the SHA1 hash accross 2 data chunks.
int get_iface_index(const char *ifname)
Get the netlink interface for a named interface.
int create_tun(const char *ifname, const unsigned char *hwaddr, int flags)
Create a tunnel device.
int set_interface_flags(int ifindex, int set, int clear)
Alter interface flags.
struct nlmsghdr n
Netlink message header.
Zeroconf IP's 169.254/16.
int reservedip(const char *ipaddr)
Check IP against list of reserved IP's.
void eui48to64(unsigned char *mac48, unsigned char *eui64)
Generate IPv6 address from mac address.
int create_kernvlan(char *ifname, unsigned short vid)
Create a VLAN on a interface.
int set_interface_name(int ifindex, const char *name)
Rename interface.
int genrand(void *buf, int len)
Generate random sequence.
int get_ip6_addrprefix(const char *iface, unsigned char *prefix)
Generate Unique Local IPv6 Unicast Addresses RFC 4193.
int delete_kernvlan(char *ifname, int vid)
Delete a VLAN.
ipv6_score
Return best ipv6 address in order of FFC/7 2002/16 ...
char buf[1024]
Request buffer.
Adminstrivly allocated addresses (FC/7)
struct ifinfomsg i
Interface info message.
IP Netlink IP addr request.
int objunlock(void *data)
Unlock a reference.
struct ifaddrmsg i
Interface addr message.
Other routable addresses.
const char * inet_ntop(int af, const void *src, char *dest, socklen_t size)
Win32 implementation of inet_ntop.
int delete_kernmac(char *macdev)
Delete Kernel MAC VLAN.
char buf[1024]
Request buffer.
int objunref(void *data)
Drop reference held.
int ifup(const char *ifname, int flags)
Set interface up.
int ifdown(const char *ifname, int flags)
Set interface down.