aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--conf.c4
-rw-r--r--netlink.c141
-rw-r--r--netlink.h4
-rw-r--r--pasta.c12
4 files changed, 95 insertions, 66 deletions
diff --git a/conf.c b/conf.c
index a0622d2..8fa5322 100644
--- a/conf.c
+++ b/conf.c
@@ -671,7 +671,7 @@ static unsigned int conf_ip4(unsigned int ifi,
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
if (MAC_IS_ZERO(mac))
- nl_link(0, ifi, mac, 0, 0);
+ nl_link_get_mac(0, ifi, mac);
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr) ||
MAC_IS_ZERO(mac))
@@ -712,7 +712,7 @@ static unsigned int conf_ip6(unsigned int ifi,
memcpy(&ip6->addr_ll_seen, &ip6->addr_ll, sizeof(ip6->addr_ll));
if (MAC_IS_ZERO(mac))
- nl_link(0, ifi, mac, 0, 0);
+ nl_link_get_mac(0, ifi, mac);
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) ||
IN6_IS_ADDR_UNSPECIFIED(&ip6->addr_ll) ||
diff --git a/netlink.c b/netlink.c
index e15e23f..a41dc63 100644
--- a/netlink.c
+++ b/netlink.c
@@ -486,83 +486,44 @@ next:
}
/**
- * nl_link() - Get/set link attributes
+ * nl_link_get_mac() - Get link MAC address
* @ns: Use netlink socket in namespace
* @ifi: Interface index
- * @mac: MAC address to fill, if passed as zero, to set otherwise
- * @up: If set, bring up the link
- * @mtu: If non-zero, set interface MTU
+ * @mac: Fill with current MAC address
*/
-void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
+void nl_link_get_mac(int ns, unsigned int ifi, void *mac)
{
- int change = !MAC_IS_ZERO(mac) || up || mtu;
struct req_t {
struct nlmsghdr nlh;
struct ifinfomsg ifm;
- struct rtattr rta;
- union {
- unsigned char mac[ETH_ALEN];
- struct {
- unsigned int mtu;
- } mtu;
- } set;
} req = {
- .nlh.nlmsg_type = change ? RTM_NEWLINK : RTM_GETLINK,
- .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
- .nlh.nlmsg_flags = NLM_F_REQUEST | (change ? NLM_F_ACK : 0),
+ .nlh.nlmsg_type = RTM_GETLINK,
+ .nlh.nlmsg_len = sizeof(req),
+ .nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
.nlh.nlmsg_seq = nl_seq++,
.ifm.ifi_family = AF_UNSPEC,
.ifm.ifi_index = ifi,
- .ifm.ifi_flags = up ? IFF_UP : 0,
- .ifm.ifi_change = up ? IFF_UP : 0,
};
- struct ifinfomsg *ifm;
struct nlmsghdr *nh;
- struct rtattr *rta;
char buf[NLBUFSIZ];
ssize_t n;
- size_t na;
-
- if (!MAC_IS_ZERO(mac)) {
- req.nlh.nlmsg_len = sizeof(req);
- memcpy(req.set.mac, mac, ETH_ALEN);
- req.rta.rta_type = IFLA_ADDRESS;
- req.rta.rta_len = RTA_LENGTH(ETH_ALEN);
- if (nl_req(ns, buf, &req, req.nlh.nlmsg_len) < 0)
- return;
- up = 0;
- }
-
- if (mtu) {
- req.nlh.nlmsg_len = offsetof(struct req_t, set.mtu)
- + sizeof(req.set.mtu);
- req.set.mtu.mtu = mtu;
- req.rta.rta_type = IFLA_MTU;
- req.rta.rta_len = RTA_LENGTH(sizeof(unsigned int));
- if (nl_req(ns, buf, &req, req.nlh.nlmsg_len) < 0)
- return;
-
- up = 0;
- }
-
- if (up && nl_req(ns, buf, &req, req.nlh.nlmsg_len) < 0)
- return;
-
- if (change)
+ n = nl_req(ns, buf, &req, sizeof(req));
+ if (n < 0)
return;
- if ((n = nl_req(ns, buf, &req, req.nlh.nlmsg_len)) < 0)
- return;
+ for (nh = (struct nlmsghdr *)buf;
+ NLMSG_OK(nh, n) && nh->nlmsg_type != NLMSG_DONE;
+ nh = NLMSG_NEXT(nh, n)) {
+ struct ifinfomsg *ifm = (struct ifinfomsg *)NLMSG_DATA(nh);
+ struct rtattr *rta;
+ size_t na;
- nh = (struct nlmsghdr *)buf;
- for ( ; NLMSG_OK(nh, n); nh = NLMSG_NEXT(nh, n)) {
if (nh->nlmsg_type != RTM_NEWLINK)
- goto next;
-
- ifm = (struct ifinfomsg *)NLMSG_DATA(nh);
+ continue;
- for (rta = IFLA_RTA(ifm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
+ for (rta = IFLA_RTA(ifm), na = RTM_PAYLOAD(nh);
+ RTA_OK(rta, na);
rta = RTA_NEXT(rta, na)) {
if (rta->rta_type != IFLA_ADDRESS)
continue;
@@ -570,8 +531,70 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
memcpy(mac, RTA_DATA(rta), ETH_ALEN);
break;
}
-next:
- if (nh->nlmsg_type == NLMSG_DONE)
- break;
}
}
+
+/**
+ * nl_link_set_mac() - Set link MAC address
+ * @ns: Use netlink socket in namespace
+ * @ifi: Interface index
+ * @mac: MAC address to set
+ */
+void nl_link_set_mac(int ns, unsigned int ifi, void *mac)
+{
+ struct req_t {
+ struct nlmsghdr nlh;
+ struct ifinfomsg ifm;
+ struct rtattr rta;
+ unsigned char mac[ETH_ALEN];
+ } req = {
+ .nlh.nlmsg_type = RTM_NEWLINK,
+ .nlh.nlmsg_len = sizeof(req),
+ .nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+ .nlh.nlmsg_seq = nl_seq++,
+ .ifm.ifi_family = AF_UNSPEC,
+ .ifm.ifi_index = ifi,
+ .rta.rta_type = IFLA_ADDRESS,
+ .rta.rta_len = RTA_LENGTH(ETH_ALEN),
+ };
+ char buf[NLBUFSIZ];
+
+ memcpy(req.mac, mac, ETH_ALEN);
+
+ nl_req(ns, buf, &req, sizeof(req));
+}
+
+/**
+ * nl_link_up() - Bring link up
+ * @ns: Use netlink socket in namespace
+ * @ifi: Interface index
+ * @mtu: If non-zero, set interface MTU
+ */
+void nl_link_up(int ns, unsigned int ifi, int mtu)
+{
+ struct req_t {
+ struct nlmsghdr nlh;
+ struct ifinfomsg ifm;
+ struct rtattr rta;
+ unsigned int mtu;
+ } req = {
+ .nlh.nlmsg_type = RTM_NEWLINK,
+ .nlh.nlmsg_len = sizeof(req),
+ .nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+ .nlh.nlmsg_seq = nl_seq++,
+ .ifm.ifi_family = AF_UNSPEC,
+ .ifm.ifi_index = ifi,
+ .ifm.ifi_flags = IFF_UP,
+ .ifm.ifi_change = IFF_UP,
+ .rta.rta_type = IFLA_MTU,
+ .rta.rta_len = RTA_LENGTH(sizeof(unsigned int)),
+ .mtu = mtu,
+ };
+ char buf[NLBUFSIZ];
+
+ if (!mtu)
+ /* Shorten request to drop MTU attribute */
+ req.nlh.nlmsg_len = offsetof(struct req_t, rta);
+
+ nl_req(ns, buf, &req, req.nlh.nlmsg_len);
+}
diff --git a/netlink.h b/netlink.h
index cd0e666..980ac44 100644
--- a/netlink.h
+++ b/netlink.h
@@ -18,6 +18,8 @@ void nl_route(enum nl_op op, unsigned int ifi, unsigned int ifi_ns,
sa_family_t af, void *gw);
void nl_addr(enum nl_op op, unsigned int ifi, unsigned int ifi_ns,
sa_family_t af, void *addr, int *prefix_len, void *addr_l);
-void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu);
+void nl_link_get_mac(int ns, unsigned int ifi, void *mac);
+void nl_link_set_mac(int ns, unsigned int ifi, void *mac);
+void nl_link_up(int ns, unsigned int ifi, int mtu);
#endif /* NETLINK_H */
diff --git a/pasta.c b/pasta.c
index 8c85546..cb509dd 100644
--- a/pasta.c
+++ b/pasta.c
@@ -272,13 +272,19 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
*/
void pasta_ns_conf(struct ctx *c)
{
- nl_link(1, 1 /* lo */, MAC_ZERO, 1, 0);
+ nl_link_up(1, 1 /* lo */, 0);
+
+ /* Get or set MAC in target namespace */
+ if (MAC_IS_ZERO(c->mac_guest))
+ nl_link_get_mac(1, c->pasta_ifi, c->mac_guest);
+ else
+ nl_link_set_mac(1, c->pasta_ifi, c->mac_guest);
if (c->pasta_conf_ns) {
enum nl_op op_routes = c->no_copy_routes ? NL_SET : NL_DUP;
enum nl_op op_addrs = c->no_copy_addrs ? NL_SET : NL_DUP;
- nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu);
+ nl_link_up(1, c->pasta_ifi, c->mtu);
if (c->ifi4) {
nl_addr(op_addrs, c->ifi4, c->pasta_ifi, AF_INET,
@@ -294,8 +300,6 @@ void pasta_ns_conf(struct ctx *c)
nl_route(op_routes, c->ifi6, c->pasta_ifi, AF_INET6,
&c->ip6.gw);
}
- } else {
- nl_link(1, c->pasta_ifi, c->mac_guest, 0, 0);
}
proto_update_l2_buf(c->mac_guest, NULL, NULL);