Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149241465
D37970.id114845.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D37970.id114845.diff
View Options
diff --git a/share/man/man4/rtnetlink.4 b/share/man/man4/rtnetlink.4
--- a/share/man/man4/rtnetlink.4
+++ b/share/man/man4/rtnetlink.4
@@ -403,14 +403,27 @@
.Ss RTM_DELADDR
Not supported
.Ss RTM_GETADDR
+Fetches interface addresses in the current VNET matching conditions.
+Each address is reported as a
+.Dv RTM_NEWADDR
+message.
+The following filters are recognised by the kernel:
+.Pp
+.Bd -literal -offset indent -compact
+ifa_family required family or AF_UNSPEC
+ifa_index matching interface index or 0
+.Ed
.Ss TLVs
.Bl -tag -width indent
.It Dv IFA_ADDRESS
(binary) masked interface address or destination address for p2p interfaces.
.It Dv IFA_LOCAL
-(binary) local interface address
+(binary) local interface address.
+Set for IPv4 and p2p addresses.
+.It Dv IFA_LABEL
+(string) interface name.
.It Dv IFA_BROADCAST
-(binary) broacast interface address
+(binary) broacast interface address.
.El
.Ss Groups
The following groups are defined:
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -672,6 +672,36 @@
return (modify_link(hdr, &attrs, &bm, nlp, npt));
}
+struct nl_parsed_ifa {
+ uint8_t ifa_family;
+ uint8_t ifa_prefixlen;
+ uint8_t ifa_scope;
+ uint32_t ifa_index;
+ uint32_t ifa_flags;
+ struct sockaddr *ifa_address;
+ struct sockaddr *ifa_local;
+};
+
+#define _IN(_field) offsetof(struct ifaddrmsg, _field)
+#define _OUT(_field) offsetof(struct nl_parsed_ifa, _field)
+static const struct nlfield_parser nlf_p_ifa[] = {
+ { .off_in = _IN(ifa_family), .off_out = _OUT(ifa_family), .cb = nlf_get_u8 },
+ { .off_in = _IN(ifa_prefixlen), .off_out = _OUT(ifa_prefixlen), .cb = nlf_get_u8 },
+ { .off_in = _IN(ifa_scope), .off_out = _OUT(ifa_scope), .cb = nlf_get_u8 },
+ { .off_in = _IN(ifa_flags), .off_out = _OUT(ifa_flags), .cb = nlf_get_u8_u32 },
+ { .off_in = _IN(ifa_index), .off_out = _OUT(ifa_index), .cb = nlf_get_u32 },
+};
+
+static const struct nlattr_parser nla_p_ifa[] = {
+ { .type = IFA_ADDRESS, .off = _OUT(ifa_address), .cb = nlattr_get_ip },
+ { .type = IFA_LOCAL, .off = _OUT(ifa_local), .cb = nlattr_get_ip },
+ { .type = IFA_FLAGS, .off = _OUT(ifa_flags), .cb = nlattr_get_uint32 },
+};
+#undef _IN
+#undef _OUT
+NL_DECLARE_PARSER(ifaddrmsg_parser, struct ifaddrmsg, nlf_p_ifa, nla_p_ifa);
+
+
/*
{ifa_family=AF_INET, ifa_prefixlen=8, ifa_flags=IFA_F_PERMANENT, ifa_scope=RT_SCOPE_HOST, ifa_index=if_nametoindex("lo")},
@@ -826,15 +856,39 @@
}
static int
-rtnl_handle_getaddr(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt)
+dump_iface_addrs(struct netlink_walkargs *wa, struct ifnet *ifp)
{
struct ifaddr *ifa;
+
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (wa->family != 0 && wa->family != ifa->ifa_addr->sa_family)
+ continue;
+ if (ifa->ifa_addr->sa_family == AF_LINK)
+ continue;
+ wa->count++;
+ if (!dump_iface_addr(wa->nw, ifp, ifa, &wa->hdr))
+ return (ENOMEM);
+ wa->dumped++;
+ }
+
+ return (0);
+}
+
+static int
+rtnl_handle_getaddr(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt)
+{
struct ifnet *ifp;
int error = 0;
+ struct nl_parsed_ifa attrs = {};
+ error = nl_parse_nlmsg(hdr, &ifaddrmsg_parser, npt, &attrs);
+ if (error != 0)
+ return (error);
+
struct netlink_walkargs wa = {
.so = nlp,
.nw = npt->nw,
+ .family = attrs.ifa_family,
.hdr.nlmsg_pid = hdr->nlmsg_pid,
.hdr.nlmsg_seq = hdr->nlmsg_seq,
.hdr.nlmsg_flags = hdr->nlmsg_flags | NLM_F_MULTI,
@@ -843,22 +897,19 @@
NL_LOG(LOG_DEBUG2, "Start dump");
- CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (wa.family != 0 && wa.family != ifa->ifa_addr->sa_family)
- continue;
- if (ifa->ifa_addr->sa_family == AF_LINK)
- continue;
- wa.count++;
- if (!dump_iface_addr(wa.nw, ifp, ifa, &wa.hdr)) {
- error = ENOMEM;
- break;
- }
- wa.dumped++;
- }
- if (error != 0)
- break;
- }
+ if (attrs.ifa_index != 0) {
+ ifp = ifnet_byindex(attrs.ifa_index);
+ if (ifp == NULL)
+ error = ENOENT;
+ else
+ error = dump_iface_addrs(&wa, ifp);
+ } else {
+ CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ error = dump_iface_addrs(&wa, ifp);
+ if (error != 0)
+ break;
+ }
+ }
NL_LOG(LOG_DEBUG2, "End dump, iterated %d dumped %d", wa.count, wa.dumped);
@@ -991,7 +1042,7 @@
},
};
-static const struct nlhdr_parser *all_parsers[] = { &ifmsg_parser };
+static const struct nlhdr_parser *all_parsers[] = { &ifmsg_parser, &ifaddrmsg_parser };
void
rtnl_iface_add_cloner(struct nl_cloner *cloner)
diff --git a/sys/netlink/route/ifaddrs.h b/sys/netlink/route/ifaddrs.h
--- a/sys/netlink/route/ifaddrs.h
+++ b/sys/netlink/route/ifaddrs.h
@@ -52,7 +52,7 @@
IFA_UNSPEC,
IFA_ADDRESS = 1, /* binary, prefix address (destination for p2p) */
IFA_LOCAL = 2, /* binary, interface address */
- IFA_LABEL = 3, /* not supported */
+ IFA_LABEL = 3, /* string, interface name */
IFA_BROADCAST = 4, /* binary, broadcast ifa */
IFA_ANYCAST = 5, /* not supported */
IFA_CACHEINFO = 6, /* not supported */
diff --git a/tests/atf_python/sys/net/netlink.py b/tests/atf_python/sys/net/netlink.py
--- a/tests/atf_python/sys/net/netlink.py
+++ b/tests/atf_python/sys/net/netlink.py
@@ -49,6 +49,12 @@
]
+class Nlmsgdone(Structure):
+ _fields_ = [
+ ("error", c_int),
+ ]
+
+
class Nlmsgerr(Structure):
_fields_ = [
("error", c_int),
@@ -961,6 +967,8 @@
),
]
+nldone_attrs = []
+
nlerr_attrs = [
AttrDescr(NlErrattrType.NLMSGERR_ATTR_MSG, NlAttrStr),
AttrDescr(NlErrattrType.NLMSGERR_ATTR_OFFS, NlAttrU32),
@@ -989,6 +997,7 @@
rtnl_ifa_attrs = [
AttrDescr(IfattrType.IFA_ADDRESS, NlAttrIp),
AttrDescr(IfattrType.IFA_LOCAL, NlAttrIp),
+ AttrDescr(IfattrType.IFA_LABEL, NlAttrStr),
AttrDescr(IfattrType.IFA_BROADCAST, NlAttrIp),
AttrDescr(IfattrType.IFA_ANYCAST, NlAttrIp),
AttrDescr(IfattrType.IFA_FLAGS, NlAttrU32),
@@ -1167,6 +1176,25 @@
nla.print_attr(" ")
+class NetlinkDoneMessage(StdNetlinkMessage):
+ messages = [NlMsgType.NLMSG_DONE.value]
+ nl_attrs_map = prepare_attrs_map(nldone_attrs)
+
+ @property
+ def error_code(self):
+ return self.base_hdr.error
+
+ def parse_base_header(self, data):
+ if len(data) < sizeof(Nlmsgdone):
+ raise ValueError("length less than nlmsgdone header")
+ done_hdr = Nlmsgdone.from_buffer_copy(data)
+ sz = sizeof(Nlmsgdone)
+ return (done_hdr, sz)
+
+ def print_base_header(self, hdr, prepend=""):
+ print("{}error={}".format(prepend, hdr.error))
+
+
class NetlinkErrorMessage(StdNetlinkMessage):
messages = [NlMsgType.NLMSG_ERROR.value]
nl_attrs_map = prepare_attrs_map(nlerr_attrs)
@@ -1340,6 +1368,7 @@
NetlinkRtMessage,
NetlinkIflaMessage,
NetlinkIfaMessage,
+ NetlinkDoneMessage,
NetlinkErrorMessage,
]
xmap = {}
@@ -1476,20 +1505,63 @@
self.write_data(msg_bytes)
-def main():
- helper = NlHelper()
- if False:
- nl = Nlsock(NlConst.NETLINK_GENERIC, helper)
- nl.request_families()
- else:
- nl = Nlsock(NlConst.NETLINK_ROUTE, helper)
- # nl.request_ifaddrs(socket.AF_INET)
- # nl.request_raw()
- nl.request_routes(0)
- # nl.request_ifaces()
- while True:
- msg = nl.read_message()
+class NetlinkMultipartIterator(object):
+ def __init__(self, obj, seq_number: int, msg_type):
+ self._obj = obj
+ self._seq = seq_number
+ self._msg_type = msg_type
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ msg = self._obj.read_message()
+ if self._seq != msg.nl_hdr.nlmsg_seq:
+ raise ValueError("bad sequence number")
+ if msg.is_type(NlMsgType.NLMSG_ERROR):
+ raise ValueError(
+ "error while handling multipart msg: {}".format(msg.error_code)
+ )
+ elif msg.is_type(NlMsgType.NLMSG_DONE):
+ if msg.error_code == 0:
+ raise StopIteration
+ raise ValueError(
+ "error listing some parts of the multipart msg: {}".format(
+ msg.error_code
+ )
+ )
+ elif not msg.is_type(self._msg_type):
+ raise ValueError("bad message type: {}".format(msg))
+ return msg
+
+
+class NetlinkTestTemplate(object):
+ REQUIRED_MODULES = ["netlink"]
+
+ def setup_netlink(self, netlink_family: NlConst):
+ self.helper = NlHelper()
+ self.nlsock = Nlsock(netlink_family, self.helper)
+
+ def write_message(self, msg):
print("")
+ print("============= >> TX MESSAGE =============")
msg.print_message()
- msg.print_as_bytes(msg._orig_data, "-- DATA --")
- pass
+ self.nlsock.write_data(bytes(msg))
+ msg.print_as_bytes(bytes(msg), "-- DATA --")
+
+ def read_message(self):
+ msg = self.nlsock.read_message()
+ print("")
+ print("============= << RX MESSAGE =============")
+ msg.print_message()
+ return msg
+
+ def get_reply(self, tx_msg):
+ self.write_message(tx_msg)
+ while True:
+ rx_msg = self.read_message()
+ if tx_msg.nl_hdr.nlmsg_seq == rx_msg.nl_hdr.nlmsg_seq:
+ return rx_msg
+
+ def read_msg_list(self, seq, msg_type):
+ return list(NetlinkMultipartIterator(self, seq, msg_type))
diff --git a/tests/sys/netlink/Makefile b/tests/sys/netlink/Makefile
--- a/tests/sys/netlink/Makefile
+++ b/tests/sys/netlink/Makefile
@@ -7,6 +7,7 @@
ATF_TESTS_C += test_snl
ATF_TESTS_PYTEST += test_rtnl_iface.py
+ATF_TESTS_PYTEST += test_rtnl_ifaddr.py
CFLAGS+= -I${.CURDIR:H:H:H}
diff --git a/tests/sys/netlink/test_rtnl_iface.py b/tests/sys/netlink/test_rtnl_iface.py
--- a/tests/sys/netlink/test_rtnl_iface.py
+++ b/tests/sys/netlink/test_rtnl_iface.py
@@ -6,49 +6,24 @@
from atf_python.sys.net.netlink import IflinkInfo
from atf_python.sys.net.netlink import IfLinkInfoDataVlan
from atf_python.sys.net.netlink import NetlinkIflaMessage
+from atf_python.sys.net.netlink import NetlinkTestTemplate
from atf_python.sys.net.netlink import NlAttrNested
from atf_python.sys.net.netlink import NlAttrStr
from atf_python.sys.net.netlink import NlAttrStrn
from atf_python.sys.net.netlink import NlAttrU16
from atf_python.sys.net.netlink import NlAttrU32
from atf_python.sys.net.netlink import NlConst
-from atf_python.sys.net.netlink import NlHelper
from atf_python.sys.net.netlink import NlmBaseFlags
from atf_python.sys.net.netlink import NlmNewFlags
from atf_python.sys.net.netlink import NlMsgType
from atf_python.sys.net.netlink import NlRtMsgType
-from atf_python.sys.net.netlink import Nlsock
from atf_python.sys.net.vnet import SingleVnetTestTemplate
-class TestRtNlIface(SingleVnetTestTemplate):
- REQUIRED_MODULES = ["netlink"]
-
+class TestRtNlIface(SingleVnetTestTemplate, NetlinkTestTemplate):
def setup_method(self, method):
super().setup_method(method)
- self.helper = NlHelper()
- self.nlsock = Nlsock(NlConst.NETLINK_ROUTE, self.helper)
-
- def write_message(self, msg):
- print("")
- print("============= >> TX MESSAGE =============")
- msg.print_message()
- self.nlsock.write_data(bytes(msg))
- msg.print_as_bytes(bytes(msg), "-- DATA --")
-
- def read_message(self):
- msg = self.nlsock.read_message()
- print("")
- print("============= << RX MESSAGE =============")
- msg.print_message()
- return msg
-
- def get_reply(self, tx_msg):
- self.write_message(tx_msg)
- while True:
- rx_msg = self.read_message()
- if tx_msg.nl_hdr.nlmsg_seq == rx_msg.nl_hdr.nlmsg_seq:
- return rx_msg
+ self.setup_netlink(NlConst.NETLINK_ROUTE)
def get_interface_byname(self, ifname):
msg = NetlinkIflaMessage(self.helper, NlRtMsgType.RTM_GETLINK.value)
@@ -236,13 +211,11 @@
# *
# * {len=76, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1662892737, pid=0},
# * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0},
- # * [
# * {{nla_len=8, nla_type=IFLA_LINK}, 2},
# * {{nla_len=12, nla_type=IFLA_IFNAME}, "xvlan22"},
# * {{nla_len=24, nla_type=IFLA_LINKINFO},
- # * [
# * {{nla_len=8, nla_type=IFLA_INFO_KIND}, "vlan"...},
- # * {{nla_len=12, nla_type=IFLA_INFO_DATA}, "\x06\x00\x01\x00\x16\x00\x00\x00"}]}]}, iov_len=76}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 76
+ # * {{nla_len=12, nla_type=IFLA_INFO_DATA}, "\x06\x00\x01\x00\x16\x00\x00\x00"}
# */
@pytest.mark.skip(reason="vlan support needs more work")
@pytest.mark.require_user("root")
diff --git a/tests/sys/netlink/test_rtnl_ifaddr.py b/tests/sys/netlink/test_rtnl_ifaddr.py
new file mode 100644
--- /dev/null
+++ b/tests/sys/netlink/test_rtnl_ifaddr.py
@@ -0,0 +1,144 @@
+import ipaddress
+import socket
+import struct
+
+from atf_python.sys.net.netlink import IfattrType
+from atf_python.sys.net.netlink import NetlinkIfaMessage
+from atf_python.sys.net.netlink import NetlinkTestTemplate
+from atf_python.sys.net.netlink import NlConst
+from atf_python.sys.net.netlink import NlHelper
+from atf_python.sys.net.netlink import NlmBaseFlags
+from atf_python.sys.net.netlink import NlMsgType
+from atf_python.sys.net.netlink import NlRtMsgType
+from atf_python.sys.net.netlink import Nlsock
+from atf_python.sys.net.netlink import RtScope
+from atf_python.sys.net.vnet import SingleVnetTestTemplate
+
+
+class TestRtNlIfaddr(SingleVnetTestTemplate, NetlinkTestTemplate):
+ def setup_method(self, method):
+ method_name = method.__name__
+ if "4" in method_name:
+ self.IPV4_PREFIXES = ["192.0.2.1/24"]
+ if "6" in method_name:
+ self.IPV6_PREFIXES = ["2001:db8::1/64"]
+ super().setup_method(method)
+ self.setup_netlink(NlConst.NETLINK_ROUTE)
+
+ def test_46_nofilter(self):
+ """Tests that listing outputs both IPv4/IPv6 and interfaces"""
+ msg = NetlinkIfaMessage(self.helper, NlRtMsgType.RTM_GETADDR.value)
+ msg.nl_hdr.nlmsg_flags = (
+ NlmBaseFlags.NLM_F_ACK.value | NlmBaseFlags.NLM_F_REQUEST.value
+ )
+ self.write_message(msg)
+
+ ret = []
+ for rx_msg in self.read_msg_list(msg.nl_hdr.nlmsg_seq, NlRtMsgType.RTM_NEWADDR):
+ ifname = socket.if_indextoname(rx_msg.base_hdr.ifa_index)
+ family = rx_msg.base_hdr.ifa_family
+ ret.append((ifname, family, rx_msg))
+
+ ifname = "lo0"
+ assert len([r for r in ret if r[0] == ifname]) > 0
+
+ ifname = self.vnet.iface_alias_map["if1"].name
+ assert len([r for r in ret if r[0] == ifname and r[1] == socket.AF_INET]) == 1
+ assert len([r for r in ret if r[0] == ifname and r[1] == socket.AF_INET6]) == 2
+
+ def test_46_filter_iface(self):
+ """Tests that listing outputs both IPv4/IPv6 for the specific interface"""
+ epair_ifname = self.vnet.iface_alias_map["if1"].name
+
+ msg = NetlinkIfaMessage(self.helper, NlRtMsgType.RTM_GETADDR.value)
+ msg.nl_hdr.nlmsg_flags = (
+ NlmBaseFlags.NLM_F_ACK.value | NlmBaseFlags.NLM_F_REQUEST.value
+ )
+ msg.base_hdr.ifa_index = socket.if_nametoindex(epair_ifname)
+ self.write_message(msg)
+
+ ret = []
+ for rx_msg in self.read_msg_list(msg.nl_hdr.nlmsg_seq, NlRtMsgType.RTM_NEWADDR):
+ ifname = socket.if_indextoname(rx_msg.base_hdr.ifa_index)
+ family = rx_msg.base_hdr.ifa_family
+ ret.append((ifname, family, rx_msg))
+
+ ifname = epair_ifname
+ assert len([r for r in ret if r[0] == ifname and r[1] == socket.AF_INET]) == 1
+ assert len([r for r in ret if r[0] == ifname and r[1] == socket.AF_INET6]) == 2
+ assert len(ret) == 3
+
+ def filter_iface_family(self, family, num_items):
+ """Tests that listing outputs IPv4 for the specific interface"""
+ epair_ifname = self.vnet.iface_alias_map["if1"].name
+
+ msg = NetlinkIfaMessage(self.helper, NlRtMsgType.RTM_GETADDR.value)
+ msg.nl_hdr.nlmsg_flags = (
+ NlmBaseFlags.NLM_F_ACK.value | NlmBaseFlags.NLM_F_REQUEST.value
+ )
+ msg.base_hdr.ifa_family = family
+ msg.base_hdr.ifa_index = socket.if_nametoindex(epair_ifname)
+ self.write_message(msg)
+
+ ret = []
+ for rx_msg in self.read_msg_list(msg.nl_hdr.nlmsg_seq, NlRtMsgType.RTM_NEWADDR):
+ assert family == rx_msg.base_hdr.ifa_family
+ assert epair_ifname == socket.if_indextoname(rx_msg.base_hdr.ifa_index)
+ ret.append(rx_msg)
+ assert len(ret) == num_items
+ return ret
+
+ def test_4_broadcast(self):
+ """Tests header/attr output for listing IPv4 ifas on broadcast iface"""
+ ret = self.filter_iface_family(socket.AF_INET, 1)
+ # Should be 192.0.2.1/24
+ msg = ret[0]
+ # Family and ifindex has been checked already
+ assert msg.base_hdr.ifa_prefixlen == 24
+ # Ignore IFA_FLAGS for now
+ assert msg.base_hdr.ifa_scope == RtScope.RT_SCOPE_UNIVERSE.value
+
+ assert msg.get_nla(IfattrType.IFA_ADDRESS).addr == "192.0.2.1"
+ assert msg.get_nla(IfattrType.IFA_LOCAL).addr == "192.0.2.1"
+ assert msg.get_nla(IfattrType.IFA_BROADCAST).addr == "192.0.2.255"
+
+ epair_ifname = self.vnet.iface_alias_map["if1"].name
+ assert msg.get_nla(IfattrType.IFA_LABEL).text == epair_ifname
+
+ def test_6_broadcast(self):
+ """Tests header/attr output for listing IPv6 ifas on broadcast iface"""
+ ret = self.filter_iface_family(socket.AF_INET6, 2)
+ # Should be 192.0.2.1/24
+ if ret[0].base_hdr.ifa_scope == RtScope.RT_SCOPE_UNIVERSE.value:
+ (gmsg, lmsg) = ret
+ else:
+ (lmsg, gmsg) = ret
+ # Start with global ( 2001:db8::1/64 )
+ msg = gmsg
+ # Family and ifindex has been checked already
+ assert msg.base_hdr.ifa_prefixlen == 64
+ # Ignore IFA_FLAGS for now
+ assert msg.base_hdr.ifa_scope == RtScope.RT_SCOPE_UNIVERSE.value
+
+ assert msg.get_nla(IfattrType.IFA_ADDRESS).addr == "2001:db8::1"
+ assert msg.get_nla(IfattrType.IFA_LOCAL) is None
+ assert msg.get_nla(IfattrType.IFA_BROADCAST) is None
+
+ epair_ifname = self.vnet.iface_alias_map["if1"].name
+ assert msg.get_nla(IfattrType.IFA_LABEL).text == epair_ifname
+
+ # Local: fe80::/64
+ msg = lmsg
+ assert msg.base_hdr.ifa_prefixlen == 64
+ # Ignore IFA_FLAGS for now
+ assert msg.base_hdr.ifa_scope == RtScope.RT_SCOPE_LINK.value
+
+ addr = ipaddress.ip_address(msg.get_nla(IfattrType.IFA_ADDRESS).addr)
+ assert addr.is_link_local
+ # Verify that ifindex is not emmbedded
+ assert struct.unpack("!H", addr.packed[2:4])[0] == 0
+ assert msg.get_nla(IfattrType.IFA_LOCAL) is None
+ assert msg.get_nla(IfattrType.IFA_BROADCAST) is None
+
+ epair_ifname = self.vnet.iface_alias_map["if1"].name
+ assert msg.get_nla(IfattrType.IFA_LABEL).text == epair_ifname
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 24, 6:07 AM (4 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30230806
Default Alt Text
D37970.id114845.diff (19 KB)
Attached To
Mode
D37970: netlink: improve RTM_GETADDR handling.
Attached
Detach File
Event Timeline
Log In to Comment