Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135826852
D22974.id66162.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
D22974.id66162.diff
View Options
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -446,10 +446,10 @@
void rt_ifmsg(struct ifnet *);
void rt_missmsg(int, struct rt_addrinfo *, int, int);
void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int);
-void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
-void rt_newaddrmsg_fib(int, struct ifaddr *, int, struct rtentry *, int);
+void rt_newaddrmsg_fib(int, struct ifaddr *, struct rtentry *, int);
int rt_addrmsg(int, struct ifaddr *, int);
-int rt_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
+int rt_routemsg(int, struct rtentry *, struct ifnet *ifp, int, int);
+int rt_routemsg_info(int, struct rt_addrinfo *, int);
void rt_newmaddrmsg(int, struct ifmultiaddr *);
int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
@@ -458,7 +458,8 @@
u_int rt_tables_get_gen(int table, int fam);
int rtsock_addrmsg(int, struct ifaddr *, int);
-int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
+int rtsock_routemsg(int, struct rtentry *, struct ifnet *ifp, int, int);
+int rtsock_routemsg_info(int, struct rt_addrinfo *, int);
/*
* Note the following locking behavior:
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -2147,7 +2147,7 @@
#endif
RT_ADDREF(rt);
RT_UNLOCK(rt);
- rt_newaddrmsg_fib(cmd, ifa, error, rt, fibnum);
+ rt_newaddrmsg_fib(cmd, ifa, rt, fibnum);
RT_LOCK(rt);
RT_REMREF(rt);
if (cmd == RTM_DELETE) {
@@ -2233,17 +2233,16 @@
}
/*
- * Announce route addition/removal.
- * Users of this function MUST validate input data BEFORE calling.
- * However we have to be able to handle invalid data:
- * if some userland app sends us "invalid" route message (invalid mask,
- * no dst, wrong address families, etc...) we need to pass it back
- * to app (and any other rtsock consumers) with rtm_errno field set to
- * non-zero value.
+ * Announce kernel-originated route addition/removal to rtsock based on @rt data.
+ * cmd: RTM_ cmd
+ * @rt: valid rtentry
+ * @ifp: target route interface
+ * @fibnum: fib id or RT_ALL_FIBS
+ *
* Returns 0 on success.
*/
int
-rt_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt,
+rt_routemsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int rti_addrs,
int fibnum)
{
@@ -2255,23 +2254,39 @@
KASSERT(rt_key(rt) != NULL, (":%s: rt_key must be supplied", __func__));
- return (rtsock_routemsg(cmd, ifp, error, rt, fibnum));
+ return (rtsock_routemsg(cmd, rt, ifp, 0, fibnum));
}
-void
-rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+/*
+ * Announce kernel-originated route addition/removal to rtsock based on @rt data.
+ * cmd: RTM_ cmd
+ * @info: addrinfo structure with valid data.
+ * @fibnum: fib id or RT_ALL_FIBS
+ *
+ * Returns 0 on success.
+ */
+int
+rt_routemsg_info(int cmd, struct rt_addrinfo *info, int fibnum)
{
- rt_newaddrmsg_fib(cmd, ifa, error, rt, RT_ALL_FIBS);
+ KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE,
+ ("unexpected cmd %d", cmd));
+
+ KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs),
+ ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs));
+
+ KASSERT(info->rti_info[RTAX_DST] != NULL, (":%s: RTAX_DST must be supplied", __func__));
+
+ return (rtsock_routemsg_info(cmd, info, fibnum));
}
+
/*
* This is called to generate messages from the routing socket
* indicating a network interface has had addresses associated with it.
*/
void
-rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
- int fibnum)
+rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, struct rtentry *rt, int fibnum)
{
KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
@@ -2282,10 +2297,10 @@
if (cmd == RTM_ADD) {
rt_addrmsg(cmd, ifa, fibnum);
if (rt != NULL)
- rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum);
+ rt_routemsg(cmd, rt, ifa->ifa_ifp, 0, fibnum);
} else {
if (rt != NULL)
- rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum);
+ rt_routemsg(cmd, rt, ifa->ifa_ifp, 0, fibnum);
rt_addrmsg(cmd, ifa, fibnum);
}
}
Index: sys/net/rtsock.c
===================================================================
--- sys/net/rtsock.c
+++ sys/net/rtsock.c
@@ -1351,7 +1351,7 @@
info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(
- info.rti_info[RTAX_IFP], ifa->ifa_netmask, &ss);
+ info.rti_info[RTAX_IFA], ifa->ifa_netmask, &ss);
info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
if ((m = rtsock_msg_mbuf(ncmd, &info)) == NULL)
return (ENOBUFS);
@@ -1372,46 +1372,69 @@
}
/*
- * Announce route addition/removal.
- * Please do not call directly, use rt_routemsg().
- * Note that @rt data MAY be inconsistent/invalid:
- * if some userland app sends us "invalid" route message (invalid mask,
- * no dst, wrong address families, etc...) we need to pass it back
- * to app (and any other rtsock consumers) with rtm_errno field set to
- * non-zero value.
+ * Announce route addition/removal to rtsock based on @rt data.
+ * Callers are advives to use rt_routemsg() instead of using this
+ * function directly.
+ * Assume @rt data is consistent.
*
* Returns 0 on success.
*/
int
-rtsock_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt,
+rtsock_routemsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int rti_addrs,
int fibnum)
{
- struct rt_addrinfo info;
- struct sockaddr *sa;
- struct mbuf *m;
- struct rt_msghdr *rtm;
struct sockaddr_storage ss;
+ struct rt_addrinfo info;
if (V_route_cb.any_count == 0)
return (0);
bzero((caddr_t)&info, sizeof(info));
- info.rti_info[RTAX_DST] = sa = rt_key(rt);
- info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(sa, rt_mask(rt), &ss);
+ info.rti_info[RTAX_DST] = rt_key(rt);
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), rt_mask(rt), &ss);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- if ((m = rtsock_msg_mbuf(cmd, &info)) == NULL)
+ info.rti_flags = rt->rt_flags;
+ info.rti_ifp = ifp;
+
+ return (rtsock_routemsg_info(cmd, &info, fibnum));
+}
+
+int
+rtsock_routemsg_info(int cmd, struct rt_addrinfo *info, int fibnum)
+{
+ struct rt_msghdr *rtm;
+ struct sockaddr *sa;
+ struct mbuf *m;
+
+ if (V_route_cb.any_count == 0)
+ return (0);
+
+ if (info->rti_flags & RTF_HOST)
+ info->rti_info[RTAX_NETMASK] = NULL;
+
+ m = rtsock_msg_mbuf(cmd, info);
+ if (m == NULL)
return (ENOBUFS);
- rtm = mtod(m, struct rt_msghdr *);
- rtm->rtm_index = ifp->if_index;
- rtm->rtm_flags |= rt->rt_flags;
- rtm->rtm_errno = error;
- rtm->rtm_addrs = info.rti_addrs;
if (fibnum != RT_ALL_FIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
+ "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
M_SETFIB(m, fibnum);
m->m_flags |= RTS_FILTER_FIB;
}
+ rtm = mtod(m, struct rt_msghdr *);
+ rtm->rtm_addrs = info->rti_addrs;
+ if (info->rti_ifp != NULL)
+ rtm->rtm_index = info->rti_ifp->if_index;
+ /* Add RTF_DONE to indicate command 'completion' required by API */
+ info->rti_flags |= RTF_DONE;
+ /* Reported routes has to be up */
+ if (cmd == RTM_ADD || cmd == RTM_CHANGE)
+ info->rti_flags |= RTF_UP;
+ rtm->rtm_flags = info->rti_flags;
+
+ sa = info->rti_info[RTAX_DST];
rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
return (0);
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -168,30 +168,35 @@
void
in6_newaddrmsg(struct in6_ifaddr *ia, int cmd)
{
+ struct rt_addrinfo info;
+ struct ifaddr *ifa;
struct sockaddr_dl gateway;
- struct sockaddr_in6 mask, addr;
- struct rtentry rt;
int fibnum;
+ ifa = &ia->ia_ifa;
+
/*
- * initialize for rtmsg generation
+ * Prepare info data for the host route.
+ * This code mimics one from ifa_maintain_loopback_route().
*/
- bzero(&gateway, sizeof(gateway));
- gateway.sdl_len = sizeof(gateway);
- gateway.sdl_family = AF_LINK;
+ bzero(&info, sizeof(struct rt_addrinfo));
+ info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED;
+ info.rti_info[RTAX_DST] = ifa->ifa_addr;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gateway;
+ link_init_sdl(ifa->ifa_ifp, (struct sockaddr *)&gateway, ifa->ifa_ifp->if_type);
+ if (cmd != RTM_DELETE)
+ info.rti_ifp = V_loif;
- bzero(&rt, sizeof(rt));
- rt.rt_gateway = (struct sockaddr *)&gateway;
- memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
- memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
- rt_mask(&rt) = (struct sockaddr *)&mask;
- rt_key(&rt) = (struct sockaddr *)&addr;
- rt.rt_flags = RTF_HOST | RTF_STATIC;
- if (cmd == RTM_ADD)
- rt.rt_flags |= RTF_UP;
+
fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : ia62ifa(ia)->ifa_ifp->if_fib;
- /* Announce arrival of local address to this FIB. */
- rt_newaddrmsg_fib(cmd, &ia->ia_ifa, 0, &rt, fibnum);
+
+ if (cmd == RTM_ADD) {
+ rt_addrmsg(cmd, &ia->ia_ifa, fibnum);
+ rt_routemsg_info(cmd, &info, fibnum);
+ } else if (cmd == RTM_DELETE) {
+ rt_routemsg_info(cmd, &info, fibnum);
+ rt_addrmsg(cmd, &ia->ia_ifa, fibnum);
+ }
}
int
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -609,30 +609,8 @@
static void
nd6_rtmsg(int cmd, struct rtentry *rt)
{
- struct rt_addrinfo info;
- struct ifnet *ifp;
- struct ifaddr *ifa;
- bzero((caddr_t)&info, sizeof(info));
- info.rti_info[RTAX_DST] = rt_key(rt);
- info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- ifp = rt->rt_ifp;
- if (ifp != NULL) {
- struct epoch_tracker et;
-
- NET_EPOCH_ENTER(et);
- ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
- info.rti_info[RTAX_IFP] = ifa->ifa_addr;
- ifa_ref(ifa);
- NET_EPOCH_EXIT(et);
- info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
- } else
- ifa = NULL;
-
- rt_missmsg_fib(cmd, &info, rt->rt_flags, 0, rt->rt_fibnum);
- if (ifa != NULL)
- ifa_free(ifa);
+ rt_routemsg(cmd, rt, rt->rt_ifp, 0, rt->rt_fibnum);
}
/* PFXRTR */
Index: tests/sys/net/routing/rtsock_common.h
===================================================================
--- tests/sys/net/routing/rtsock_common.h
+++ tests/sys/net/routing/rtsock_common.h
@@ -706,35 +706,36 @@
}
static void
-_validate_route_message(struct rt_msghdr *rtm)
+_validate_message_sockaddrs(char *buffer, int rtm_len, size_t offset, int rtm_addrs)
{
struct sockaddr *sa;
- size_t parsed_len = sizeof(struct rt_msghdr);
- int len = rtm->rtm_msglen;
+ size_t parsed_len = offset;
- sa = (struct sockaddr *)(rtm + 1);
+ /* Offset denotes initial header size */
+ sa = (struct sockaddr *)(buffer + offset);
for (int i = 0; i < RTAX_MAX; i++) {
- if ((rtm->rtm_addrs & (1 << i)) == 0)
+ if ((rtm_addrs & (1 << i)) == 0)
continue;
parsed_len += SA_SIZE(sa);
- RTSOCK_ATF_REQUIRE_MSG(rtm, parsed_len <= len,
- "SA %d: len %d exceeds msg size %d", i, (int)sa->sa_len, len);
+ RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len <= rtm_len,
+ "SA %d: len %d exceeds msg size %d", i, (int)sa->sa_len, rtm_len);
if (sa->sa_family == AF_LINK) {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
int data_len = sdl->sdl_nlen + sdl->sdl_alen;
data_len += offsetof(struct sockaddr_dl, sdl_data);
- RTSOCK_ATF_REQUIRE_MSG(rtm, data_len <= len,
- "AF_LINK data size exceeds total len: %u vs %u",
- data_len, len);
+ RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer,
+ data_len <= rtm_len,
+ "AF_LINK data size exceeds total len: %u vs %u, nlen=%d alen=%d",
+ data_len, rtm_len, sdl->sdl_nlen, sdl->sdl_alen);
}
sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
}
- RTSOCK_ATF_REQUIRE_MSG(rtm, parsed_len == rtm->rtm_msglen,
+ RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len == rtm_len,
"message len != parsed len: expected %d parsed %d",
- rtm->rtm_msglen, (int)parsed_len);
+ rtm_len, (int)parsed_len);
}
/*
@@ -758,9 +759,36 @@
case RTM_ADD:
case RTM_DELETE:
case RTM_CHANGE:
- _validate_route_message(rtm);
+ _validate_message_sockaddrs(buffer, rtm->rtm_msglen,
+ sizeof(struct rt_msghdr), rtm->rtm_addrs);
break;
+ case RTM_DELADDR:
+ case RTM_NEWADDR:
+ _validate_message_sockaddrs(buffer, rtm->rtm_msglen,
+ sizeof(struct ifa_msghdr), ((struct ifa_msghdr *)buffer)->ifam_addrs);
+ break;
}
+}
+
+void
+rtsock_validate_pid_ours(struct rt_msghdr *rtm)
+{
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == getpid(), "expected pid %d, got %d",
+ getpid(), rtm->rtm_pid);
+}
+
+void
+rtsock_validate_pid_user(struct rt_msghdr *rtm)
+{
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid > 0, "expected non-zero pid, got %d",
+ rtm->rtm_pid);
+}
+
+void
+rtsock_validate_pid_kernel(struct rt_msghdr *rtm)
+{
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == 0, "expected zero pid, got %d",
+ rtm->rtm_pid);
}
#endif
Index: tests/sys/net/routing/rtsock_print.h
===================================================================
--- tests/sys/net/routing/rtsock_print.h
+++ tests/sys/net/routing/rtsock_print.h
@@ -40,12 +40,20 @@
#define RTSOCK_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \
if (!(_cond)) { \
printf("-- CONDITION FAILED, rtm dump --\n\n");\
- rtsock_print_rtm(_rtm); \
+ rtsock_print_message(_rtm); \
} \
ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \
} while (0);
+#define RTSOCKHD_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \
+ if (!(_cond)) { \
+ printf("-- CONDITION FAILED, rtm hexdump--\n\n");\
+ rtsock_print_message_hd(_rtm); \
+ } \
+ ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \
+} while (0);
+
/* from route.c */
static const char *const msgtypes[] = {
"",
@@ -145,7 +153,7 @@
unsigned char v;
int repeat_count = 0;
for (int i = 0; i < len; i++) {
- if (last_char && *last_char == data[i]) {
+ if (last_char && *last_char == data[i] && data[i] == 0x00) {
repeat_count++;
continue;
}
@@ -157,9 +165,9 @@
v = ((const unsigned char *)data)[i];
if (last_char == NULL)
- _PRINTX("%02X", v);
+ _PRINTX("x%02X", v);
else
- _PRINTX(", %02X", v);
+ _PRINTX(", x%02X", v);
last_char = &data[i];
repeat_count = 1;
@@ -275,6 +283,81 @@
printf("\n");
+}
+
+void
+rtsock_print_ifa(struct ifa_msghdr *ifam)
+{
+ struct timeval tv;
+ struct tm tm_res;
+ char buf[64];
+
+ gettimeofday(&tv, NULL);
+ localtime_r(&tv.tv_sec, &tm_res);
+ strftime(buf, sizeof(buf), "%F %T", &tm_res);
+ printf("Got message of size %hu on %s\n", ifam->ifam_msglen, buf);
+
+ char flags_buf[256];
+ _printb(flags_buf, sizeof(flags_buf), ifam->ifam_flags, routeflags);
+
+ printf("%s: len %hu, ifindex: %d, flags: %s\n", msgtypes[ifam->ifam_type],
+ ifam->ifam_msglen, ifam->ifam_index, flags_buf);
+
+ _printb(flags_buf, sizeof(flags_buf), ifam->ifam_addrs, addrnames);
+ printf("sockaddrs: 0x%X %s\n", ifam->ifam_addrs, flags_buf);
+
+ char *ptr = (char *)(ifam + 1);
+ for (int i = 0; i < RTAX_MAX; i++) {
+ if (ifam->ifam_addrs & (1 << i)) {
+ struct sockaddr *sa = (struct sockaddr *)ptr;
+ sa_print(sa, 1);
+
+ /* add */
+ ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
+ }
+ }
+
+ printf("\n");
+
+}
+
+void
+rtsock_print_message_hd(struct rt_msghdr *rtm)
+{
+ struct timeval tv;
+ struct tm tm_res;
+ char buf[64];
+ char dumpbuf[2048];
+
+ gettimeofday(&tv, NULL);
+ localtime_r(&tv.tv_sec, &tm_res);
+ strftime(buf, sizeof(buf), "%F %T", &tm_res);
+ printf("Got message type %s of size %hu on %s\n",
+ rtsock_print_cmdtype(rtm->rtm_type),
+ rtm->rtm_msglen, buf);
+
+ sa_print_hd(dumpbuf, sizeof(dumpbuf), (char *)rtm, rtm->rtm_msglen);
+ printf(" %s\n", dumpbuf);
+}
+
+void
+rtsock_print_message(struct rt_msghdr *rtm)
+{
+
+ switch (rtm->rtm_type) {
+ case RTM_GET:
+ case RTM_ADD:
+ case RTM_DELETE:
+ case RTM_CHANGE:
+ rtsock_print_rtm(rtm);
+ break;
+ case RTM_DELADDR:
+ case RTM_NEWADDR:
+ rtsock_print_ifa((struct ifa_msghdr *)rtm);
+ break;
+ default:
+ printf("unknown rt message type %X\n", rtm->rtm_type);
+ }
}
#endif
Index: tests/sys/net/routing/test_rtsock_l3.c
===================================================================
--- tests/sys/net/routing/test_rtsock_l3.c
+++ tests/sys/net/routing/test_rtsock_l3.c
@@ -31,7 +31,7 @@
#include "rtsock_config.h"
static inline struct rtsock_test_config *
-presetup_ipv6(const atf_tc_t *tc)
+presetup_ipv6_iface(const atf_tc_t *tc)
{
struct rtsock_test_config *c;
int ret;
@@ -44,6 +44,17 @@
ret = iface_enable_ipv6(c->ifname);
ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname);
+ return (c);
+}
+
+static inline struct rtsock_test_config *
+presetup_ipv6(const atf_tc_t *tc)
+{
+ struct rtsock_test_config *c;
+ int ret;
+
+ c = presetup_ipv6_iface(tc);
+
ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
c->rtsock_fd = rtsock_setup_socket();
@@ -52,16 +63,15 @@
}
static inline struct rtsock_test_config *
-presetup_ipv4(const atf_tc_t *tc)
+presetup_ipv4_iface(const atf_tc_t *tc)
{
struct rtsock_test_config *c;
int ret;
c = config_setup(tc);
- /* assumes ifconfig doing IFF_UP */
- ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
- ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
+ ret = iface_turn_up(c->ifname);
+ ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
/* Actually open interface, so kernel writes won't fail */
if (c->autocreated_interface) {
@@ -69,6 +79,21 @@
ATF_REQUIRE_MSG(ret >= 0, "unable to open interface %s", c->ifname);
}
+ return (c);
+}
+
+static inline struct rtsock_test_config *
+presetup_ipv4(const atf_tc_t *tc)
+{
+ struct rtsock_test_config *c;
+ int ret;
+
+ c = presetup_ipv4_iface(tc);
+
+ /* assumes ifconfig doing IFF_UP */
+ ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
+ ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
+
c->rtsock_fd = rtsock_setup_socket();
return (c);
@@ -158,8 +183,6 @@
ret = sa_equal_msg(sa, gw, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
}
-
- RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid > 0, "expected non-zero pid");
}
static void
@@ -169,9 +192,22 @@
"expected ifindex %d, got %d", ifindex, rtm->rtm_index);
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags,
- "expected flags: %X, got %X", rtm_flags, rtm->rtm_flags);
+ "expected flags: 0x%X, got 0x%X", rtm_flags, rtm->rtm_flags);
}
+static void
+verify_link_gateway(struct rt_msghdr *rtm, int ifindex)
+{
+ struct sockaddr *sa;
+ struct sockaddr_dl *sdl;
+
+ sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
+ RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
+ RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
+ sdl = (struct sockaddr_dl *)sa;
+ RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index);
+}
+
/* TESTS */
#define DECLARE_TEST_VARS \
@@ -185,6 +221,16 @@
#define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg)
#define CLEANUP_AFTER_TEST config_generic_cleanup(config_setup(tc))
+#define RTM_DECLARE_ROOT_TEST(_name, _descr) \
+ATF_TC_WITH_CLEANUP(_name); \
+ATF_TC_HEAD(_name, tc) \
+{ \
+ DESCRIBE_ROOT_TEST(_descr); \
+} \
+ATF_TC_CLEANUP(_name, tc) \
+{ \
+ CLEANUP_AFTER_TEST; \
+}
ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success);
ATF_TC_HEAD(rtm_get_v4_exact_success, tc)
@@ -219,6 +265,7 @@
verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED);
/* Explicitly verify gateway for the interface route */
+ verify_link_gateway(rtm, c->ifindex);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
@@ -247,7 +294,7 @@
rtsock_send_rtm(c->rtsock_fd, rtm);
- rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
/*
* RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED>
@@ -503,8 +550,336 @@
CLEANUP_AFTER_TEST;
}
+/* Interface address messages tests */
+RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success,
+ "Tests validness for /128 host route announce after ifaddr assignment");
+ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv6_iface(tc);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ /*
+ * There will be multiple.
+ * RTM_ADD without llinfo.
+ */
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0))
+ break;
+ }
+ /* This should be a message for the host route */
+
+ verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL);
+ rtsock_validate_pid_kernel(rtm);
+ /* No netmask should be set */
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
+ verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags);
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success,
+ "Tests validness for the prefix route announce after ifaddr assignment");
+
+ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv6_iface(tc);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ /*
+ * Multiple RTM_ADD messages will be generated:
+ * 1) lladdr mapping (RTF_LLDATA)
+ * 2) host route (one w/o netmask)
+ * 3) prefix route
+ */
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
+ break;
+ }
+
+ /* This should be a message for the prefix route */
+ verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6,
+ (struct sockaddr *)&c->mask6, NULL);
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ /* TODO: PINNED? */
+ int expected_rt_flags = RTF_UP | RTF_DONE;
+ verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success,
+ "Tests ordering of the messages for IPv6 global unicast ifaddr assignment");
+
+ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv6_iface(tc);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ int count = 0, tries = 0;
+
+ enum msgtype {
+ MSG_IFADDR,
+ MSG_HOSTROUTE,
+ MSG_PREFIXROUTE,
+ MSG_MAX,
+ };
+
+ int msg_array[MSG_MAX];
+
+ bzero(msg_array, sizeof(msg_array));
+
+ while (count < 3 && tries < 20) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ tries++;
+ /* Classify */
+ if (rtm->rtm_type == RTM_NEWADDR) {
+ RLOG("MSG_IFADDR: %d", count);
+ msg_array[MSG_IFADDR] = count++;
+ continue;
+ }
+
+ /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
+ RLOG("MSG_PREFIXROUTE: %d", count);
+ msg_array[MSG_PREFIXROUTE] = count++;
+ continue;
+ }
+
+ if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) {
+ RLOG("MSG_HOSTROUTE: %d", count);
+ msg_array[MSG_HOSTROUTE] = count++;
+ continue;
+ }
+
+ RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
+ tries);
+ }
+
+ /* TODO: verify multicast */
+ ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count);
+ ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success,
+ "Tests validness for /128 host route removal after ifaddr removal");
+
+ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv6_iface(tc);
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_delete_addr(c->ifname, c->addr6_str);
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ if ((rtm->rtm_type == RTM_DELETE) &&
+ ((rtm->rtm_flags & RTF_LLINFO) == 0) &&
+ rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL)
+ break;
+ }
+ /* This should be a message for the host route */
+
+ verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL);
+ rtsock_validate_pid_kernel(rtm);
+ /* No netmask should be set */
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ /* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */
+ int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
+ RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags,
+ "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags);
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success,
+ "Tests validness for the prefix route removal after ifaddr assignment");
+
+ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv6_iface(tc);
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_delete_addr(c->ifname, c->addr6_str);
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ /* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
+ break;
+ }
+
+ /* This should be a message for the prefix route */
+ verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6,
+ (struct sockaddr *)&c->mask6, NULL);
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ int expected_rt_flags = RTF_DONE;
+ verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success,
+ "Tests validness for the prefix route announce after ifaddr assignment");
+
+ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv4_iface(tc);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
+
+ /*
+ * Multiple RTM_ADD messages will be generated:
+ * 1) lladdr mapping (RTF_LLDATA)
+ * 3) prefix route
+ */
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
+ break;
+ }
+
+ /* This should be a message for the prefix route */
+ verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4,
+ (struct sockaddr *)&c->mask4, NULL);
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED;
+ verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success,
+ "Tests ordering of the messages for IPv4 unicast ifaddr assignment");
+
+ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv4_iface(tc);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
+
+ int count = 0, tries = 0;
+
+ enum msgtype {
+ MSG_IFADDR,
+ MSG_PREFIXROUTE,
+ MSG_MAX,
+ };
+
+ int msg_array[MSG_MAX];
+
+ bzero(msg_array, sizeof(msg_array));
+
+ while (count < 2 && tries < 20) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ tries++;
+ /* Classify */
+ if (rtm->rtm_type == RTM_NEWADDR) {
+ RLOG("MSG_IFADDR: %d", count);
+ msg_array[MSG_IFADDR] = count++;
+ continue;
+ }
+
+ /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
+ RLOG("MSG_PREFIXROUTE: %d", count);
+ msg_array[MSG_PREFIXROUTE] = count++;
+ continue;
+ }
+
+ RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
+ tries);
+ }
+
+ /* TODO: verify multicast */
+ ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count);
+ ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
+}
+
+RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success,
+ "Tests validness for the prefix route removal after ifaddr assignment");
+
+ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc)
+{
+ DECLARE_TEST_VARS;
+
+ c = presetup_ipv4_iface(tc);
+
+
+ ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
+
+ c->rtsock_fd = rtsock_setup_socket();
+
+ ret = iface_delete_addr(c->ifname, c->addr4_str);
+
+ while (true) {
+ rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
+ /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
+ if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
+ break;
+ }
+
+ /* This should be a message for the prefix route */
+ verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4,
+ (struct sockaddr *)&c->mask4, NULL);
+
+ /* gateway should be link sdl with ifindex of an address interface */
+ verify_link_gateway(rtm, c->ifindex);
+
+ int expected_rt_flags = RTF_DONE | RTF_PINNED;
+ verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
+}
+
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success);
@@ -515,6 +890,14 @@
ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success);
ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success);
ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success);
+ /* ifaddr tests */
+ ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success);
+ ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success);
+ ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success);
+ ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success);
+ ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success);
+ ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success);
+ ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success);
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 14, 6:43 AM (22 m, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25269492
Default Alt Text
D22974.id66162.diff (30 KB)
Attached To
Mode
D22974: Fix rtsock route message generation for interface addresses.
Attached
Detach File
Event Timeline
Log In to Comment