Skip to content

Commit

Permalink
Merge pull request #94 from GNS3/docker-set-mac-addr
Browse files Browse the repository at this point in the history
Support to set a MAC address on an interface
  • Loading branch information
grossmj authored Sep 18, 2024
2 parents 3d430a6 + dedea93 commit 2f7798c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2.1
jobs:
build:
macos:
xcode: "12.5.1"
xcode: "14.2.0"

steps:
- checkout
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -414,6 +414,14 @@ docker move_to_ns guestif 6367 eth0
100-guestif moved to namespace 6367
```

- **docker set_mac_addr** *\<interface\>* *\<mac_addr\>*
*\<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** *\<interface_name\>*: Delete virtual
Ethernet interface.

Expand Down
57 changes: 57 additions & 0 deletions src/hypervisor_docker.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <linux/if_bridge.h>
#include <sched.h>
#include <linux/ethtool.h>
#include <regex.h>

#include "ubridge.h"
#include "hypervisor.h"
Expand Down Expand Up @@ -308,11 +309,67 @@ 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[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(&regex, "^([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(&regex, argv[1], 0, NULL, 0)) {
hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "invalid MAC address format");
regfree(&regex);
return (-1);
}
regfree(&regex);

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],
&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, IFNAMSIZ);
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 },
};

Expand Down

0 comments on commit 2f7798c

Please sign in to comment.