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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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);
|
||||
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
|
||||
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_dup(int s_src, unsigned int ifi_src,
|
||||
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) {
|
||||
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);
|
||||
if (rc < 0) {
|
||||
warn("Can't set nodad for LL in namespace: %s",
|
||||
|
|
Loading…
Reference in a new issue