netlink, pasta: Fetch link-local address from namespace interface once it's up
As soon as we bring up the interface, the Linux kernel will set up a link-local address for it, so we can fetch it and start using right away, if we need a link-local address to communicate to the container before we see any traffic coming from it. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
74e508cf79
commit
d6f0220731
3 changed files with 55 additions and 0 deletions
47
netlink.c
47
netlink.c
|
@ -796,6 +796,53 @@ int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nl_addr_get_ll() - Get first IPv6 link-local address for a given interface
|
||||||
|
* @s: Netlink socket
|
||||||
|
* @ifi: Interface index in outer network namespace
|
||||||
|
* @addr: Link-local address to fill
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int nl_addr_get_ll(int s, unsigned int ifi, struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
struct req_t {
|
||||||
|
struct nlmsghdr nlh;
|
||||||
|
struct ifaddrmsg ifa;
|
||||||
|
} req = {
|
||||||
|
.ifa.ifa_family = AF_INET6,
|
||||||
|
.ifa.ifa_index = ifi,
|
||||||
|
};
|
||||||
|
struct nlmsghdr *nh;
|
||||||
|
bool found = false;
|
||||||
|
char buf[NLBUFSIZ];
|
||||||
|
ssize_t status;
|
||||||
|
uint32_t seq;
|
||||||
|
|
||||||
|
seq = nl_send(s, &req, RTM_GETADDR, NLM_F_DUMP, sizeof(req));
|
||||||
|
nl_foreach_oftype(nh, status, s, buf, seq, RTM_NEWADDR) {
|
||||||
|
struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
|
||||||
|
struct rtattr *rta;
|
||||||
|
size_t na;
|
||||||
|
|
||||||
|
if (ifa->ifa_index != ifi || ifa->ifa_scope != RT_SCOPE_LINK ||
|
||||||
|
found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rta = IFA_RTA(ifa), na = IFA_PAYLOAD(nh); RTA_OK(rta, na);
|
||||||
|
rta = RTA_NEXT(rta, na)) {
|
||||||
|
if (rta->rta_type != IFA_ADDRESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
memcpy(addr, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nl_add_set() - Set IP addresses for given interface and address family
|
* nl_add_set() - Set IP addresses for given interface and address family
|
||||||
* @s: Netlink socket
|
* @s: Netlink socket
|
||||||
|
|
|
@ -19,6 +19,7 @@ int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
|
||||||
void *addr, int *prefix_len, void *addr_l);
|
void *addr, int *prefix_len, void *addr_l);
|
||||||
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
|
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
|
||||||
const void *addr, int prefix_len);
|
const void *addr, int prefix_len);
|
||||||
|
int nl_addr_get_ll(int s, unsigned int ifi, struct in6_addr *addr);
|
||||||
int nl_addr_set_ll_nodad(int s, unsigned int ifi);
|
int nl_addr_set_ll_nodad(int s, unsigned int ifi);
|
||||||
int nl_addr_dup(int s_src, unsigned int ifi_src,
|
int nl_addr_dup(int s_src, unsigned int ifi_src,
|
||||||
int s_dst, unsigned int ifi_dst, sa_family_t af);
|
int s_dst, unsigned int ifi_dst, sa_family_t af);
|
||||||
|
|
7
pasta.c
7
pasta.c
|
@ -340,6 +340,13 @@ void pasta_ns_conf(struct ctx *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->ifi6) {
|
if (c->ifi6) {
|
||||||
|
rc = nl_addr_get_ll(nl_sock_ns, c->pasta_ifi,
|
||||||
|
&c->ip6.addr_ll_seen);
|
||||||
|
if (rc < 0) {
|
||||||
|
warn("Can't get LL address from namespace: %s",
|
||||||
|
strerror(-rc));
|
||||||
|
}
|
||||||
|
|
||||||
rc = nl_addr_set_ll_nodad(nl_sock_ns, c->pasta_ifi);
|
rc = nl_addr_set_ll_nodad(nl_sock_ns, c->pasta_ifi);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
warn("Can't set nodad for LL in namespace: %s",
|
warn("Can't set nodad for LL in namespace: %s",
|
||||||
|
|
Loading…
Reference in a new issue