commit ed433bd013ee2de115c697293baee8f117f040ba
parent 31b387ee9181a0e68ba721b9fde30167f918b66c
Author: Robin Bron <robin@finwo.nl>
Date: Sun, 12 Feb 2023 21:37:16 +0100
iface thread basics
Diffstat:
| M | src/main.c | | | 389 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
1 file changed, 217 insertions(+), 172 deletions(-)
diff --git a/src/main.c b/src/main.c
@@ -17,7 +17,9 @@
#include "config.h"
#include "socket.h"
-#define INTERFACE "enp0s13f0u2c2"
+/* #define INTERFACE "enp0s13f0u2c2" */
+
+#define RCVBUFSIZ 65536
static const char *const usage[] = {
__NAME " [options]",
@@ -27,12 +29,61 @@ static const char *const usage[] = {
void * thread_iface(void *arg) {
struct pmlag_iface *iface = (struct pmlag_iface *)arg;
- int sockfd = sockraw_open(iface->name);
- printf("Thread started for iface: %s->%s(%d)\n", iface->bond->name, iface->name, sockfd);
+ // Open socket for the interface in the bond
+ iface->sockfd = sockraw_open(iface->name);
+ if (iface->sockfd < 0) {
+ pthread_exit(NULL);
+ return NULL;
+ }
+
+ // Reserve receive buffer, support 64k packets just in case
+ int buflen;
+ unsigned char *buffer = (unsigned char *) malloc(RCVBUFSIZ);
+ struct sockaddr saddr;
+ int saddr_len = sizeof(saddr);
+
+ printf("Thread started for iface: %s->%s(%d)\n", iface->bond->name, iface->name, iface->sockfd);
+
+ // Allow some time for all threads to register their sockets
+ // TODO: use a mutex from main thread for this to not have idle-time?
+ sleep(1);
+
+ // Bail if the bond's socket could not be opened
+ if (!iface->bond->sockfd) {
+ pthread_exit(NULL);
+ return NULL;
+ }
+
+ // Find bond socket iface_idx
+ struct sockaddr_ll sadr_ll;
+ sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address */
+ int bond_fd = iface->bond->sockfd;
+ int bond_idx = iface_idx(bond_fd, iface->bond->name);
+ int send_len;
+
+ while(1) {
+
+ // Zero out buffer, to prevent pollution, & receive packet
+ memset(buffer, 0, RCVBUFSIZ);
+ buflen = recvfrom(iface->sockfd, buffer, RCVBUFSIZ, 0, &saddr, (socklen_t *)&saddr_len);
+ if (buflen < 0) {
+ perror("recvfrom");
+ pthread_exit(NULL);
+ return NULL;
+ }
- // TODO: open raw socket on iface
- // TODO: blocking listen on iface, send to bond
- // TODO: track announces in routing table
+ // TODO: track received proto=0x0666 packet to update routing table
+
+ // Redirect packet to bond socket as-is
+ sadr_ll.sll_ifindex = bond_idx;
+ memcpy(sadr_ll.sll_addr, buffer, ETH_ALEN);
+ send_len = sendto(bond_fd, buffer, buflen, 0, (const struct sockaddr*)&sadr_ll, sizeof(struct sockaddr_ll));
+ if (buflen != send_len) {
+ perror("sendto");
+ pthread_exit(NULL);
+ return NULL;
+ }
+ }
sleep(3);
pthread_exit(NULL);
@@ -54,10 +105,10 @@ void * thread_bond(void *arg) {
iface = iface->next;
}
- // TODO: create bonded interface here
+ // TODO: open tun/tap device
// TODO: blocked listen on bond, send through routing table to other ifaces
// TODO: send broadcasts to all interfaces
- // TODO: timer to broadcast announce our presence to ifaces (keepalive-ish)
+ // TODO: timer to broadcast announce our presence to ifaces (vrrp-ish)
// hint: include sequence id, so tracking can react quickly (seq dist > 1)
// Wait for iface threads to finish
@@ -74,15 +125,10 @@ void * thread_bond(void *arg) {
int main(int argc, const char **argv) {
char *config_file="/etc/pmlag/pmlag.ini";
- int rx = 0;
- int tx = 0;
-
// Define which options we support
struct argparse_option options[] = {
OPT_HELP(),
OPT_STRING('c', "config", &config_file, "Config file to use", NULL, 0, 0),
- OPT_BOOLEAN('t', "tx", &tx, "Send a message", NULL, 0, 0),
- OPT_BOOLEAN('r', "rx", &rx, "eth dump", NULL, 0, 0),
OPT_END(),
};
@@ -97,182 +143,181 @@ int main(int argc, const char **argv) {
);
argc = argparse_parse(&argparse, argc, argv);
- /* // Load configuration file */
- /* struct pmlag_configuration *config = config_load(config_file); */
- /* if (!config) { */
- /* return 1; */
- /* } */
+ // Load configuration file
+ struct pmlag_configuration *config = config_load(config_file);
+ if (!config) {
+ return 1;
+ }
- /* // For each bond of config->bonds */
- /* struct pmlag_bond *bond = config->bonds; */
- /* while(bond) { */
- /* if(pthread_create(&(bond->tid), NULL, thread_bond, bond)) { */
- /* perror("Starting bond thread"); */
- /* return 1; */
- /* } */
- /* bond = bond->next; */
- /* } */
+ // For each bond of config->bonds
+ struct pmlag_bond *bond = config->bonds;
+ while(bond) {
+ if(pthread_create(&(bond->tid), NULL, thread_bond, bond)) {
+ perror("Starting bond thread");
+ return 1;
+ }
+ bond = bond->next;
+ }
- /* // Wait for all bonds to finish */
- /* bond = config->bonds; */
- /* while(bond) { */
- /* pthread_join(bond->tid, NULL); */
- /* bond = bond->next; */
- /* } */
+ // Wait for all bonds to finish
+ bond = config->bonds;
+ while(bond) {
+ pthread_join(bond->tid, NULL);
+ bond = bond->next;
+ }
- int sockfd;
/* int sockfd = sockraw_open(INTERFACE); */
/* if (sockfd < 0) { */
/* return 1; */
/* } */
- if (rx) {
- sockfd = sockraw_open("enp0s13f0u1c2");
- if (sockfd < 0) {
- return 1;
- }
+ /* if (rx) { */
+ /* sockfd = sockraw_open("enp0s13f0u1c2"); */
+ /* if (sockfd < 0) { */
+ /* return 1; */
+ /* } */
- // Prepare ingress buffer
- int buflen;
- unsigned char *buffer = (unsigned char *) malloc(65536);
- memset(buffer, 0, 65536);
- struct sockaddr saddr;
- int saddr_len = sizeof(saddr);
-
- struct ethhdr *eth = (struct ethhdr *)(buffer);
- struct sockaddr_in source;
- struct sockaddr_in dest;
-
- while(1) {
-
- // Fetch a packet
- buflen = recvfrom(sockfd, buffer, 65536, 0, &saddr, (socklen_t *)&saddr_len);
- if (buflen < 0) {
- perror("recvfrom");
- exit(EXIT_FAILURE);
- }
-
- printf("\n");
- printf("Got packet: %d bytes\n", buflen);
- printf("\n");
-
- printf("Ethernet header\n");
- printf("\t|- DST %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
- printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
- printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto));
-
- printf("\n");
-
- if (be16toh(eth->h_proto) == 0x0800) {
- unsigned short iphdrlen;
- struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr));
- memset(&source, 0, sizeof(source));
- source.sin_addr.s_addr = ip->saddr;
- memset(&dest, 0, sizeof(dest));
- dest.sin_addr.s_addr = ip->daddr;
-
- printf("IP header\n");
- printf("\t|- Version %d\n",(unsigned int)ip->version);
- printf("\t|- Internet hlen %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4);
- printf("\t|- Type Of Service %d\n",(unsigned int)ip->tos);
- printf("\t|- Total Length %d Bytes\n",ntohs(ip->tot_len));
- printf("\t|- Identification %d\n",ntohs(ip->id));
- printf("\t|- Time To Live %d\n",(unsigned int)ip->ttl);
- printf("\t|- Protocol %d\n",(unsigned int)ip->protocol);
- printf("\t|- Header Checksum %d\n",ntohs(ip->check));
- printf("\t|- Source IP %s\n", inet_ntoa(source.sin_addr));
- printf("\t|- Destination IP %s\n",inet_ntoa(dest.sin_addr));
-
- printf("\n");
- }
+ /* // Prepare ingress buffer */
+ /* int buflen; */
+ /* unsigned char *buffer = (unsigned char *) malloc(65536); */
+ /* memset(buffer, 0, 65536); */
+ /* struct sockaddr saddr; */
+ /* int saddr_len = sizeof(saddr); */
+
+ /* struct ethhdr *eth = (struct ethhdr *)(buffer); */
+ /* struct sockaddr_in source; */
+ /* struct sockaddr_in dest; */
+
+ /* while(1) { */
+
+ /* // Fetch a packet */
+ /* buflen = recvfrom(sockfd, buffer, 65536, 0, &saddr, (socklen_t *)&saddr_len); */
+ /* if (buflen < 0) { */
+ /* perror("recvfrom"); */
+ /* exit(EXIT_FAILURE); */
+ /* } */
+
+ /* printf("\n"); */
+ /* printf("Got packet: %d bytes\n", buflen); */
+ /* printf("\n"); */
+
+ /* printf("Ethernet header\n"); */
+ /* printf("\t|- DST %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]); */
+ /* printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]); */
+ /* printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto)); */
+
+ /* printf("\n"); */
+
+ /* if (be16toh(eth->h_proto) == 0x0800) { */
+ /* unsigned short iphdrlen; */
+ /* struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr)); */
+ /* memset(&source, 0, sizeof(source)); */
+ /* source.sin_addr.s_addr = ip->saddr; */
+ /* memset(&dest, 0, sizeof(dest)); */
+ /* dest.sin_addr.s_addr = ip->daddr; */
+
+ /* printf("IP header\n"); */
+ /* printf("\t|- Version %d\n",(unsigned int)ip->version); */
+ /* printf("\t|- Internet hlen %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4); */
+ /* printf("\t|- Type Of Service %d\n",(unsigned int)ip->tos); */
+ /* printf("\t|- Total Length %d Bytes\n",ntohs(ip->tot_len)); */
+ /* printf("\t|- Identification %d\n",ntohs(ip->id)); */
+ /* printf("\t|- Time To Live %d\n",(unsigned int)ip->ttl); */
+ /* printf("\t|- Protocol %d\n",(unsigned int)ip->protocol); */
+ /* printf("\t|- Header Checksum %d\n",ntohs(ip->check)); */
+ /* printf("\t|- Source IP %s\n", inet_ntoa(source.sin_addr)); */
+ /* printf("\t|- Destination IP %s\n",inet_ntoa(dest.sin_addr)); */
+
+ /* printf("\n"); */
+ /* } */
- }
+ /* } */
- }
+ /* } */
- if (tx) {
- sockfd = sockraw_open(INTERFACE);
- if (sockfd < 0) {
- return 1;
- }
+ /* if (tx) { */
+ /* sockfd = sockraw_open(INTERFACE); */
+ /* if (sockfd < 0) { */
+ /* return 1; */
+ /* } */
- // Prepare egress buffer
- int buflen;
- unsigned char *buffer = (unsigned char *) malloc(65536);
- memset(buffer, 0, 65536);
- struct sockaddr_ll saddr;
- int saddr_len = sizeof(saddr);
-
- // Get MAC address of the interface
- struct ifreq ifreq_c;
- memset(&ifreq_c,0,sizeof(ifreq_c));
- strncpy(ifreq_c.ifr_name,INTERFACE,IFNAMSIZ-1);//giving name of Interface
- if((ioctl(sockfd,SIOCGIFHWADDR,&ifreq_c))<0) {
- perror("error in SIOCGIFHWADDR ioctl reading");
- return 1;
- }
+ /* // Prepare egress buffer */
+ /* int buflen; */
+ /* unsigned char *buffer = (unsigned char *) malloc(65536); */
+ /* memset(buffer, 0, 65536); */
+ /* struct sockaddr_ll saddr; */
+ /* int saddr_len = sizeof(saddr); */
+
+ /* // Get MAC address of the interface */
+ /* struct ifreq ifreq_c; */
+ /* memset(&ifreq_c,0,sizeof(ifreq_c)); */
+ /* strncpy(ifreq_c.ifr_name,INTERFACE,IFNAMSIZ-1);//giving name of Interface */
+ /* if((ioctl(sockfd,SIOCGIFHWADDR,&ifreq_c))<0) { */
+ /* perror("error in SIOCGIFHWADDR ioctl reading"); */
+ /* return 1; */
+ /* } */
- // Get ethhdr reference to the buffer
- struct ethhdr *eth = (struct ethhdr *)(buffer);
-
- // Fill ethernet source address
- memcpy(eth->h_source, ifreq_c.ifr_hwaddr.sa_data, 6);
- /* eth->h_source[0] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[0]); */
- /* eth->h_source[1] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[1]); */
- /* eth->h_source[2] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[2]); */
- /* eth->h_source[3] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[3]); */
- /* eth->h_source[4] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[4]); */
- /* eth->h_source[5] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[5]); */
-
- // Broadcast packet
- eth->h_dest[0] = 0xFF;
- eth->h_dest[1] = 0xFF;
- eth->h_dest[2] = 0xFF;
- eth->h_dest[3] = 0xFF;
- eth->h_dest[4] = 0xFF;
- eth->h_dest[5] = 0xFF;
-
- // Custom protocol (not shown as registered on https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml)
- eth->h_proto = htons(0x0666);
-
- struct sockaddr_ll sadr_ll;
- sadr_ll.sll_ifindex = iface_idx(sockfd, INTERFACE);
- sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address
- memcpy(sadr_ll.sll_addr, eth->h_dest, ETH_ALEN);
-
- /* sadr_ll.sll_addr[0] = 0xFF; */
- /* sadr_ll.sll_addr[1] = 0xFF; */
- /* sadr_ll.sll_addr[2] = 0xFF; */
- /* sadr_ll.sll_addr[3] = 0xFF; */
- /* sadr_ll.sll_addr[4] = 0xFF; */
- /* sadr_ll.sll_addr[5] = 0xFF; */
-
- /* saddr.sll_ifindex = ifreq_i.ifr_ifindex; // index of interface */
- /* saddr.sll_halen = ETH_ALEN; // length of destination mac address */
- /* saddr.sll_addr[0] = DESTMAC0; */
- /* saddr.sll_addr[1] = DESTMAC1; */
- /* saddr.sll_addr[2] = DESTMAC2; */
- /* saddr.sll_addr[3] = DESTMAC3; */
- /* saddr.sll_addr[4] = DESTMAC4; */
- /* saddr.sll_addr[5] = DESTMAC5; */
-
-
- int send_len = sendto(sockfd,buffer, 12 + 2 + 46,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll));
- if(send_len<0) {
- printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno);
- return -1;
- }
+ /* // Get ethhdr reference to the buffer */
+ /* struct ethhdr *eth = (struct ethhdr *)(buffer); */
+
+ /* // Fill ethernet source address */
+ /* memcpy(eth->h_source, ifreq_c.ifr_hwaddr.sa_data, 6); */
+ /* /1* eth->h_source[0] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[0]); *1/ */
+ /* /1* eth->h_source[1] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[1]); *1/ */
+ /* /1* eth->h_source[2] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[2]); *1/ */
+ /* /1* eth->h_source[3] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[3]); *1/ */
+ /* /1* eth->h_source[4] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[4]); *1/ */
+ /* /1* eth->h_source[5] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[5]); *1/ */
+
+ /* // Broadcast packet */
+ /* eth->h_dest[0] = 0xFF; */
+ /* eth->h_dest[1] = 0xFF; */
+ /* eth->h_dest[2] = 0xFF; */
+ /* eth->h_dest[3] = 0xFF; */
+ /* eth->h_dest[4] = 0xFF; */
+ /* eth->h_dest[5] = 0xFF; */
+
+ /* // Custom protocol (not shown as registered on https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml) */
+ /* eth->h_proto = htons(0x0666); */
+
+ /* struct sockaddr_ll sadr_ll; */
+ /* sadr_ll.sll_ifindex = iface_idx(sockfd, INTERFACE); */
+ /* sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address */
+ /* memcpy(sadr_ll.sll_addr, eth->h_dest, ETH_ALEN); */
+
+ /* /1* sadr_ll.sll_addr[0] = 0xFF; *1/ */
+ /* /1* sadr_ll.sll_addr[1] = 0xFF; *1/ */
+ /* /1* sadr_ll.sll_addr[2] = 0xFF; *1/ */
+ /* /1* sadr_ll.sll_addr[3] = 0xFF; *1/ */
+ /* /1* sadr_ll.sll_addr[4] = 0xFF; *1/ */
+ /* /1* sadr_ll.sll_addr[5] = 0xFF; *1/ */
+
+ /* /1* saddr.sll_ifindex = ifreq_i.ifr_ifindex; // index of interface *1/ */
+ /* /1* saddr.sll_halen = ETH_ALEN; // length of destination mac address *1/ */
+ /* /1* saddr.sll_addr[0] = DESTMAC0; *1/ */
+ /* /1* saddr.sll_addr[1] = DESTMAC1; *1/ */
+ /* /1* saddr.sll_addr[2] = DESTMAC2; *1/ */
+ /* /1* saddr.sll_addr[3] = DESTMAC3; *1/ */
+ /* /1* saddr.sll_addr[4] = DESTMAC4; *1/ */
+ /* /1* saddr.sll_addr[5] = DESTMAC5; *1/ */
+
+
+ /* int send_len = sendto(sockfd,buffer, 12 + 2 + 46,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll)); */
+ /* if(send_len<0) { */
+ /* printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno); */
+ /* return -1; */
+ /* } */
- printf("\n");
- printf("Sent packet: %d bytes\n", send_len);
- printf("\n");
+ /* printf("\n"); */
+ /* printf("Sent packet: %d bytes\n", send_len); */
+ /* printf("\n"); */
- printf("Ethernet header\n");
- printf("\t|- DST %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
- printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
- printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto));
+ /* printf("Ethernet header\n"); */
+ /* printf("\t|- DST %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]); */
+ /* printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]); */
+ /* printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto)); */
- }
+ /* } */
/* printf("name: %s\n", __NAME); */
/* printf("conf: %s\n", config_file); */