netlink: automatically generate broadcast for IPv4 ifa if not set.
MFC after: 2 weeks
This commit is contained in:
parent
a72b78905a
commit
7eee0eaf16
@ -1096,13 +1096,14 @@ static int
|
||||
handle_newaddr_inet(struct nlmsghdr *hdr, struct nl_parsed_ifa *attrs,
|
||||
struct ifnet *ifp, struct nlpcb *nlp, struct nl_pstate *npt)
|
||||
{
|
||||
if (attrs->ifa_prefixlen > 32) {
|
||||
int plen = attrs->ifa_prefixlen;
|
||||
int if_flags = if_getflags(ifp);
|
||||
|
||||
if (plen > 32) {
|
||||
nlmsg_report_err_msg(npt, "invalid ifa_prefixlen");
|
||||
return (EINVAL);
|
||||
};
|
||||
|
||||
int if_flags = if_getflags(ifp);
|
||||
|
||||
if (if_flags & IFF_POINTOPOINT) {
|
||||
if (attrs->ifa_addr == NULL || attrs->ifa_dst == NULL) {
|
||||
nlmsg_report_err_msg(npt, "Empty IFA_LOCAL/IFA_ADDRESS");
|
||||
@ -1115,13 +1116,32 @@ handle_newaddr_inet(struct nlmsghdr *hdr, struct nl_parsed_ifa *attrs,
|
||||
}
|
||||
attrs->ifa_dst = attrs->ifa_broadcast;
|
||||
|
||||
if (attrs->ifa_dst == NULL && !(if_flags & IFF_LOOPBACK)) {
|
||||
nlmsg_report_err_msg(npt, "empty IFA_BROADCAST for BRD interface");
|
||||
return (EINVAL);
|
||||
/* Generate broadcast address if not set */
|
||||
if ((if_flags & IFF_BROADCAST) && attrs->ifa_dst == NULL) {
|
||||
uint32_t s_baddr;
|
||||
struct sockaddr_in *sin_brd;
|
||||
|
||||
if (plen == 31)
|
||||
s_baddr = INADDR_BROADCAST; /* RFC 3021 */
|
||||
else {
|
||||
struct sockaddr_in *addr;
|
||||
uint32_t s_mask;
|
||||
|
||||
addr = (struct sockaddr_in *)attrs->ifa_addr;
|
||||
s_mask = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0);
|
||||
s_baddr = addr->sin_addr.s_addr | ~s_mask;
|
||||
}
|
||||
|
||||
sin_brd = (struct sockaddr_in *)npt_alloc(npt, sizeof(*sin_brd));
|
||||
if (sin_brd == NULL)
|
||||
return (ENOMEM);
|
||||
sin_brd->sin_family = AF_INET;
|
||||
sin_brd->sin_len = sizeof(*sin_brd);
|
||||
sin_brd->sin_addr.s_addr = s_baddr;
|
||||
attrs->ifa_dst = (struct sockaddr *)sin_brd;
|
||||
}
|
||||
}
|
||||
|
||||
int plen = attrs->ifa_prefixlen;
|
||||
struct sockaddr_in mask = {
|
||||
.sin_len = sizeof(struct sockaddr_in),
|
||||
.sin_family = AF_INET,
|
||||
|
@ -254,6 +254,41 @@ def test_add_4(self):
|
||||
assert rx_msg.get_nla(IfaAttrType.IFA_LOCAL).addr == str(ifa.ip)
|
||||
assert rx_msg.get_nla(IfaAttrType.IFA_BROADCAST).addr == str(ifa_brd)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"brd",
|
||||
[
|
||||
pytest.param((32, True, "192.0.2.1"), id="auto_32"),
|
||||
pytest.param((31, True, "255.255.255.255"), id="auto_31"),
|
||||
pytest.param((30, True, "192.0.2.3"), id="auto_30"),
|
||||
pytest.param((30, False, "192.0.2.2"), id="custom_30"),
|
||||
pytest.param((24, False, "192.0.2.7"), id="custom_24"),
|
||||
],
|
||||
)
|
||||
def test_add_4_brd(self, brd):
|
||||
"""Tests proper broadcast setup when adding IPv4 ifa"""
|
||||
plen, auto_brd, ifa_brd_str = brd
|
||||
ifa = ipaddress.ip_interface("192.0.2.1/{}".format(plen))
|
||||
iface = self.vnet.iface_alias_map["if1"]
|
||||
ifa_brd = ipaddress.ip_address(ifa_brd_str)
|
||||
|
||||
msg = self.create_msg(ifa)
|
||||
msg.add_nla(NlAttrIp(IfaAttrType.IFA_LOCAL, str(ifa.ip)))
|
||||
if not auto_brd:
|
||||
msg.add_nla(NlAttrIp(IfaAttrType.IFA_BROADCAST, str(ifa_brd)))
|
||||
|
||||
self.send_check_success(msg)
|
||||
|
||||
lst = self.get_ifa_list(iface.ifindex, self.get_family_from_ip(ifa.ip))
|
||||
assert len(lst) == 1
|
||||
rx_msg = lst[0]
|
||||
|
||||
assert rx_msg.base_hdr.ifa_prefixlen == ifa.network.prefixlen
|
||||
assert rx_msg.base_hdr.ifa_scope == RtScope.RT_SCOPE_UNIVERSE.value
|
||||
|
||||
assert rx_msg.get_nla(IfaAttrType.IFA_ADDRESS).addr == str(ifa.ip)
|
||||
assert rx_msg.get_nla(IfaAttrType.IFA_LOCAL).addr == str(ifa.ip)
|
||||
assert rx_msg.get_nla(IfaAttrType.IFA_BROADCAST).addr == str(ifa_brd)
|
||||
|
||||
def test_add_6(self):
|
||||
ifa = ipaddress.ip_interface("2001:db8::1/64")
|
||||
iface = self.vnet.iface_alias_map["if1"]
|
||||
|
Loading…
Reference in New Issue
Block a user