From 71ed8fff9069326543d63c3623468be038610656 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 19:24:17 +0700 Subject: [PATCH 1/5] Support to set a MAC address on an interface (Linux only) --- README.md | 10 +++++++++- src/hypervisor_docker.c | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 473983c..32a3438 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ The modules that are currently defined are given below: - hypervisor : General hypervisor management - bridge : bridges management - iol_bridge : IOL (IOS on Linux) bridges management -- docker : Docker veth management +- docker : Docker management - brctl : Linux bridge management ### Hypervisor module ("hypervisor") @@ -414,6 +414,14 @@ docker move_to_ns guestif 6367 eth0 100-guestif moved to namespace 6367 ``` +- **docker set_mac_addr** *\* *\* + *\*: Set a MAC address on an interface. + +``` {.bash} +docker set_mac_addr tap-gns3-e0 12:34:56:78:12:42 +100-MAC address 12:34:56:78:12:42" has been successfully set on interface tap-gns3-e0 +``` + - **docker delete_veth** *\*: Delete virtual Ethernet interface. diff --git a/src/hypervisor_docker.c b/src/hypervisor_docker.c index 16d3dc1..79065ff 100644 --- a/src/hypervisor_docker.c +++ b/src/hypervisor_docker.c @@ -308,11 +308,53 @@ static int cmd_move_ns(hypervisor_conn_t *conn, int argc, char *argv[]) return err; } +static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) +{ + int fd; + struct ifreq ifr; + char *interface = argv[0]; + char mac_char[17]; + + if (strlen(argv[1]) != 17) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "invalid MAC address format"); + return (-1); + } + + strncpy(mac_char, argv[1], 17); + sscanf(mac_char, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &ifr.ifr_hwaddr.sa_data[0], + &ifr.ifr_hwaddr.sa_data[1], + &ifr.ifr_hwaddr.sa_data[2], + &ifr.ifr_hwaddr.sa_data[3], + &ifr.ifr_hwaddr.sa_data[4], + &ifr.ifr_hwaddr.sa_data[5] + ); + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "could not create socket: %s", strerror(errno)); + return (-1); + } + + strncpy(ifr.ifr_name, interface, strlen(interface)); + ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; + + if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "could not set a MAC address on interface %s", interface); + close(fd); + return (-1); + } + + hypervisor_send_reply(conn, HSC_INFO_OK, 1, "MAC address %s has been successfully set on interface %s", mac_char, interface); + close(fd); + return (0); +} + /* Docker commands */ static hypervisor_cmd_t docker_cmd_array[] = { { "create_veth", 2, 2, cmd_create_veth_pair, NULL }, { "delete_veth", 1, 1, cmd_delete_veth, NULL }, { "move_to_ns", 3, 3, cmd_move_ns, NULL }, + { "set_mac_addr", 2, 2, cmd_set_mac_addr, NULL }, { NULL, -1, -1, NULL, NULL }, }; From f6c6af13f4df1265c28a4dce38726fb9a4a5d30b Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 21:35:29 +0700 Subject: [PATCH 2/5] MAC address validation --- src/hypervisor_docker.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/hypervisor_docker.c b/src/hypervisor_docker.c index 79065ff..3337f95 100644 --- a/src/hypervisor_docker.c +++ b/src/hypervisor_docker.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "ubridge.h" #include "hypervisor.h" @@ -313,14 +314,23 @@ static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) int fd; struct ifreq ifr; char *interface = argv[0]; - char mac_char[17]; + char mac_char[18]; + regex_t regex; - if (strlen(argv[1]) != 17) { + if (regcomp(®ex, "^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$", REG_EXTENDED)) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "could not compile regex"); + return (-1); + } + + if (regexec(®ex, argv[1], 0, NULL, 0)) { hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "invalid MAC address format"); + regfree(®ex); return (-1); } + regfree(®ex); strncpy(mac_char, argv[1], 17); + mac_char[17] = '\0'; sscanf(mac_char, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &ifr.ifr_hwaddr.sa_data[0], &ifr.ifr_hwaddr.sa_data[1], @@ -335,7 +345,8 @@ static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) return (-1); } - strncpy(ifr.ifr_name, interface, strlen(interface)); + strncpy(ifr.ifr_name, interface, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { From 2f5cc1b3cb018f2e2223254aea7d60713639d844 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 21:37:27 +0700 Subject: [PATCH 3/5] Switch to xcode "14.2.0" --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 67e1d7f..8ded714 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build: macos: - xcode: "12.5.1" + xcode: "14.2.0" steps: - checkout From 7a8b011cec7d68540b86d5a2169eda19d72ecce8 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 22:21:15 +0700 Subject: [PATCH 4/5] Validate interface name is not too long --- src/hypervisor_docker.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hypervisor_docker.c b/src/hypervisor_docker.c index 3337f95..1df824d 100644 --- a/src/hypervisor_docker.c +++ b/src/hypervisor_docker.c @@ -313,10 +313,15 @@ static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) { int fd; struct ifreq ifr; - char *interface = argv[0]; - char mac_char[18]; + char *interface = argv[0]; + char mac_char[18]; regex_t regex; + if (strlen(interface) >= IFNAMSIZ) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "interface name is too long"); + return (-1); + } + if (regcomp(®ex, "^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$", REG_EXTENDED)) { hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "could not compile regex"); return (-1); @@ -346,7 +351,6 @@ static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) } strncpy(ifr.ifr_name, interface, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = '\0'; ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { From dedea93534e0793086f77dc59b129642c39ece48 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 22:22:19 +0700 Subject: [PATCH 5/5] Fix indentation --- src/hypervisor_docker.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hypervisor_docker.c b/src/hypervisor_docker.c index 1df824d..be9d50c 100644 --- a/src/hypervisor_docker.c +++ b/src/hypervisor_docker.c @@ -317,10 +317,10 @@ static int cmd_set_mac_addr(hypervisor_conn_t *conn, int argc, char *argv[]) char mac_char[18]; regex_t regex; - if (strlen(interface) >= IFNAMSIZ) { - hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "interface name is too long"); - return (-1); - } + if (strlen(interface) >= IFNAMSIZ) { + hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "interface name is too long"); + return (-1); + } if (regcomp(®ex, "^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$", REG_EXTENDED)) { hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "could not compile regex");