2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-12-25 12:41:39 +00:00
confluent/misc/copernicus.c
2019-03-08 13:25:53 -05:00

169 lines
6.1 KiB
C

#include <dirent.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_arp.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <net/if.h>
int add_uuid(char* destination, int maxsize) {
int uuidf;
int uuidsize;
uuidf = open("/sys/devices/virtual/dmi/id/product_uuid", O_RDONLY);
if (uuidf < 1) { return 0; }
strncpy(destination, "/uuid=", maxsize);
uuidsize = read(uuidf, destination + 6, maxsize - 6);
close(uuidf);
if (destination[uuidsize + 5] == '\n') {
destination[uuidsize + 5 ] = 0;
}
return uuidsize + 6;
}
int add_macs(char* destination, int maxsize) {
struct ifaddrs *ifc, *ifa;
struct sockaddr_ll *lla;
int offset;
char macaddr[32];
offset = 0;
getifaddrs(&ifa);
for (ifc = ifa; ifc != NULL; ifc = ifc->ifa_next) {
if (ifc->ifa_addr->sa_family != AF_PACKET)
continue;
lla = (struct sockaddr_ll *)ifc->ifa_addr;
if (lla->sll_hatype == ARPHRD_INFINIBAND) {
snprintf(macaddr, 32, "/mac=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
lla->sll_addr[12], lla->sll_addr[13], lla->sll_addr[14],
lla->sll_addr[15], lla->sll_addr[16], lla->sll_addr[17],
lla->sll_addr[18], lla->sll_addr[19]
);
} else if (lla->sll_hatype == ARPHRD_ETHER) {
snprintf(macaddr, 32, "/mac=%02x:%02x:%02x:%02x:%02x:%02x",
lla->sll_addr[0], lla->sll_addr[1], lla->sll_addr[2],
lla->sll_addr[3], lla->sll_addr[4], lla->sll_addr[5],
lla->sll_addr[6]
);
} else {
continue;
}
strncpy(destination + offset, macaddr, maxsize - offset);
offset += strnlen(macaddr, 32);
}
freeifaddrs(ifa);
}
int main(int argc, char* argv[]) {
struct ifaddrs *ifc, *ifa;
struct sockaddr_in6 *in6;
struct sockaddr_in *in, *bin;
int ns, n4;
struct sockaddr_in6 addr, dst;
struct sockaddr_in addr4, dst4;
char msg[1024];
char lastmsg[1024];
int ifidx, offset;
fd_set rfds;
struct timeval tv;
socklen_t dstsize, dst4size;
dstsize = sizeof(dst);
dst4size = sizeof(dst4);
memset(msg, 0, 1024);
memset(&addr, 0, sizeof(addr));
memset(&dst, 0, sizeof(dst));
memset(&dst4, 0, sizeof(dst4));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(190);
addr4.sin_family = AF_INET;
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
addr4.sin_port = htons(190);
dst.sin6_family = AF_INET6;
dst.sin6_port = htons(1900);
inet_pton(AF_INET6, "ff02::c", &dst.sin6_addr);
dst4.sin_family = AF_INET;
dst4.sin_port = htons(1900);
inet_pton(AF_INET, "239.255.255.250", &dst4.sin_addr);
strncpy(msg, "M-SEARCH * HTTP/1.1\r\nST: urn:xcat.org:service:confluent:", 1024);
offset = strnlen(msg, 1024);
if (argc > 1) {
snprintf(msg + offset, 1024 - offset, "/node=%s", argv[1]);
offset = strnlen(msg, 1024);
}
add_uuid(msg + offset, 1024 - offset);
offset = strnlen(msg, 1024);
add_macs(msg + offset, 1024 - offset);
offset = strnlen(msg, 1024);
ns = socket(AF_INET6, SOCK_DGRAM, 0);
n4 = socket(AF_INET, SOCK_DGRAM, 0);
ifidx = 1; /* reuse ifidx because it's an unused int here */
setsockopt(n4, SOL_SOCKET, SO_BROADCAST, &ifidx, sizeof(ifidx));
setsockopt(ns, IPPROTO_IPV6, IPV6_V6ONLY, &ifidx, sizeof(ifidx));
/* For now, bind to 190 to prove we are a privileged process */
bind(n4, (const struct sockaddr *)&addr4, sizeof(addr4));
bind(ns, (const struct sockaddr *)&addr, sizeof(addr));
getifaddrs(&ifa);
for (ifc = ifa; ifc != NULL; ifc = ifc->ifa_next) {
if (!ifc->ifa_addr) continue;
if (ifc->ifa_flags & IFF_LOOPBACK) continue;
if (ifc->ifa_flags & IFF_MULTICAST != IFF_MULTICAST) continue;
if (ifc->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ifc->ifa_addr;
if (in6->sin6_scope_id == 0)
continue;
ifidx = in6->sin6_scope_id;
setsockopt(ns, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifidx, sizeof(ifidx));
sendto(ns, msg, strnlen(msg, 1024), 0, (const struct sockaddr *)&dst, sizeof(dst));
} else if (ifc->ifa_addr->sa_family == AF_INET) {
in = (struct sockaddr_in *)ifc->ifa_addr;
bin = (struct sockaddr_in *)ifc->ifa_ifu.ifu_broadaddr;
bin->sin_port = htons(1900);
setsockopt(n4, IPPROTO_IP, IP_MULTICAST_IF, &in->sin_addr, sizeof(in->sin_addr));
sendto(n4, msg, strnlen(msg, 1024), 0, (const struct sockaddr *)&dst4, sizeof(dst4));
sendto(n4, msg, strnlen(msg, 1024), 0, (const struct sockaddr *)bin, sizeof(*bin));
}
}
FD_ZERO(&rfds);
FD_SET(n4, &rfds);
FD_SET(ns, &rfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
ifidx = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
while (ifidx) {
if (ifidx == -1) perror("Unable to select");
if (ifidx) {
if (FD_ISSET(n4, &rfds)) {
recvfrom(n4, msg, 1024, 0, (struct sockaddr *)&dst4, &dst4size);
inet_ntop(dst4.sin_family, &dst4.sin_addr, msg, dst4size);
/* Take measure from printing out the same ip twice in a row */
if (strncmp(lastmsg, msg, 1024) != 0) {
printf("%s\n", msg);
strncpy(lastmsg, msg, 1024);
}
}
if (FD_ISSET(ns, &rfds)) {
recvfrom(ns, msg, 1024, 0, (struct sockaddr *)&dst, &dstsize);
inet_ntop(dst.sin6_family, &dst.sin6_addr, msg, dstsize);
if (strncmp(lastmsg, msg, 1024) != 0) {
printf("%s\n", msg);
strncpy(lastmsg, msg, 1024);
}
}
}
tv.tv_sec = 0;
tv.tv_usec = 500000;
FD_SET(n4, &rfds);
FD_SET(ns, &rfds);
ifidx = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
}
}