From 71ed8fff9069326543d63c3623468be038610656 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 17 Sep 2024 19:24:17 +0700 Subject: [PATCH] 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 }, };