commit dee2f5cf9ef6f300c6fdb1affcb3e7800275339a
parent ce4e853aeb77251b876641d4aecb5756a2d41dcf
Author: Yersa Nordman <yersa@finwo.nl>
Date: Tue, 7 Feb 2023 21:28:24 +0100
Loading ini file now functional
Diffstat:
| A | src/config.c | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/config.h | | | 36 | ++++++++++++++++++++++++++++++++++++ |
| M | src/main.c | | | 399 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
| A | src/socket.c | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/socket.h | | | 15 | +++++++++++++++ |
| A | test.ini | | | 23 | +++++++++++++++++++++++ |
6 files changed, 397 insertions(+), 225 deletions(-)
diff --git a/src/config.c b/src/config.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "benhoyt/inih.h"
+#include "config.h"
+
+static int config_load_handler(
+ void *user,
+ const char *section,
+ const char *name,
+ const char *value
+) {
+ struct pmlag_configuration* config = (struct pmlag_configuration *) user;
+
+ // Get bond being configured
+ struct pmlag_bond *bond = config->bonds;
+ while(bond) {
+ if (!strcmp(bond->name, section)) {
+ break;
+ }
+ bond = bond->next;
+ }
+
+ // Create bond if not found
+ if (!bond) {
+ bond = calloc(1, sizeof(struct pmlag_bond));
+ bond->next = config->bonds;
+ bond->name = strdup(section);
+ config->bonds = bond;
+ }
+
+ // Get interface being configured
+ struct pmlag_interface *iface = bond->interfaces;
+
+ if (0) {
+ // Intentionally empty
+ } else if (!strcmp(name, "mode")) {
+ // Set the mode according to found value
+ if (0) {
+ // Intentionally empty
+ } else if (!strcmp(value, "active-backup")) {
+ bond->mode = PMLAG_MODE_ACTIVE_BACKUP;
+ } else if (!strcmp(value, "balanced-rr")) {
+ bond->mode = PMLAG_MODE_BALANCED_RR;
+ } else if (!strcmp(value, "broadcast")) {
+ bond->mode = PMLAG_MODE_BROADCAST;
+ } else {
+ return 0;
+ }
+ } else if (!strcmp(name, "interface")) {
+
+ // Select the right interface
+ while(iface) {
+ if (!strcmp(iface->name, value)) {
+ break;
+ }
+ iface = iface->next;
+ }
+
+ // Create iface if not found
+ if (!iface) {
+ iface = calloc(1, sizeof(struct pmlag_interface));
+ iface->next = bond->interfaces;
+ iface->name = strdup(value);
+ iface->weight = 10;
+ bond->interfaces = iface;
+ }
+
+ } else if (!strcmp(name, "weight")) {
+ if (!iface) {
+ return 0;
+ }
+
+ iface->weight = atoi(value);
+ } else {
+ // Unknown key
+ return 0;
+ }
+
+ return 1;
+}
+
+struct pmlag_configuration * config_load(const char * filename) {
+ // Load config, entry-by-entry
+ struct pmlag_configuration *config = calloc(1, sizeof(struct pmlag_configuration));
+ if (ini_parse(filename, config_load_handler, config) < 0) {
+ fprintf(stderr, "Can not load %s\n", filename);
+ return NULL;
+ }
+ return config;
+}
diff --git a/src/config.h b/src/config.h
@@ -0,0 +1,36 @@
+#ifndef __PMLAG_CONFIG_H__
+#define __PMLAG_CONFIG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PMLAG_MODE_NONE 0
+#define PMLAG_MODE_ACTIVE_BACKUP 1
+#define PMLAG_MODE_BROADCAST 2
+#define PMLAG_MODE_BALANCED_RR 3
+
+struct pmlag_interface {
+ void *next;
+ char *name;
+ int weight;
+};
+
+struct pmlag_bond {
+ void *next;
+ char *name;
+ int mode;
+ struct pmlag_interface *interfaces;
+};
+
+struct pmlag_configuration {
+ struct pmlag_bond *bonds;
+};
+
+struct pmlag_configuration * config_load(const char * filename);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // __PMLAG_CONFIG_H__
diff --git a/src/main.c b/src/main.c
@@ -1,96 +1,34 @@
-#include "cofyc/argparse.h"
-
-#include <stdio.h>
-
#include <arpa/inet.h>
-#include <net/ethernet.h>
+#include <errno.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
-#include <unistd.h>
-#include <linux/if_packet.h>
-#include <netinet/ip.h>
+#include <stdio.h>
-#include <errno.h>
+#include "cofyc/argparse.h"
+#include "config.h"
+#include "socket.h"
#define INTERFACE "docker0"
-
static const char *const usage[] = {
__NAME " [options]",
NULL
};
-/* typedef struct { */
-/* // Linked list */
-/* void *next; // Ref to the next interface */
-/* // Config */
-/* char *name; // Name of the interface */
-/* char *mac; // Mac address to set on the interface */
-/* // Activity */
-/* int socket; // Socket file descriptor */
-/* } pmlag_interface; */
-
-int iface_idx(int sockfd, char * ifname) {
- struct ifreq ifr;
- bzero(&ifr, sizeof(ifr));
-
- // Get interface index
- strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ);
- if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) {
- perror("Error getting interface index");
- close(sockfd);
- return -1;
- }
-
- return ifr.ifr_ifindex;
-}
-
-int sockraw_open(char * ifname) {
-
- // Open socket
- int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (sockfd < 0) {
- perror("Error opening socket");
- close(sockfd);
- return -1;
- }
-
- // Bind socket to interface
- struct sockaddr_ll sll;
- bzero(&sll, sizeof(sll));
- sll.sll_family = AF_PACKET;
- sll.sll_ifindex = iface_idx(sockfd, ifname);
- sll.sll_protocol = htons(ETH_P_ALL);
- if (sll.sll_ifindex < 0) {
- // Error already printed, not reprinting
- return -1;
- }
- if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) {
- perror("Error binding raw socket to interface");
- close(sockfd);
- return -1;
- }
-
- // Return the prepared socket
- return sockfd;
-}
-
int main(int argc, const char **argv) {
char *config_file="/etc/pmlag/pmlag.ini";
-
- int tx = 0;
- int rx = 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, "Send a message", NULL, 0, 0),
OPT_END(),
};
@@ -105,168 +43,179 @@ int main(int argc, const char **argv) {
);
argc = argparse_parse(&argparse, argc, argv);
- /* while(iface) { */
- /* fprintf(stderr, " Interface: %s\n", iface->name); */
- /* fprintf(stderr, " master : %s\n", iface->master ? iface->master : ""); */
- /* fprintf(stderr, " mac : %s\n", iface->mac ? iface->mac : ""); */
- /* fprintf(stderr, " broadcast: %s%s\n", */
- /* iface->broadcast == BROADCAST_FLOOD ? "flood" : "", */
- /* iface->broadcast == BROADCAST_BALANCED ? "balanced" : "" */
- /* ); */
- /* fprintf(stderr, " mode : %s%s%s%s\n", */
- /* iface->mode == MODE_SLAVE ? "slave" : "", */
- /* iface->mode == MODE_ACTIVE_BACKUP ? "active-backup" : "", */
- /* iface->mode == MODE_BROADCAST ? "broadcast" : "", */
- /* iface->mode == MODE_BALANCE_RR ? "balance-rr" : "" */
- /* ); */
- /* fprintf(stderr, " weight : %d\n", iface->weight); */
- /* iface = iface->next; */
- /* if (iface == loaded->interfaces) break; */
- /* } */
-
-
-
-
-
- int sockfd = sockraw_open(INTERFACE);
- if (sockfd < 0) {
+ // Load configuration file
+ struct pmlag_configuration *config = config_load(config_file);
+ if (!config) {
return 1;
}
- if (rx) {
-
- // 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");
- }
-
+ printf("Loaded configuration:\n");
+ // For each bond of config->bonds
+ struct pmlag_bond *bond = config->bonds;
+ struct pmlag_interface *iface;
+ while(bond) {
+ printf("\n%s:\n", bond->name);
+ printf(" mode: %s\n", (
+ bond->mode == PMLAG_MODE_NONE
+ ? "NONE"
+ : (
+ bond->mode == PMLAG_MODE_BROADCAST
+ ? "BROADCAST"
+ : (
+ bond->mode == PMLAG_MODE_BALANCED_RR
+ ? "BROADCAST"
+ : "ACTIVE_BACKUP"
+ )
+ )
+ ));
+ iface = bond->interfaces;
+ // For each iface of config->interfaces
+ while(iface) {
+ printf("\n %s:\n", iface->name);
+ printf(" weight: %d\n", iface->weight);
+ iface = iface->next;
}
-
+ bond = bond->next;
}
- if (tx) {
-
- // 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;
- }
+ /* int sockfd = sockraw_open(INTERFACE); */
+ /* if (sockfd < 0) { */
+ /* 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,64,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;
- }
+ /* if (rx) { */
+
+/* // 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"); */
+/* } */
+
+/* } */
- printf("Hello there!\n");
- }
+ /* } */
+
+ /* if (tx) { */
+
+/* // 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); */
+/* /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,60,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("name: %s\n", __NAME);
- printf("conf: %s\n", config_file);
- printf("sock: %d\n", sockfd);
+ /* printf("name: %s\n", __NAME); */
+ /* printf("conf: %s\n", config_file); */
+ /* printf("sock: %d\n", sockfd); */
return 42;
}
diff --git a/src/socket.c b/src/socket.c
@@ -0,0 +1,57 @@
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "socket.h"
+
+int iface_idx(int sockfd, char * ifname) {
+ struct ifreq ifr;
+ bzero(&ifr, sizeof(ifr));
+
+ // Get interface index
+ strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ);
+ if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) {
+ perror("Error getting interface index");
+ close(sockfd);
+ return -1;
+ }
+
+ return ifr.ifr_ifindex;
+}
+
+int sockraw_open(char * ifname) {
+
+ // Open socket
+ int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (sockfd < 0) {
+ perror("Error opening socket");
+ close(sockfd);
+ return -1;
+ }
+
+ // Bind socket to interface
+ struct sockaddr_ll sll;
+ bzero(&sll, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = iface_idx(sockfd, ifname);
+ sll.sll_protocol = htons(ETH_P_ALL);
+ if (sll.sll_ifindex < 0) {
+ // Error already printed, not reprinting
+ return -1;
+ }
+ if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) {
+ perror("Error binding raw socket to interface");
+ close(sockfd);
+ return -1;
+ }
+
+ // Return the prepared socket
+ return sockfd;
+}
diff --git a/src/socket.h b/src/socket.h
@@ -0,0 +1,15 @@
+#ifndef __PMLAG_SOCKET_H__
+#define __PMLAG_SOCKET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sockraw_open(char * ifname);
+int iface_idx(int sockfd, char * ifname);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // __PMLAG_SOCKET_H__
diff --git a/test.ini b/test.ini
@@ -0,0 +1,23 @@
+; This is an example configuration, showcasing how you might configure multiple types of bonds
+
+; eth0 = backup, eth1 = primary
+[bond0]
+mode=active-backup
+interface=eth0
+weight=10
+interface=eth1
+weight=25
+
+; broadcast everything on all interfaces
+[bond1]
+mode=broadcast
+interface=eth2
+interface=eth3
+
+; use both at the same time
+[bond2]
+mode=balanced-rr
+interface=eth4
+weight=10
+interface=eth5
+weight=25