Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Mar 2023 10:08:53 +0100
From:      Alexander Chernikov <melifaro@FreeBSD.org>
To:        Jessica Clarke <jrtc27@freebsd.org>
Cc:        "src-committers@freebsd.org" <src-committers@FreeBSD.org>, "dev-commits-src-all@freebsd.org" <dev-commits-src-all@FreeBSD.org>, "dev-commits-src-main@freebsd.org" <dev-commits-src-main@FreeBSD.org>
Subject:   Re: git: c597432e2297 - main - route(8): convert to netlink
Message-ID:  <F0DD3830-654C-49F1-B6D6-C17171A30553@FreeBSD.org>
In-Reply-To: <81A0DF64-F466-451F-83CB-86A9FC1EB300@freebsd.org>
References:  <202303261107.32QB7UZK058893@gitrepo.freebsd.org> <81A0DF64-F466-451F-83CB-86A9FC1EB300@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_AE460F85-A90B-4D1C-9453-E5B4D7CEC4B9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8



> On 27 Mar 2023, at 21:41, Jessica Clarke <jrtc27@freebsd.org> wrote:
>=20
> On 26 Mar 2023, at 12:07, Alexander V. Chernikov <melifaro@FreeBSD.org =
<mailto:melifaro@FreeBSD.org>> wrote:
>>=20
>> The branch main has been updated by melifaro:
>>=20
>> URL: =
https://cgit.FreeBSD.org/src/commit/?id=3Dc597432e22975f4d409b845377996712=
9c6b57e9
>>=20
>> commit c597432e22975f4d409b8453779967129c6b57e9
>> Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
>> AuthorDate: 2023-03-26 09:13:50 +0000
>> Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
>> CommitDate: 2023-03-26 11:06:56 +0000
>>=20
>>   route(8): convert to netlink
>>=20
>>   This change converts all kernel rtsock interactions in route(8)
>>    to Netlink.
>>=20
>>   Based on the WITHOUT_NETLINK_SUPPORT src.conf(5) variable, route(8)
>>    now fully operates either via Netlink or via rtsock/sysctl.
>>   The default (compile-time) is Netlink.
>>=20
>>   The output for route delete/add/get/flush is targeted to be exactly
>>    the same (apart from some error handling cases).
>>   The output for the route monitor has been changed to improve
>>    readability and support netlink models.
>>=20
>>   Other behaviour changes:
>>   * exact prefix lookup (route -n get a.b.c.d/e) is not yet =
supported.
>>   * route monitor does not show the change originator yet.
>=20
> If there are regressions then it should be off by default, =
*especially*
Hi Jessica,
I have a plan to fix both this week. I=E2=80=99d also want to note that =
these two are not the documented / often used features.
> when we=E2=80=99re just under a month out from the proposed 14 code =
slush.
>=20
> Jess
>=20
>>   Differential Revision:  https://reviews.freebsd.org/D39007
>> ---
>> sbin/route/Makefile        |   6 +
>> sbin/route/route.c         | 117 +++++--
>> sbin/route/route_netlink.c | 835 =
+++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 930 insertions(+), 28 deletions(-)
>>=20
>> diff --git a/sbin/route/Makefile b/sbin/route/Makefile
>> index e65030f805bb..aec222310d46 100644
>> --- a/sbin/route/Makefile
>> +++ b/sbin/route/Makefile
>> @@ -19,6 +19,12 @@ CFLAGS+=3D -DINET6
>> .endif
>> CFLAGS+=3D -I.
>>=20
>> +.if ${MK_NETLINK_SUPPORT} !=3D "no"
>> +SRCS+=3D	route_netlink.c
>> +.else
>> +CFLAGS+=3D-DWITHOUT_NETLINK
>> +.endif
>> +
>> HAS_TESTS=3D
>> SUBDIR.${MK_TESTS}+=3D tests
>>=20
>> diff --git a/sbin/route/route.c b/sbin/route/route.c
>> index 5f33cecb1b20..947c97ce794a 100644
>> --- a/sbin/route/route.c
>> +++ b/sbin/route/route.c
>> @@ -90,12 +90,11 @@ static struct keytab {
>> 	{0, 0}
>> };
>>=20
>> +int	verbose, debugonly;
>> static struct sockaddr_storage so[RTAX_MAX];
>> static int	pid, rtm_addrs;
>> -static int	s;
>> -static int	nflag, af, qflag, tflag;
>> -static int	verbose, aflen;
>> -static int	locking, lockrest, debugonly;
>> +static int	nflag, af, aflen, qflag, tflag;
>> +static int	locking, lockrest;
>> static struct rt_metrics rt_metrics;
>> static u_long  rtm_inits;
>> static uid_t	uid;
>> @@ -103,18 +102,30 @@ static int	defaultfib;
>> static int	numfibs;
>> static char	domain[MAXHOSTNAMELEN + 1];
>> static bool	domain_initialized;
>> -static int	rtm_seq;
>> static char	rt_line[NI_MAXHOST];
>> static char	net_line[MAXHOSTNAMELEN + 1];
>>=20
>> +#ifdef WITHOUT_NETLINK
>> +static int	s;
>> +static int	rtm_seq;
>> +
>> static struct {
>> 	struct	rt_msghdr m_rtm;
>> 	char	m_space[512];
>> } m_rtmsg;
>>=20
>> +static int	rtmsg_rtsock(int, int, int);
>> +static int	flushroutes_fib_rtsock(int);
>> +static void	monitor_rtsock(void);
>> +#else
>> +int		rtmsg_nl(int, int, int, struct sockaddr_storage *, =
struct rt_metrics *);
>> +int		flushroutes_fib_nl(int, int);
>> +void		monitor_nl(int);
>> +#endif
>> +
>> static TAILQ_HEAD(fibl_head_t, fibl) fibl_head;
>>=20
>> -static void	printb(int, const char *);
>> +void	printb(int, const char *);
>> static void	flushroutes(int argc, char *argv[]);
>> static int	flushroutes_fib(int);
>> static int	getaddr(int, char *, int);
>> @@ -127,7 +138,7 @@ static int	inet6_makenetandmask(struct =
sockaddr_in6 *, const char *);
>> #endif
>> static void	interfaces(void);
>> static void	monitor(int, char*[]);
>> -static const char	*netname(struct sockaddr *);
>> +const char	*netname(struct sockaddr *);
>> static void	newroute(int, char **);
>> static int	newroute_fib(int, char *, int);
>> static void	pmsg_addrs(char *, int, size_t);
>> @@ -135,7 +146,7 @@ static void	pmsg_common(struct rt_msghdr *, =
size_t);
>> static int	prefixlen(const char *);
>> static void	print_getmsg(struct rt_msghdr *, int, int);
>> static void	print_rtmsg(struct rt_msghdr *, size_t);
>> -static const char	*routename(struct sockaddr *);
>> +const char	*routename(struct sockaddr *);
>> static int	rtmsg(int, int, int);
>> static void	set_metric(char *, int);
>> static int	set_sofib(int);
>> @@ -216,12 +227,14 @@ main(int argc, char **argv)
>>=20
>> 	pid =3D getpid();
>> 	uid =3D geteuid();
>> +#ifdef WITHOUT_NETLINK
>> 	if (tflag)
>> 		s =3D open(_PATH_DEVNULL, O_WRONLY, 0);
>> 	else
>> 		s =3D socket(PF_ROUTE, SOCK_RAW, 0);
>> 	if (s < 0)
>> 		err(EX_OSERR, "socket");
>> +#endif
>>=20
>> 	len =3D sizeof(numfibs);
>> 	if (sysctlbyname("net.fibs", (void *)&numfibs, &len, NULL, 0) =3D=3D=
 -1)
>> @@ -264,10 +277,14 @@ static int
>> set_sofib(int fib)
>> {
>>=20
>> +#ifdef WITHOUT_NETLINK
>> 	if (fib < 0)
>> 		return (0);
>> 	return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
>> 	    sizeof(fib)));
>> +#else
>> +	return (0);
>> +#endif
>> }
>>=20
>> static int
>> @@ -395,7 +412,9 @@ flushroutes(int argc, char *argv[])
>>=20
>> 	if (uid !=3D 0 && !debugonly && !tflag)
>> 		errx(EX_NOPERM, "must be root to alter routing table");
>> +#ifdef WITHOUT_NETLINK
>> 	shutdown(s, SHUT_RD); /* Don't want to read back our messages */
>> +#endif
>>=20
>> 	TAILQ_INIT(&fibl_head);
>> 	while (argc > 1) {
>> @@ -441,6 +460,17 @@ flushroutes(int argc, char *argv[])
>>=20
>> static int
>> flushroutes_fib(int fib)
>> +{
>> +#ifdef WITHOUT_NETLINK
>> +	return (flushroutes_fib_rtsock(fib));
>> +#else
>> +	return (flushroutes_fib_nl(fib, af));
>> +#endif
>> +}
>> +
>> +#ifdef WITHOUT_NETLINK
>> +static int
>> +flushroutes_fib_rtsock(int fib)
>> {
>> 	struct rt_msghdr *rtm;
>> 	size_t needed;
>> @@ -525,8 +555,9 @@ retry:
>> 	free(buf);
>> 	return (error);
>> }
>> +#endif
>>=20
>> -static const char *
>> +const char *
>> routename(struct sockaddr *sa)
>> {
>> 	struct sockaddr_dl *sdl;
>> @@ -645,7 +676,7 @@ routename(struct sockaddr *sa)
>> * Return the name of the network whose address is given.
>> * The address is assumed to be that of a net, not a host.
>> */
>> -static const char *
>> +const char *
>> netname(struct sockaddr *sa)
>> {
>> 	struct sockaddr_dl *sdl;
>> @@ -810,8 +841,10 @@ newroute(int argc, char **argv)
>> 		warn("sigaction SIGALRM");
>>=20
>> 	cmd =3D argv[0];
>> +#ifdef WITHOUT_NETLINK
>> 	if (*cmd !=3D 'g' && *cmd !=3D 's')
>> 		shutdown(s, SHUT_RD); /* Don't want to read back our =
messages */
>> +#endif
>> 	while (--argc > 0) {
>> 		if (**(++argv)=3D=3D '-') {
>> 			switch (key =3D keyword(1 + *argv)) {
>> @@ -1398,8 +1431,8 @@ retry2:
>> static void
>> monitor(int argc, char *argv[])
>> {
>> -	int n, fib, error;
>> -	char msg[2048], *endptr;
>> +	int fib, error;
>> +	char *endptr;
>>=20
>> 	fib =3D defaultfib;
>> 	while (argc > 1) {
>> @@ -1435,6 +1468,19 @@ monitor(int argc, char *argv[])
>> 		interfaces();
>> 		exit(0);
>> 	}
>> +#ifdef WITHOUT_NETLINK
>> +	monitor_rtsock();
>> +#else
>> +	monitor_nl(fib);
>> +#endif
>> +}
>> +
>> +#ifdef WITHOUT_NETLINK
>> +static void
>> +monitor_rtsock(void)
>> +{
>> +	char msg[2048];
>> +	int n;
>>=20
>> #ifdef SO_RERROR
>> 	n =3D 1;
>> @@ -1454,25 +1500,12 @@ monitor(int argc, char *argv[])
>> 		print_rtmsg((struct rt_msghdr *)(void *)msg, n);
>> 	}
>> }
>> +#endif
>>=20
>> static int
>> rtmsg(int cmd, int flags, int fib)
>> {
>> -	int rlen;
>> -	char *cp =3D m_rtmsg.m_space;
>> -	int l;
>> -
>> -#define NEXTADDR(w, u)							=
\
>> -	if (rtm_addrs & (w)) {						=
\
>> -		l =3D SA_SIZE(&(u));					=
\
>> -		memmove(cp, (char *)&(u), l);				=
\
>> -		cp +=3D l;						=
\
>> -		if (verbose)						=
\
>> -			sodump((struct sockaddr *)&(u), #w);		=
\
>> -	}
>> -
>> 	errno =3D 0;
>> -	memset(&m_rtmsg, 0, sizeof(m_rtmsg));
>> 	if (cmd =3D=3D 'a')
>> 		cmd =3D RTM_ADD;
>> 	else if (cmd =3D=3D 'c')
>> @@ -1488,6 +1521,33 @@ rtmsg(int cmd, int flags, int fib)
>> 		cmd =3D RTM_DELETE;
>> 		flags |=3D RTF_PINNED;
>> 	}
>> +#ifdef WITHOUT_NETLINK
>> +	return (rtmsg_rtsock(cmd, flags, fib));
>> +#else
>> +	errno =3D rtmsg_nl(cmd, flags, fib, so, &rt_metrics);
>> +	return (errno =3D=3D 0 ? 0 : -1);
>> +#endif
>> +}
>> +
>> +#ifdef WITHOUT_NETLINK
>> +static int
>> +rtmsg_rtsock(int cmd, int flags, int fib)
>> +{
>> +	int rlen;
>> +	char *cp =3D m_rtmsg.m_space;
>> +	int l;
>> +
>> +	memset(&m_rtmsg, 0, sizeof(m_rtmsg));
>> +
>> +#define NEXTADDR(w, u)							=
\
>> +	if (rtm_addrs & (w)) {						=
\
>> +		l =3D SA_SIZE(&(u));					=
\
>> +		memmove(cp, (char *)&(u), l);				=
\
>> +		cp +=3D l;						=
\
>> +		if (verbose)						=
\
>> +			sodump((struct sockaddr *)&(u), #w);		=
\
>> +	}
>> +
>> #define rtm m_rtmsg.m_rtm
>> 	rtm.rtm_type =3D cmd;
>> 	rtm.rtm_flags =3D flags;
>> @@ -1545,6 +1605,7 @@ rtmsg(int cmd, int flags, int fib)
>> #undef rtm
>> 	return (0);
>> }
>> +#endif
>>=20
>> static const char *const msgtypes[] =3D {
>> 	"",
>> @@ -1571,7 +1632,7 @@ static const char *const msgtypes[] =3D {
>> static const char metricnames[] =3D
>>    "\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"
>>    "\1mtu";
>> -static const char routeflags[] =3D
>> +const char routeflags[] =3D
>>    "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
>>    "\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
>>    "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
>> @@ -1812,7 +1873,7 @@ pmsg_addrs(char *cp, int addrs, size_t len)
>> 	(void)fflush(stdout);
>> }
>>=20
>> -static void
>> +void
>> printb(int b, const char *str)
>> {
>> 	int i;
>> diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
>> new file mode 100644
>> index 000000000000..648d866670fc
>> --- /dev/null
>> +++ b/sbin/route/route_netlink.c
>> @@ -0,0 +1,835 @@
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <err.h>
>> +#include <errno.h>
>> +
>> +#include <sys/bitcount.h>
>> +#include <sys/param.h>
>> +#include <sys/socket.h>
>> +#include <sys/sysctl.h>
>> +#include <sys/time.h>
>> +#include <sys/types.h>
>> +
>> +#include <netinet/in.h>
>> +#include <arpa/inet.h>
>> +
>> +#include <net/ethernet.h>
>> +#include <net/if.h>
>> +#include <net/if_dl.h>
>> +#include <net/if_types.h>
>> +#include <netlink/netlink.h>
>> +#include <netlink/netlink_route.h>
>> +#include <netlink/netlink_snl.h>
>> +#include <netlink/netlink_snl_route.h>
>> +#include <netlink/netlink_snl_route_compat.h>
>> +#include <netlink/netlink_snl_route_parsers.h>
>> +
>> +const char *routename(struct sockaddr *);
>> +const char *netname(struct sockaddr *);
>> +void printb(int, const char *);
>> +extern const char routeflags[];
>> +extern int verbose, debugonly;
>> +
>> +int rtmsg_nl(int cmd, int rtm_flags, int fib, struct =
sockaddr_storage *so,
>> +    struct rt_metrics *rt_metrics);
>> +int flushroutes_fib_nl(int fib, int af);
>> +void monitor_nl(int fib);
>> +
>> +struct nl_helper;
>> +static void print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, =
struct sockaddr *dst);
>> +static void print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr);
>> +
>> +#define s6_addr32 __u6_addr.__u6_addr32
>> +#define	bitcount32(x)	__bitcount32((uint32_t)(x))
>> +static int
>> +inet6_get_plen(const struct in6_addr *addr)
>> +{
>> +
>> +	return (bitcount32(addr->s6_addr32[0]) + =
bitcount32(addr->s6_addr32[1]) +
>> +	    bitcount32(addr->s6_addr32[2]) + =
bitcount32(addr->s6_addr32[3]));
>> +}
>> +
>> +static void
>> +ip6_writemask(struct in6_addr *addr6, uint8_t mask)
>> +{
>> +	uint32_t *cp;
>> +
>> +	for (cp =3D (uint32_t *)addr6; mask >=3D 32; mask -=3D 32)
>> +		*cp++ =3D 0xFFFFFFFF;
>> +	if (mask > 0)
>> +		*cp =3D htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
>> +}
>> +
>> +static struct sockaddr *
>> +get_netmask(struct snl_state *ss, int family, int plen)
>> +{
>> +	if (family =3D=3D AF_INET) {
>> +		if (plen =3D=3D 32)
>> +			return (NULL);
>> +
>> +		struct sockaddr_in *sin =3D snl_allocz(ss, =
sizeof(*sin));
>> +
>> +		sin->sin_len =3D sizeof(*sin);
>> +		sin->sin_family =3D family;
>> +		sin->sin_addr.s_addr =3D htonl(plen ? ~((1 << (32 - =
plen)) - 1) : 0);
>> +
>> +		return (struct sockaddr *)sin;
>> +	} else if (family =3D=3D AF_INET6) {
>> +		if (plen =3D=3D 128)
>> +			return (NULL);
>> +
>> +		struct sockaddr_in6 *sin6 =3D snl_allocz(ss, =
sizeof(*sin6));
>> +
>> +		sin6->sin6_len =3D sizeof(*sin6);
>> +		sin6->sin6_family =3D family;
>> +		ip6_writemask(&sin6->sin6_addr, plen);
>> +
>> +		return (struct sockaddr *)sin6;
>> +	}
>> +	return (NULL);
>> +}
>> +
>> +struct nl_helper {
>> +	struct snl_state ss_cmd;
>> +};
>> +
>> +static void
>> +nl_helper_init(struct nl_helper *h)
>> +{
>> +	if (!snl_init(&h->ss_cmd, NETLINK_ROUTE))
>> +		err(1, "unable to open netlink socket");
>> +}
>> +
>> +static void
>> +nl_helper_free(struct nl_helper *h)
>> +{
>> +	snl_free(&h->ss_cmd);
>> +}
>> +
>> +static int
>> +rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib,
>> +    struct sockaddr_storage *so, struct rt_metrics *rt_metrics)
>> +{
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +	struct snl_writer nw;
>> +	int nl_type =3D 0, nl_flags =3D 0;
>> +
>> +	snl_init_writer(ss, &nw);
>> +
>> +	switch (cmd) {
>> +	case RTSOCK_RTM_ADD:
>> +		nl_type =3D RTM_NEWROUTE;
>> +		nl_flags =3D NLM_F_CREATE | NLM_F_APPEND; /* Do append =
by default */
>> +		break;
>> +	case RTSOCK_RTM_CHANGE:
>> +		nl_type =3D RTM_NEWROUTE;
>> +		nl_flags =3D NLM_F_REPLACE;
>> +		break;
>> +	case RTSOCK_RTM_DELETE:
>> +		nl_type =3D RTM_DELROUTE;
>> +		break;
>> +	case RTSOCK_RTM_GET:
>> +		nl_type =3D RTM_GETROUTE;
>> +		break;
>> +	default:
>> +		exit(1);
>> +	}
>> +
>> +	struct sockaddr *dst =3D (struct sockaddr *)&so[RTAX_DST];
>> +	struct sockaddr *mask =3D (struct sockaddr *)&so[RTAX_NETMASK];
>> +	struct sockaddr *gw =3D (struct sockaddr *)&so[RTAX_GATEWAY];
>> +
>> +	if (dst =3D=3D NULL)
>> +		return (EINVAL);
>> +
>> +	struct nlmsghdr *hdr =3D snl_create_msg_request(&nw, nl_type);
>> +	hdr->nlmsg_flags |=3D nl_flags;
>> +
>> +	int plen =3D 0;
>> +	int rtm_type =3D RTN_UNICAST;
>> +
>> +	switch (dst->sa_family) {
>> +	case AF_INET:
>> +	    {
>> +		struct sockaddr_in *mask4 =3D (struct sockaddr_in =
*)mask;
>> +
>> +		plen =3D mask4 ? bitcount32(mask4->sin_addr.s_addr) : =
32;
>> +		break;
>> +	    }
>> +	case AF_INET6:
>> +	    {
>> +		struct sockaddr_in6 *mask6 =3D (struct sockaddr_in6 =
*)mask;
>> +
>> +		plen =3D mask6 ? inet6_get_plen(&mask6->sin6_addr) : =
128;
>> +		break;
>> +	    }
>> +	default:
>> +		return (ENOTSUP);
>> +	}
>> +
>> +	if (rtm_flags & RTF_REJECT)
>> +		rtm_type =3D RTN_PROHIBIT;
>> +	else if (rtm_flags & RTF_BLACKHOLE)
>> +		rtm_type =3D RTN_BLACKHOLE;
>> +
>> +	struct rtmsg *rtm =3D snl_reserve_msg_object(&nw, struct rtmsg);
>> +	rtm->rtm_family =3D dst->sa_family;
>> +	rtm->rtm_protocol =3D RTPROT_STATIC;
>> +	rtm->rtm_type =3D rtm_type;
>> +	rtm->rtm_dst_len =3D plen;
>> +
>> +	snl_add_msg_attr_ip(&nw, RTA_DST, dst);
>> +	snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
>> +
>> +	if (rtm_flags & RTF_GATEWAY) {
>> +		if (gw->sa_family =3D=3D dst->sa_family)
>> +			snl_add_msg_attr_ip(&nw, RTA_GATEWAY, gw);
>> +		else
>> +			snl_add_msg_attr_ipvia(&nw, RTA_VIA, gw);
>> +	} else if (gw !=3D NULL) {
>> +		/* Should be AF_LINK */
>> +		struct sockaddr_dl *sdl =3D (struct sockaddr_dl *)gw;
>> +		if (sdl->sdl_index !=3D 0)
>> +			snl_add_msg_attr_u32(&nw, RTA_OIF, =
sdl->sdl_index);
>> +	}
>> +
>> +	if (rtm_flags !=3D 0)
>> +		snl_add_msg_attr_u32(&nw, NL_RTA_RTFLAGS, rtm_flags);
>> +
>> +	if (rt_metrics->rmx_mtu > 0) {
>> +		int off =3D snl_add_msg_attr_nested(&nw, RTA_METRICS);
>> +		snl_add_msg_attr_u32(&nw, RTAX_MTU, =
rt_metrics->rmx_mtu);
>> +		snl_end_attr_nested(&nw, off);
>> +	}
>> +
>> +	if (rt_metrics->rmx_weight > 0)
>> +		snl_add_msg_attr_u32(&nw, NL_RTA_WEIGHT, =
rt_metrics->rmx_weight);
>> +
>> +	if (snl_finalize_msg(&nw) && snl_send_message(ss, hdr)) {
>> +		struct snl_errmsg_data e =3D {};
>> +
>> +		hdr =3D snl_read_reply(ss, hdr->nlmsg_seq);
>> +		if (nl_type =3D=3D NL_RTM_GETROUTE) {
>> +			if (hdr->nlmsg_type =3D=3D NL_RTM_NEWROUTE)
>> +				print_getmsg(h, hdr, dst);
>> +			else {
>> +				snl_parse_errmsg(ss, hdr, &e);
>> +				if (e.error =3D=3D ESRCH)
>> +					warn("route has not been =
found");
>> +				else
>> +					warn("message indicates error =
%d", e.error);
>> +			}
>> +
>> +			return (0);
>> +		}
>> +
>> +		if (snl_parse_errmsg(ss, hdr, &e))
>> +			return (e.error);
>> +	}
>> +	return (EINVAL);
>> +}
>> +
>> +int
>> +rtmsg_nl(int cmd, int rtm_flags, int fib, struct sockaddr_storage =
*so,
>> +    struct rt_metrics *rt_metrics)
>> +{
>> +	struct nl_helper h =3D {};
>> +
>> +	nl_helper_init(&h);
>> +	int error =3D rtmsg_nl_int(&h, cmd, rtm_flags, fib, so, =
rt_metrics);
>> +	nl_helper_free(&h);
>> +
>> +	return (error);
>> +}
>> +
>> +static void
>> +get_ifdata(struct nl_helper *h, uint32_t ifindex, struct =
snl_parsed_link_simple *link)
>> +{
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +	struct snl_writer nw;
>> +
>> +	snl_init_writer(ss, &nw);
>> +	struct nlmsghdr *hdr =3D snl_create_msg_request(&nw, =
NL_RTM_GETLINK);
>> +	struct ifinfomsg *ifmsg =3D snl_reserve_msg_object(&nw, struct =
ifinfomsg);
>> +	if (ifmsg !=3D NULL)
>> +		ifmsg->ifi_index =3D ifindex;
>> +	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
>> +		return;
>> +
>> +	hdr =3D snl_read_reply(ss, hdr->nlmsg_seq);
>> +
>> +	if (hdr !=3D NULL && hdr->nlmsg_type =3D=3D RTM_NEWLINK) {
>> +		snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, =
link);
>> +	}
>> +
>> +	if (link->ifla_ifname =3D=3D NULL) {
>> +		char ifname[16];
>> +
>> +		snprintf(ifname, sizeof(ifname), "if#%u", ifindex);
>> +		int len =3D strlen(ifname);
>> +		char *buf =3D snl_allocz(ss, len + 1);
>> +		strlcpy(buf, ifname, len + 1);
>> +		link->ifla_ifname =3D buf;
>> +	}
>> +}
>> +
>> +static void
>> +print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct =
sockaddr *dst)
>> +{
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +	struct timespec ts;
>> +	struct snl_parsed_route r =3D { .rtax_weight =3D =
RT_DEFAULT_WEIGHT };
>> +
>> +	if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
>> +		return;
>> +
>> +	struct snl_parsed_link_simple link =3D {};
>> +	get_ifdata(h, r.rta_oif, &link);
>> +
>> +	if (r.rtax_mtu =3D=3D 0)
>> +		r.rtax_mtu =3D link.ifla_mtu;
>> +	r.rta_rtflags |=3D (RTF_UP | RTF_DONE);
>> +
>> +	(void)printf("   route to: %s\n", routename(dst));
>> +
>> +	if (r.rta_dst)
>> +		(void)printf("destination: %s\n", routename(r.rta_dst));
>> +	struct sockaddr *mask =3D get_netmask(ss, r.rtm_family, =
r.rtm_dst_len);
>> +	if (mask)
>> +		(void)printf("       mask: %s\n", routename(mask));
>> +	if (r.rta_gw && (r.rta_rtflags & RTF_GATEWAY))
>> +		(void)printf("    gateway: %s\n", routename(r.rta_gw));
>> +	(void)printf("        fib: %u\n", (unsigned int)r.rta_table);
>> +	if (link.ifla_ifname)
>> +		(void)printf("  interface: %s\n", link.ifla_ifname);
>> +	(void)printf("      flags: ");
>> +	printb(r.rta_rtflags, routeflags);
>> +
>> +	struct rt_metrics rmx =3D {
>> +		.rmx_mtu =3D r.rtax_mtu,
>> +		.rmx_weight =3D r.rtax_weight,
>> +		.rmx_expire =3D r.rta_expire,
>> +	};
>> +
>> +	printf("\n%9s %9s %9s %9s %9s %10s %9s\n", "recvpipe",
>> +	    "sendpipe", "ssthresh", "rtt,msec", "mtu   ", "weight", =
"expire");
>> +	printf("%8lu  ", rmx.rmx_recvpipe);
>> +	printf("%8lu  ", rmx.rmx_sendpipe);
>> +	printf("%8lu  ", rmx.rmx_ssthresh);
>> +	printf("%8lu  ", 0UL);
>> +	printf("%8lu  ", rmx.rmx_mtu);
>> +	printf("%8lu  ", rmx.rmx_weight);
>> +	if (rmx.rmx_expire > 0)
>> +		clock_gettime(CLOCK_REALTIME_FAST, &ts);
>> +	else
>> +		ts.tv_sec =3D 0;
>> +	printf("%8ld \n", (long)(rmx.rmx_expire - ts.tv_sec));
>> +}
>> +
>> +static void
>> +print_prefix(struct nl_helper *h, char *buf, int bufsize, struct =
sockaddr *sa, int plen)
>> +{
>> +	int sz =3D 0;
>> +
>> +	if (sa =3D=3D NULL) {
>> +		snprintf(buf, bufsize, "<NULL>");
>> +		return;
>> +	}
>> +
>> +	switch (sa->sa_family) {
>> +	case AF_INET:
>> +		{
>> +			struct sockaddr_in *sin =3D (struct sockaddr_in =
*)sa;
>> +			char abuf[INET_ADDRSTRLEN];
>> +
>> +			inet_ntop(AF_INET, &sin->sin_addr, abuf, =
sizeof(abuf));
>> +			sz =3D snprintf(buf, bufsize, "%s", abuf);
>> +			break;
>> +		}
>> +	case AF_INET6:
>> +		{
>> +			struct sockaddr_in6 *sin6 =3D (struct =
sockaddr_in6 *)sa;
>> +			char abuf[INET6_ADDRSTRLEN];
>> +			char *ifname =3D NULL;
>> +
>> +			inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, =
sizeof(abuf));
>> +			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
>> +				struct snl_parsed_link_simple link =3D =
{};
>> +
>> +				if (sin6->sin6_scope_id !=3D 0) {
>> +					get_ifdata(h, =
sin6->sin6_scope_id, &link);
>> +					ifname =3D link.ifla_ifname;
>> +				}
>> +			}
>> +			if (ifname =3D=3D NULL)
>> +				sz =3D snprintf(buf, bufsize, "%s", =
abuf);
>> +			else
>> +				sz =3D snprintf(buf, bufsize, "%s%%%s", =
abuf, ifname);
>> +			break;
>> +		}
>> +	default:
>> +		snprintf(buf, bufsize, "unknown_af#%d", sa->sa_family);
>> +		plen =3D -1;
>> +	}
>> +
>> +	if (plen >=3D 0)
>> +		snprintf(buf + sz, bufsize - sz, "/%d", plen);
>> +}
>> +
>> +
>> +static int
>> +print_line_prefix(const char *cmd, const char *name)
>> +{
>> +	struct timespec tp;
>> +	struct tm tm;
>> +	char buf[32];
>> +
>> +	clock_gettime(CLOCK_REALTIME, &tp);
>> +	localtime_r(&tp.tv_sec, &tm);
>> +
>> +	strftime(buf, sizeof(buf), "%T", &tm);
>> +	int len =3D printf("%s.%03ld %s %s ", buf, tp.tv_nsec / 1000000, =
cmd, name);
>> +
>> +	return (len);
>> +}
>> +
>> +static const char *
>> +get_action_name(struct nlmsghdr *hdr, int new_cmd)
>> +{
>> +	if (hdr->nlmsg_type =3D=3D new_cmd) {
>> +		//return ((hdr->nlmsg_flags & NLM_F_REPLACE) ? "replace" =
: "add");
>> +		return ("add/repl");
>> +	} else
>> +		return ("delete");
>> +}
>> +
>> +static void
>> +print_nlmsg_route_nhop(struct nl_helper *h, struct snl_parsed_route =
*r,
>> +    struct rta_mpath_nh *nh, bool first)
>> +{
>> +	// gw 10.0.0.1 ifp vtnet0 mtu 1500 table inet.0
>> +	if (nh->gw !=3D NULL) {
>> +		char gwbuf[128];
>> +		print_prefix(h, gwbuf, sizeof(gwbuf), nh->gw, -1);
>> +		printf("gw %s ", gwbuf);
>> +	}
>> +
>> +	if (nh->ifindex !=3D 0) {
>> +		struct snl_parsed_link_simple link =3D {};
>> +
>> +		get_ifdata(h, nh->ifindex, &link);
>> +		if (nh->rtax_mtu =3D=3D 0)
>> +			nh->rtax_mtu =3D link.ifla_mtu;
>> +		printf("iface %s ", link.ifla_ifname);
>> +		if (nh->rtax_mtu !=3D 0)
>> +			printf("mtu %d ", nh->rtax_mtu);
>> +	}
>> +
>> +	if (first) {
>> +		switch (r->rtm_family) {
>> +			case AF_INET:
>> +				printf("table inet.%d", r->rta_table);
>> +				break;
>> +			case AF_INET6:
>> +				printf("table inet6.%d", r->rta_table);
>> +				break;
>> +		}
>> +	}
>> +
>> +	printf("\n");
>> +}
>> +
>> +static void
>> +print_nlmsg_route(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +	struct snl_parsed_route r =3D { .rtax_weight =3D =
RT_DEFAULT_WEIGHT };
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +
>> +	if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
>> +		return;
>> +
>> +	// 20:19:41.333 add route 10.0.0.0/24 gw 10.0.0.1 ifp vtnet0 mtu =
1500 table inet.0
>> +
>> +	const char *cmd =3D get_action_name(hdr, RTM_NEWROUTE);
>> +	int len =3D print_line_prefix(cmd, "route");
>> +
>> +	char buf[128];
>> +	print_prefix(h, buf, sizeof(buf), r.rta_dst, r.rtm_dst_len);
>> +	len +=3D strlen(buf) + 1;
>> +	printf("%s ", buf);
>> +
>> +	switch (r.rtm_type) {
>> +	case RTN_BLACKHOLE:
>> +		printf("blackhole\n");
>> +		return;
>> +	case RTN_UNREACHABLE:
>> +		printf("unreach(reject)\n");
>> +		return;
>> +	case RTN_PROHIBIT:
>> +		printf("prohibit(reject)\n");
>> +		return;
>> +	}
>> +
>> +	if (r.rta_multipath !=3D NULL) {
>> +		bool first =3D true;
>> +
>> +		memset(buf, ' ', sizeof(buf));
>> +		buf[len] =3D '\0';
>> +
>> +		for (int i =3D 0; i < r.rta_multipath->num_nhops; i++) {
>> +			struct rta_mpath_nh *nh =3D =
&r.rta_multipath->nhops[i];
>> +
>> +			if (!first)
>> +				printf("%s", buf);
>> +			print_nlmsg_route_nhop(h, &r, nh, first);
>> +			first =3D false;
>> +		}
>> +	} else {
>> +		struct rta_mpath_nh nh =3D {
>> +			.gw =3D r.rta_gw,
>> +			.ifindex =3D r.rta_oif,
>> +			.rtax_mtu =3D r.rtax_mtu,
>> +		};
>> +
>> +		print_nlmsg_route_nhop(h, &r, &nh, true);
>> +	}
>> +}
>> +
>> +static const char *operstate[] =3D {
>> +	"UNKNOWN",	/* 0, IF_OPER_UNKNOWN */
>> +	"NOTPRESENT",	/* 1, IF_OPER_NOTPRESENT */
>> +	"DOWN",		/* 2, IF_OPER_DOWN */
>> +	"LLDOWN",	/* 3, IF_OPER_LOWERLAYERDOWN */
>> +	"TESTING",	/* 4, IF_OPER_TESTING */
>> +	"DORMANT",	/* 5, IF_OPER_DORMANT */
>> +	"UP",		/* 6, IF_OPER_UP */
>> +};
>> +
>> +static void
>> +print_nlmsg_link(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +	struct snl_parsed_link l =3D {};
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +
>> +	if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser, &l))
>> +		return;
>> +
>> +	// 20:19:41.333 add iface#3 vtnet0 admin UP oper UP mtu 1500 =
table inet.0
>> +	const char *cmd =3D get_action_name(hdr, RTM_NEWLINK);
>> +	print_line_prefix(cmd, "iface");
>> +
>> +	printf("iface#%u %s ", l.ifi_index, l.ifla_ifname);
>> +	printf("admin %s ", (l.ifi_flags & IFF_UP) ? "UP" : "DOWN");
>> +	if (l.ifla_operstate < NL_ARRAY_LEN(operstate))
>> +		printf("oper %s ", operstate[l.ifla_operstate]);
>> +	if (l.ifla_mtu > 0)
>> +		printf("mtu %u ", l.ifla_mtu);
>> +
>> +	printf("\n");
>> +}
>> +
>> +static void
>> +print_nlmsg_addr(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +	struct snl_parsed_addr attrs =3D {};
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +
>> +	if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &attrs))
>> +		return;
>> +
>> +	// add addr 192.168.1.1/24 iface vtnet0
>> +	const char *cmd =3D get_action_name(hdr, RTM_NEWADDR);
>> +	print_line_prefix(cmd, "addr");
>> +
>> +	char buf[128];
>> +	struct sockaddr *addr =3D attrs.ifa_local ? attrs.ifa_local : =
attrs.ifa_address;
>> +	print_prefix(h, buf, sizeof(buf), addr, attrs.ifa_prefixlen);
>> +	printf("%s ", buf);
>> +
>> +	struct snl_parsed_link_simple link =3D {};
>> +	get_ifdata(h, attrs.ifa_index, &link);
>> +
>> +	if (link.ifi_flags & IFF_POINTOPOINT) {
>> +		char buf[64];
>> +		print_prefix(h, buf, sizeof(buf), attrs.ifa_address, =
-1);
>> +		printf("-> %s ", buf);
>> +	}
>> +
>> +	printf("iface %s ", link.ifla_ifname);
>> +
>> +	printf("\n");
>> +}
>> +
>> +static const char *nudstate[] =3D {
>> +	"INCOMPLETE",		/* 0x01(0) */
>> +	"REACHABLE",		/* 0x02(1) */
>> +	"STALE",		/* 0x04(2) */
>> +	"DELAY",		/* 0x08(3) */
>> +	"PROBE",		/* 0x10(4) */
>> +	"FAILED",		/* 0x20(5) */
>> +};
>> +
>> +#define	NUD_INCOMPLETE		0x01	/* No lladdr, address =
resolution in progress */
>> +#define	NUD_REACHABLE		0x02	/* reachable & recently =
resolved */
>> +#define	NUD_STALE		0x04	/* has lladdr but it's =
stale */
>> +#define	NUD_DELAY		0x08	/* has lladdr, is stale, =
probes delayed */
>> +#define	NUD_PROBE		0x10	/* has lladdr, is stale, =
probes sent */
>> +#define	NUD_FAILED		0x20	/* unused */
>> +
>> +
>> +static void
>> +print_nlmsg_neigh(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +	struct snl_parsed_neigh attrs =3D {};
>> +	struct snl_state *ss =3D &h->ss_cmd;
>> +
>> +	if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_neigh_parser, &attrs))
>> +		return;
>> +
>> +	// add addr 192.168.1.1 state %s lladdr %s iface vtnet0
>> +	const char *cmd =3D get_action_name(hdr, RTM_NEWNEIGH);
>> +	print_line_prefix(cmd, "neigh");
>> +
>> +	char buf[128];
>> +	print_prefix(h, buf, sizeof(buf), attrs.nda_dst, -1);
>> +	printf("%s ", buf);
>> +
>> +	struct snl_parsed_link_simple link =3D {};
>> +	get_ifdata(h, attrs.nda_ifindex, &link);
>> +
>> +	for (unsigned int i =3D 0; i < NL_ARRAY_LEN(nudstate); i++) {
>> +		if ((1 << i) & attrs.ndm_state) {
>> +			printf("state %s ", nudstate[i]);
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (attrs.nda_lladdr !=3D NULL) {
>> +		int if_type =3D link.ifi_type;
>> +
>> +		if ((if_type =3D=3D IFT_ETHER || if_type =3D=3D =
IFT_L2VLAN || if_type =3D=3D IFT_BRIDGE) &&
>> +		    NLA_DATA_LEN(attrs.nda_lladdr) =3D=3D =
ETHER_ADDR_LEN) {
>> +			struct ether_addr *ll;
>> +
>> +			ll =3D (struct ether_addr =
*)NLA_DATA(attrs.nda_lladdr);
>> +			printf("lladdr %s ", ether_ntoa(ll));
>> +		} else {
>> +			struct sockaddr_dl sdl =3D {
>> +				.sdl_len =3D sizeof(sdl),
>> +				.sdl_family =3D AF_LINK,
>> +				.sdl_index =3D attrs.nda_ifindex,
>> +				.sdl_type =3D if_type,
>> +				.sdl_alen =3D =
NLA_DATA_LEN(attrs.nda_lladdr),
>> +			};
>> +			if (sdl.sdl_alen < sizeof(sdl.sdl_data)) {
>> +				void *ll =3D NLA_DATA(attrs.nda_lladdr);
>> +
>> +				memcpy(sdl.sdl_data, ll, sdl.sdl_alen);
>> +				printf("lladdr %s ", link_ntoa(&sdl));
>> +			}
>> +		}
>> +	}
>> +
>> +	if (link.ifla_ifname !=3D NULL)
>> +		printf("iface %s ", link.ifla_ifname);
>> +	printf("\n");
>> +}
>> +
>> +static void
>> +print_nlmsg_generic(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +}
>> +
>> +static void
>> +print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr)
>> +{
>> +	switch (hdr->nlmsg_type) {
>> +	case RTM_NEWLINK:
>> +	case RTM_DELLINK:
>> +		print_nlmsg_link(h, hdr);
>> +		break;
>> *** 184 LINES SKIPPED ***


--Apple-Mail=_AE460F85-A90B-4D1C-9453-E5B4D7CEC4B9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
	charset=utf-8

<html><head><meta http-equiv=3D"content-type" content=3D"text/html; =
charset=3Dutf-8"></head><body style=3D"overflow-wrap: break-word; =
-webkit-nbsp-mode: space; line-break: =
after-white-space;"><br><div><br><blockquote type=3D"cite"><div>On 27 =
Mar 2023, at 21:41, Jessica Clarke &lt;jrtc27@freebsd.org&gt; =
wrote:</div><br class=3D"Apple-interchange-newline"><div><meta =
charset=3D"UTF-8"><span style=3D"caret-color: rgb(0, 0, 0); font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: =
none; float: none; display: inline !important;">On 26 Mar 2023, at =
12:07, Alexander V. Chernikov &lt;</span><a =
href=3D"mailto:melifaro@FreeBSD.org" style=3D"font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant-caps: normal; =
font-weight: 400; letter-spacing: normal; orphans: auto; text-align: =
start; text-indent: 0px; text-transform: none; white-space: normal; =
widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; =
-webkit-text-stroke-width: 0px;">melifaro@FreeBSD.org</a><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;">&gt; wrote:</span><br style=3D"caret-color: =
rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: =
normal; font-variant-caps: normal; font-weight: 400; letter-spacing: =
normal; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
text-decoration: none;"><blockquote type=3D"cite" style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; orphans: auto; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; =
-webkit-text-stroke-width: 0px; text-decoration: none;"><br>The branch =
main has been updated by melifaro:<br><br>URL: =
https://cgit.FreeBSD.org/src/commit/?id=3Dc597432e22975f4d409b845377996712=
9c6b57e9<br><br>commit =
c597432e22975f4d409b8453779967129c6b57e9<br>Author: =
&nbsp;&nbsp;&nbsp;&nbsp;Alexander V. Chernikov =
&lt;melifaro@FreeBSD.org&gt;<br>AuthorDate: 2023-03-26 09:13:50 =
+0000<br>Commit: &nbsp;&nbsp;&nbsp;&nbsp;Alexander V. Chernikov =
&lt;melifaro@FreeBSD.org&gt;<br>CommitDate: 2023-03-26 11:06:56 =
+0000<br><br>&nbsp;&nbsp;route(8): convert to =
netlink<br><br>&nbsp;&nbsp;This change converts all kernel rtsock =
interactions in route(8)<br>&nbsp;&nbsp;&nbsp;to =
Netlink.<br><br>&nbsp;&nbsp;Based on the WITHOUT_NETLINK_SUPPORT =
src.conf(5) variable, route(8)<br>&nbsp;&nbsp;&nbsp;now fully operates =
either via Netlink or via rtsock/sysctl.<br>&nbsp;&nbsp;The default =
(compile-time) is Netlink.<br><br>&nbsp;&nbsp;The output for route =
delete/add/get/flush is targeted to be exactly<br>&nbsp;&nbsp;&nbsp;the =
same (apart from some error handling cases).<br>&nbsp;&nbsp;The output =
for the route monitor has been changed to =
improve<br>&nbsp;&nbsp;&nbsp;readability and support netlink =
models.<br><br>&nbsp;&nbsp;Other behaviour changes:<br>&nbsp;&nbsp;* =
exact prefix lookup (route -n get a.b.c.d/e) is not yet =
supported.<br>&nbsp;&nbsp;* route monitor does not show the change =
originator yet.<br></blockquote><br style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
text-decoration: none;"><span style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
text-decoration: none; float: none; display: inline !important;">If =
there are regressions then it should be off by default, =
*especially*</span><br style=3D"caret-color: rgb(0, 0, 0); font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: =
none;"></div></blockquote>Hi Jessica,</div><div>I have a plan to fix =
both this week. I=E2=80=99d also want to note that these two are not the =
documented / often used features.</div><div><blockquote =
type=3D"cite"><div><span style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
text-decoration: none; float: none; display: inline !important;">when =
we=E2=80=99re just under a month out from the proposed 14 code =
slush.</span><br style=3D"caret-color: rgb(0, 0, 0); font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: =
none;"><br style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant-caps: normal; =
font-weight: 400; letter-spacing: normal; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: =
none;"><span style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant-caps: normal; =
font-weight: 400; letter-spacing: normal; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: =
none; float: none; display: inline !important;">Jess</span><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;"><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;"><blockquote =
type=3D"cite" style=3D"font-family: Helvetica; font-size: 12px; =
font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: auto; text-align: start; text-indent: =
0px; text-transform: none; white-space: normal; widows: auto; =
word-spacing: 0px; -webkit-text-size-adjust: auto; =
-webkit-text-stroke-width: 0px; text-decoration: =
none;">&nbsp;&nbsp;Differential Revision: =
&nbsp;https://reviews.freebsd.org/D39007<br>---<br>sbin/route/Makefile =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &nbsp;&nbsp;6 =
+<br>sbin/route/route.c =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 117 =
+++++--<br>sbin/route/route_netlink.c | 835 =
+++++++++++++++++++++++++++++++++++++++++++++<br>3 files changed, 930 =
insertions(+), 28 deletions(-)<br><br>diff --git a/sbin/route/Makefile =
b/sbin/route/Makefile<br>index e65030f805bb..aec222310d46 100644<br>--- =
a/sbin/route/Makefile<br>+++ b/sbin/route/Makefile<br>@@ -19,6 +19,12 @@ =
CFLAGS+=3D -DINET6<br>.endif<br>CFLAGS+=3D -I.<br><br>+.if =
${MK_NETLINK_SUPPORT} !=3D "no"<br>+SRCS+=3D<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	=
</span>route_netlink.c<br>+.else<br>+CFLAGS+=3D-DWITHOUT_NETLINK<br>+.endi=
f<br>+<br>HAS_TESTS=3D<br>SUBDIR.${MK_TESTS}+=3D tests<br><br>diff --git =
a/sbin/route/route.c b/sbin/route/route.c<br>index =
5f33cecb1b20..947c97ce794a 100644<br>--- a/sbin/route/route.c<br>+++ =
b/sbin/route/route.c<br>@@ -90,12 +90,11 @@ static struct keytab =
{<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>{0, 0}<br>};<br><br>+int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>verbose, debugonly;<br>static =
struct sockaddr_storage so[RTAX_MAX];<br>static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>pid, =
rtm_addrs;<br>-static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>s;<br>-static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>nflag, =
af, qflag, tflag;<br>-static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>verbose, aflen;<br>-static =
int<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>locking, lockrest, debugonly;<br>+static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>nflag, =
af, aflen, qflag, tflag;<br>+static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>locking, lockrest;<br>static =
struct rt_metrics rt_metrics;<br>static u_long =
&nbsp;rtm_inits;<br>static uid_t<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>uid;<br>@@ -103,18 +102,30 @@ =
static int<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>defaultfib;<br>static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>numfibs;<br>static char<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>domain[MAXHOSTNAMELEN + 1];<br>static bool<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>domain_initialized;<br>-static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtm_seq;<br>static char<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rt_line[NI_MAXHOST];<br>static char<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>net_line[MAXHOSTNAMELEN + =
1];<br><br>+#ifdef WITHOUT_NETLINK<br>+static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>s;<br>+static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtm_seq;<br>+<br>static struct =
{<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>struct<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rt_msghdr m_rtm;<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>char<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>m_space[512];<br>} =
m_rtmsg;<br><br>+static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtmsg_rtsock(int, int, =
int);<br>+static int<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>flushroutes_fib_rtsock(int);<br>+static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>monitor_rtsock(void);<br>+#else<br>+int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtmsg_nl(int, int, int, struct sockaddr_storage *, struct =
rt_metrics *);<br>+int<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>flushroutes_fib_nl(int, int);<br>+void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>monitor_nl(int);<br>+#endif<br>+<br>static =
TAILQ_HEAD(fibl_head_t, fibl) fibl_head;<br><br>-static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printb(int, const char *);<br>+void<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printb(int, const char =
*);<br>static void<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>flushroutes(int argc, char *argv[]);<br>static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>flushroutes_fib(int);<br>static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>getaddr(int, char *, int);<br>@@ =
-127,7 +138,7 @@ static int<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>inet6_makenetandmask(struct =
sockaddr_in6 *, const char *);<br>#endif<br>static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>interfaces(void);<br>static void<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>monitor(int, char*[]);<br>-static =
const char<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>*netname(struct sockaddr *);<br>+const char<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>*netname(struct sockaddr *);<br>static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>newroute(int, char **);<br>static int<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>newroute_fib(int, char *, =
int);<br>static void<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>pmsg_addrs(char *, int, size_t);<br>@@ -135,7 +146,7 @@ =
static void<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>pmsg_common(struct rt_msghdr *, size_t);<br>static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>prefixlen(const char *);<br>static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_getmsg(struct rt_msghdr *, int, int);<br>static void<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_rtmsg(struct rt_msghdr *, size_t);<br>-static const =
char<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>*routename(struct sockaddr *);<br>+const char<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>*routename(struct sockaddr *);<br>static int<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtmsg(int, int, int);<br>static void<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>set_metric(char *, =
int);<br>static int<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>set_sofib(int);<br>@@ -216,12 +227,14 @@ main(int argc, =
char **argv)<br><br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>pid =3D getpid();<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>uid =3D geteuid();<br>+#ifdef =
WITHOUT_NETLINK<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (tflag)<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>s =3D open(_PATH_DEVNULL, =
O_WRONLY, 0);<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>else<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>s =3D socket(PF_ROUTE, SOCK_RAW, =
0);<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (s &lt; 0)<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>err(EX_OSERR, =
"socket");<br>+#endif<br><br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>len =3D sizeof(numfibs);<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(sysctlbyname("net.fibs", (void *)&amp;numfibs, &amp;len, NULL, 0) =3D=3D =
-1)<br>@@ -264,10 +277,14 @@ static int<br>set_sofib(int =
fib)<br>{<br><br>+#ifdef WITHOUT_NETLINK<br><span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>if (fib &lt; 0)<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(0);<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void =
*)&amp;fib,<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;sizeof(fib)=
));<br>+#else<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (0);<br>+#endif<br>}<br><br>static int<br>@@ =
-395,7 +412,9 @@ flushroutes(int argc, char *argv[])<br><br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if (uid =
!=3D 0 &amp;&amp; !debugonly &amp;&amp; !tflag)<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>errx(EX_NOPERM, "must be root to alter routing =
table");<br>+#ifdef WITHOUT_NETLINK<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>shutdown(s, SHUT_RD); /* Don't =
want to read back our messages */<br>+#endif<br><br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>TAILQ_INIT(&amp;fibl_head);<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>while (argc &gt; 1) {<br>@@ =
-441,6 +460,17 @@ flushroutes(int argc, char *argv[])<br><br>static =
int<br>flushroutes_fib(int fib)<br>+{<br>+#ifdef =
WITHOUT_NETLINK<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (flushroutes_fib_rtsock(fib));<br>+#else<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(flushroutes_fib_nl(fib, af));<br>+#endif<br>+}<br>+<br>+#ifdef =
WITHOUT_NETLINK<br>+static int<br>+flushroutes_fib_rtsock(int =
fib)<br>{<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>struct rt_msghdr *rtm;<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>size_t needed;<br>@@ -525,8 =
+555,9 @@ retry:<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>free(buf);<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return =
(error);<br>}<br>+#endif<br><br>-static const char *<br>+const char =
*<br>routename(struct sockaddr *sa)<br>{<br><span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>struct sockaddr_dl *sdl;<br>@@ =
-645,7 +676,7 @@ routename(struct sockaddr *sa)<br>* Return the name of =
the network whose address is given.<br>* The address is assumed to be =
that of a net, not a host.<br>*/<br>-static const char *<br>+const char =
*<br>netname(struct sockaddr *sa)<br>{<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr_dl *sdl;<br>@@ =
-810,8 +841,10 @@ newroute(int argc, char **argv)<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>warn("sigaction SIGALRM");<br><br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>cmd =3D argv[0];<br>+#ifdef =
WITHOUT_NETLINK<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (*cmd !=3D 'g' &amp;&amp; *cmd !=3D 's')<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>shutdown(s, SHUT_RD); /* Don't want to read back our messages =
*/<br>+#endif<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>while (--argc &gt; 0) {<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (**(++argv)=3D=3D '-') =
{<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>switch (key =3D keyword(1 + *argv)) {<br>@@ -1398,8 +1431,8 @@ =
retry2:<br>static void<br>monitor(int argc, char *argv[])<br>{<br>-<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int n, =
fib, error;<br>-<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>char msg[2048], *endptr;<br>+<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>int fib, error;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
*endptr;<br><br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>fib =3D defaultfib;<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>while (argc &gt; 1) {<br>@@ =
-1435,6 +1468,19 @@ monitor(int argc, char *argv[])<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>interfaces();<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>exit(0);<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+#ifdef WITHOUT_NETLINK<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	=
</span>monitor_rtsock();<br>+#else<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	=
</span>monitor_nl(fib);<br>+#endif<br>+}<br>+<br>+#ifdef =
WITHOUT_NETLINK<br>+static void<br>+monitor_rtsock(void)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
msg[2048];<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>int n;<br><br>#ifdef SO_RERROR<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>n =3D =
1;<br>@@ -1454,25 +1500,12 @@ monitor(int argc, char *argv[])<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_rtmsg((struct rt_msghdr *)(void *)msg, n);<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>}<br>+#endif<br><br>static int<br>rtmsg(int cmd, int flags, =
int fib)<br>{<br>-<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>int rlen;<br>-<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>char *cp =3D =
m_rtmsg.m_space;<br>-<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>int l;<br>-<br>-#define NEXTADDR(w, u)<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>\<br>-<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (rtm_addrs &amp; (w)) {<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>\<br>-<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>l =3D =
SA_SIZE(&amp;(u));<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>\<br>-<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>memmove(cp, (char *)&amp;(u), l);<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>\<br>-<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>cp +=3D l;<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>\<br>-<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (verbose)<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>\<br>-<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>sodump((struct sockaddr *)&amp;(u), #w);<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>\<br>-<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>-<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>errno =3D 0;<br>-<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>memset(&amp;m_rtmsg, 0, =
sizeof(m_rtmsg));<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (cmd =3D=3D 'a')<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>cmd =3D RTM_ADD;<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>else if =
(cmd =3D=3D 'c')<br>@@ -1488,6 +1521,33 @@ rtmsg(int cmd, int flags, int =
fib)<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>cmd =3D RTM_DELETE;<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>flags |=3D RTF_PINNED;<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+#ifdef WITHOUT_NETLINK<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return (rtmsg_rtsock(cmd, flags, =
fib));<br>+#else<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>errno =3D rtmsg_nl(cmd, flags, fib, so, =
&amp;rt_metrics);<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>return (errno =3D=3D 0 ? 0 : =
-1);<br>+#endif<br>+}<br>+<br>+#ifdef WITHOUT_NETLINK<br>+static =
int<br>+rtmsg_rtsock(int cmd, int flags, int fib)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int =
rlen;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>char *cp =3D m_rtmsg.m_space;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>int l;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>memset(&amp;m_rtmsg, 0, sizeof(m_rtmsg));<br>+<br>+#define =
NEXTADDR(w, u)<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>\<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (rtm_addrs &amp; (w)) {<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>\<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>l =3D =
SA_SIZE(&amp;(u));<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>\<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>memmove(cp, (char *)&amp;(u), l);<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>\<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>cp +=3D l;<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>\<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (verbose)<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>\<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>sodump((struct sockaddr *)&amp;(u), #w);<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>\<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>#define rtm m_rtmsg.m_rtm<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtm.rtm_type =3D cmd;<br><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtm.rtm_flags =3D flags;<br>@@ =
-1545,6 +1605,7 @@ rtmsg(int cmd, int flags, int fib)<br>#undef =
rtm<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return (0);<br>}<br>+#endif<br><br>static const char *const =
msgtypes[] =3D {<br><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>"",<br>@@ -1571,7 +1632,7 @@ static const char *const =
msgtypes[] =3D {<br>static const char metricnames[] =
=3D<br>&nbsp;&nbsp;&nbsp;"\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4r=
ecvpipe\3expire"<br>&nbsp;&nbsp;&nbsp;"\1mtu";<br>-static const char =
routeflags[] =3D<br>+const char routeflags[] =
=3D<br>&nbsp;&nbsp;&nbsp;"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7=
DONE"<br>&nbsp;&nbsp;&nbsp;"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"=
<br>&nbsp;&nbsp;&nbsp;"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023P=
ROTO3"<br>@@ -1812,7 +1873,7 @@ pmsg_addrs(char *cp, int addrs, size_t =
len)<br><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>(void)fflush(stdout);<br>}<br><br>-static =
void<br>+void<br>printb(int b, const char *str)<br>{<br><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int =
i;<br>diff --git a/sbin/route/route_netlink.c =
b/sbin/route/route_netlink.c<br>new file mode 100644<br>index =
000000000000..648d866670fc<br>--- /dev/null<br>+++ =
b/sbin/route/route_netlink.c<br>@@ -0,0 +1,835 @@<br>+#include =
&lt;stdio.h&gt;<br>+#include &lt;stdlib.h&gt;<br>+#include =
&lt;string.h&gt;<br>+#include &lt;err.h&gt;<br>+#include =
&lt;errno.h&gt;<br>+<br>+#include &lt;sys/bitcount.h&gt;<br>+#include =
&lt;sys/param.h&gt;<br>+#include &lt;sys/socket.h&gt;<br>+#include =
&lt;sys/sysctl.h&gt;<br>+#include &lt;sys/time.h&gt;<br>+#include =
&lt;sys/types.h&gt;<br>+<br>+#include &lt;netinet/in.h&gt;<br>+#include =
&lt;arpa/inet.h&gt;<br>+<br>+#include =
&lt;net/ethernet.h&gt;<br>+#include &lt;net/if.h&gt;<br>+#include =
&lt;net/if_dl.h&gt;<br>+#include &lt;net/if_types.h&gt;<br>+#include =
&lt;netlink/netlink.h&gt;<br>+#include =
&lt;netlink/netlink_route.h&gt;<br>+#include =
&lt;netlink/netlink_snl.h&gt;<br>+#include =
&lt;netlink/netlink_snl_route.h&gt;<br>+#include =
&lt;netlink/netlink_snl_route_compat.h&gt;<br>+#include =
&lt;netlink/netlink_snl_route_parsers.h&gt;<br>+<br>+const char =
*routename(struct sockaddr *);<br>+const char *netname(struct sockaddr =
*);<br>+void printb(int, const char *);<br>+extern const char =
routeflags[];<br>+extern int verbose, debugonly;<br>+<br>+int =
rtmsg_nl(int cmd, int rtm_flags, int fib, struct sockaddr_storage =
*so,<br>+ &nbsp;&nbsp;&nbsp;struct rt_metrics *rt_metrics);<br>+int =
flushroutes_fib_nl(int fib, int af);<br>+void monitor_nl(int =
fib);<br>+<br>+struct nl_helper;<br>+static void print_getmsg(struct =
nl_helper *h, struct nlmsghdr *hdr, struct sockaddr *dst);<br>+static =
void print_nlmsg(struct nl_helper *h, struct nlmsghdr =
*hdr);<br>+<br>+#define s6_addr32 __u6_addr.__u6_addr32<br>+#define<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>bitcount32(x)<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>__bitcount32((uint32_t)(x))<br>+static =
int<br>+inet6_get_plen(const struct in6_addr *addr)<br>+{<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(bitcount32(addr-&gt;s6_addr32[0]) + bitcount32(addr-&gt;s6_addr32[1]) =
+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;bitcount32(=
addr-&gt;s6_addr32[2]) + =
bitcount32(addr-&gt;s6_addr32[3]));<br>+}<br>+<br>+static =
void<br>+ip6_writemask(struct in6_addr *addr6, uint8_t =
mask)<br>+{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>uint32_t *cp;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>for (cp =3D (uint32_t *)addr6; =
mask &gt;=3D 32; mask -=3D 32)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>*cp++ =3D 0xFFFFFFFF;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if (mask =
&gt; 0)<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>*cp =3D htonl(mask ? ~((1 &lt;&lt; (32 - mask)) - 1) : =
0);<br>+}<br>+<br>+static struct sockaddr *<br>+get_netmask(struct =
snl_state *ss, int family, int plen)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(family =3D=3D AF_INET) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (plen =3D=3D 32)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(NULL);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct sockaddr_in *sin =3D snl_allocz(ss, =
sizeof(*sin));<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>sin-&gt;sin_len =3D =
sizeof(*sin);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>sin-&gt;sin_family =3D family;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>sin-&gt;sin_addr.s_addr =3D htonl(plen ? ~((1 &lt;&lt; (32 - =
plen)) - 1) : 0);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return (struct sockaddr =
*)sin;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>} else if (family =3D=3D AF_INET6) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if (plen =
=3D=3D 128)<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (NULL);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr_in6 *sin6 =3D =
snl_allocz(ss, sizeof(*sin6));<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>sin6-&gt;sin6_len =3D =
sizeof(*sin6);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>sin6-&gt;sin6_family =3D family;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>ip6_writemask(&amp;sin6-&gt;sin6_addr, plen);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(struct sockaddr *)sin6;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(NULL);<br>+}<br>+<br>+struct nl_helper {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
snl_state ss_cmd;<br>+};<br>+<br>+static void<br>+nl_helper_init(struct =
nl_helper *h)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (!snl_init(&amp;h-&gt;ss_cmd, =
NETLINK_ROUTE))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>err(1, "unable to open netlink =
socket");<br>+}<br>+<br>+static void<br>+nl_helper_free(struct nl_helper =
*h)<br>+{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>snl_free(&amp;h-&gt;ss_cmd);<br>+}<br>+<br>+static =
int<br>+rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int =
fib,<br>+ &nbsp;&nbsp;&nbsp;struct sockaddr_storage *so, struct =
rt_metrics *rt_metrics)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_state *ss =3D =
&amp;h-&gt;ss_cmd;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_writer nw;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int =
nl_type =3D 0, nl_flags =3D 0;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_init_writer(ss, =
&amp;nw);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>switch (cmd) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case RTSOCK_RTM_ADD:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>nl_type =3D=
 RTM_NEWROUTE;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>nl_flags =3D NLM_F_CREATE | NLM_F_APPEND; /* Do append by =
default */<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>break;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case RTSOCK_RTM_CHANGE:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>nl_type =3D=
 RTM_NEWROUTE;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>nl_flags =3D NLM_F_REPLACE;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>break;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>case RTSOCK_RTM_DELETE:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>nl_type =3D =
RTM_DELROUTE;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>break;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case RTSOCK_RTM_GET:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>nl_type =3D=
 RTM_GETROUTE;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>break;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>default:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>exit(1);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>}<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr *dst =3D (struct =
sockaddr *)&amp;so[RTAX_DST];<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr *mask =3D (struct =
sockaddr *)&amp;so[RTAX_NETMASK];<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr *gw =3D (struct =
sockaddr *)&amp;so[RTAX_GATEWAY];<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (dst =3D=3D NULL)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
(EINVAL);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct nlmsghdr *hdr =3D snl_create_msg_request(&amp;nw, =
nl_type);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>hdr-&gt;nlmsg_flags |=3D nl_flags;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int plen =
=3D 0;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>int rtm_type =3D RTN_UNICAST;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>switch =
(dst-&gt;sa_family) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case AF_INET:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;{<br>+<span=
 class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
sockaddr_in *mask4 =3D (struct sockaddr_in *)mask;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>plen =3D =
mask4 ? bitcount32(mask4-&gt;sin_addr.s_addr) : 32;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>break;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;}<br>+<span=
 class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>case =
AF_INET6:<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;{<br>+<span=
 class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
sockaddr_in6 *mask6 =3D (struct sockaddr_in6 *)mask;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>plen =3D =
mask6 ? inet6_get_plen(&amp;mask6-&gt;sin6_addr) : 128;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>break;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;}<br>+<span=
 class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>default:<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (ENOTSUP);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(rtm_flags &amp; RTF_REJECT)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtm_type =3D =
RTN_PROHIBIT;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>else if (rtm_flags &amp; RTF_BLACKHOLE)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>rtm_type =
=3D RTN_BLACKHOLE;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct rtmsg *rtm =3D =
snl_reserve_msg_object(&amp;nw, struct rtmsg);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtm-&gt;rtm_family =3D dst-&gt;sa_family;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtm-&gt;rtm_protocol =3D RTPROT_STATIC;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>rtm-&gt;rtm_type =3D rtm_type;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>rtm-&gt;rtm_dst_len =3D =
plen;<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>snl_add_msg_attr_ip(&amp;nw, RTA_DST, dst);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snl_add_msg_attr_u32(&amp;nw, RTA_TABLE, fib);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(rtm_flags &amp; RTF_GATEWAY) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (gw-&gt;sa_family =3D=3D =
dst-&gt;sa_family)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_add_msg_attr_ip(&amp;nw, =
RTA_GATEWAY, gw);<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>else<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_add_msg_attr_ipvia(&amp;nw, =
RTA_VIA, gw);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>} else if (gw !=3D NULL) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* Should =
be AF_LINK */<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct sockaddr_dl *sdl =3D (struct sockaddr_dl =
*)gw;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (sdl-&gt;sdl_index !=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_add_msg_attr_u32(&amp;nw, =
RTA_OIF, sdl-&gt;sdl_index);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(rtm_flags !=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_add_msg_attr_u32(&amp;nw, =
NL_RTA_RTFLAGS, rtm_flags);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (rt_metrics-&gt;rmx_mtu &gt; =
0) {<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>int off =3D snl_add_msg_attr_nested(&amp;nw, =
RTA_METRICS);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>snl_add_msg_attr_u32(&amp;nw, RTAX_MTU, =
rt_metrics-&gt;rmx_mtu);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snl_end_attr_nested(&amp;nw, =
off);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (rt_metrics-&gt;rmx_weight &gt; 0)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snl_add_msg_attr_u32(&amp;nw, NL_RTA_WEIGHT, =
rt_metrics-&gt;rmx_weight);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (snl_finalize_msg(&amp;nw) =
&amp;&amp; snl_send_message(ss, hdr)) {<br>+<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_errmsg_data e =3D =
{};<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>hdr =3D snl_read_reply(ss, hdr-&gt;nlmsg_seq);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(nl_type =3D=3D NL_RTM_GETROUTE) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (hdr-&gt;nlmsg_type =3D=3D =
NL_RTM_NEWROUTE)<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>print_getmsg(h, hdr, dst);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>else =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snl_parse_errmsg(ss, hdr, &amp;e);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(e.error =3D=3D ESRCH)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>warn("route has not been =
found");<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>else<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>warn("message indicates error %d", e.error);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (0);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(snl_parse_errmsg(ss, hdr, &amp;e))<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return (e.error);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return (EINVAL);<br>+}<br>+<br>+int<br>+rtmsg_nl(int cmd, int =
rtm_flags, int fib, struct sockaddr_storage *so,<br>+ =
&nbsp;&nbsp;&nbsp;struct rt_metrics *rt_metrics)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
nl_helper h =3D {};<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>nl_helper_init(&amp;h);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int error =
=3D rtmsg_nl_int(&amp;h, cmd, rtm_flags, fib, so, rt_metrics);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>nl_helper_free(&amp;h);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return =
(error);<br>+}<br>+<br>+static void<br>+get_ifdata(struct nl_helper *h, =
uint32_t ifindex, struct snl_parsed_link_simple *link)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
snl_state *ss =3D &amp;h-&gt;ss_cmd;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_writer =
nw;<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snl_init_writer(ss, &amp;nw);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct nlmsghdr *hdr =3D =
snl_create_msg_request(&amp;nw, NL_RTM_GETLINK);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
ifinfomsg *ifmsg =3D snl_reserve_msg_object(&amp;nw, struct =
ifinfomsg);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (ifmsg !=3D NULL)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>ifmsg-&gt;ifi_index =3D =
ifindex;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (!snl_finalize_msg(&amp;nw) || !snl_send_message(ss, =
hdr))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>hdr =3D snl_read_reply(ss, =
hdr-&gt;nlmsg_seq);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (hdr !=3D NULL &amp;&amp; =
hdr-&gt;nlmsg_type =3D=3D RTM_NEWLINK) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snl_parse_nlmsg(ss, hdr, &amp;snl_rtm_link_parser_simple, =
link);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (link-&gt;ifla_ifname =3D=3D NULL) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
ifname[16];<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>snprintf(ifname, sizeof(ifname), "if#%u", =
ifindex);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>int len =3D strlen(ifname);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char *buf =
=3D snl_allocz(ss, len + 1);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>strlcpy(buf, ifname, len + =
1);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>link-&gt;ifla_ifname =3D buf;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+}<br>+<br>+static =
void<br>+print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct =
sockaddr *dst)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_state *ss =3D =
&amp;h-&gt;ss_cmd;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct timespec ts;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
snl_parsed_route r =3D { .rtax_weight =3D RT_DEFAULT_WEIGHT =
};<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (!snl_parse_nlmsg(ss, hdr, &amp;snl_rtm_route_parser, =
&amp;r))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_parsed_link_simple =
link =3D {};<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>get_ifdata(h, r.rta_oif, &amp;link);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(r.rtax_mtu =3D=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>r.rtax_mtu =3D =
link.ifla_mtu;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>r.rta_rtflags |=3D (RTF_UP | RTF_DONE);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>(void)printf(" &nbsp;&nbsp;route to: %s\n", =
routename(dst));<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (r.rta_dst)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>(void)printf("destination: %s\n", =
routename(r.rta_dst));<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr *mask =3D =
get_netmask(ss, r.rtm_family, r.rtm_dst_len);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(mask)<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>(void)printf(" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mask: %s\n", =
routename(mask));<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>if (r.rta_gw &amp;&amp; (r.rta_rtflags &amp; =
RTF_GATEWAY))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>(void)printf(" &nbsp;&nbsp;&nbsp;gateway: %s\n", =
routename(r.rta_gw));<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>(void)printf(" =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fib: %u\n", (unsigned =
int)r.rta_table);<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>if (link.ifla_ifname)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>(void)printf(" &nbsp;interface: =
%s\n", link.ifla_ifname);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>(void)printf(" =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flags: ");<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printb(r.rta_rtflags, routeflags);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
rt_metrics rmx =3D {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>.rmx_mtu =3D =
r.rtax_mtu,<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>.rmx_weight =3D r.rtax_weight,<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>.rmx_expire =3D r.rta_expire,<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>};<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("\n%9s %9s %9s %9s %9s %10s %9s\n", "recvpipe",<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;"sendpipe",=
 "ssthresh", "rtt,msec", "mtu &nbsp;&nbsp;", "weight", =
"expire");<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("%8lu &nbsp;", rmx.rmx_recvpipe);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("%8lu &nbsp;", rmx.rmx_sendpipe);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("%8lu &nbsp;", rmx.rmx_ssthresh);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("%8lu &nbsp;", 0UL);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("%8lu &nbsp;", =
rmx.rmx_mtu);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("%8lu &nbsp;", rmx.rmx_weight);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(rmx.rmx_expire &gt; 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	=
</span>clock_gettime(CLOCK_REALTIME_FAST, &amp;ts);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>else<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>ts.tv_sec =3D 0;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("%8ld \n", =
(long)(rmx.rmx_expire - ts.tv_sec));<br>+}<br>+<br>+static =
void<br>+print_prefix(struct nl_helper *h, char *buf, int bufsize, =
struct sockaddr *sa, int plen)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>int sz =3D 0;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if (sa =3D=3D=
 NULL) {<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>snprintf(buf, bufsize, "&lt;NULL&gt;");<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>}<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>switch (sa-&gt;sa_family) =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>case AF_INET:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
sockaddr_in *sin =3D (struct sockaddr_in *)sa;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
abuf[INET_ADDRSTRLEN];<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>inet_ntop(AF_INET, =
&amp;sin-&gt;sin_addr, abuf, sizeof(abuf));<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>sz =3D =
snprintf(buf, bufsize, "%s", abuf);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>break;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>case AF_INET6:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
sockaddr_in6 *sin6 =3D (struct sockaddr_in6 *)sa;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
abuf[INET6_ADDRSTRLEN];<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>char *ifname =3D =
NULL;<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>inet_ntop(AF_INET6, &amp;sin6-&gt;sin6_addr, abuf, =
sizeof(abuf));<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (IN6_IS_ADDR_LINKLOCAL(&amp;sin6-&gt;sin6_addr)) =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>struct snl_parsed_link_simple link =3D {};<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(sin6-&gt;sin6_scope_id !=3D 0) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>get_ifdata(h, =
sin6-&gt;sin6_scope_id, &amp;link);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>ifname =3D =
link.ifla_ifname;<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (ifname =3D=3D NULL)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>sz =3D snprintf(buf, bufsize, =
"%s", abuf);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>else<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>sz =3D snprintf(buf, bufsize, =
"%s%%%s", abuf, ifname);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>break;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>default:<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>snprintf(buf, bufsize, "unknown_af#%d", =
sa-&gt;sa_family);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>plen =3D -1;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (plen &gt;=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>snprintf(buf + sz, bufsize - sz, =
"/%d", plen);<br>+}<br>+<br>+<br>+static int<br>+print_line_prefix(const =
char *cmd, const char *name)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct timespec tp;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct tm =
tm;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>char buf[32];<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>clock_gettime(CLOCK_REALTIME, =
&amp;tp);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>localtime_r(&amp;tp.tv_sec, &amp;tm);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>strftime(buf, sizeof(buf), "%T", &amp;tm);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int len =3D=
 printf("%s.%03ld %s %s ", buf, tp.tv_nsec / 1000000, cmd, =
name);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return (len);<br>+}<br>+<br>+static const char =
*<br>+get_action_name(struct nlmsghdr *hdr, int new_cmd)<br>+{<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(hdr-&gt;nlmsg_type =3D=3D new_cmd) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>//return ((hdr-&gt;nlmsg_flags =
&amp; NLM_F_REPLACE) ? "replace" : "add");<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>return =
("add/repl");<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>} else<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return =
("delete");<br>+}<br>+<br>+static void<br>+print_nlmsg_route_nhop(struct =
nl_helper *h, struct snl_parsed_route *r,<br>+ &nbsp;&nbsp;&nbsp;struct =
rta_mpath_nh *nh, bool first)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>// gw 10.0.0.1 ifp vtnet0 mtu =
1500 table inet.0<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>if (nh-&gt;gw !=3D NULL) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
gwbuf[128];<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>print_prefix(h, gwbuf, sizeof(gwbuf), nh-&gt;gw, =
-1);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("gw %s ", gwbuf);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(nh-&gt;ifindex !=3D 0) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_parsed_link_simple =
link =3D {};<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>get_ifdata(h, nh-&gt;ifindex, &amp;link);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(nh-&gt;rtax_mtu =3D=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>nh-&gt;rtax_mtu =3D =
link.ifla_mtu;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("iface %s ", link.ifla_ifname);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(nh-&gt;rtax_mtu !=3D 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("mtu %d ", =
nh-&gt;rtax_mtu);<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>}<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (first) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>switch =
(r-&gt;rtm_family) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case AF_INET:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("table inet.%d", r-&gt;rta_table);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>break;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>case AF_INET6:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("table inet6.%d", =
r-&gt;rta_table);<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>break;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("\n");<br>+}<br>+<br>+static =
void<br>+print_nlmsg_route(struct nl_helper *h, struct nlmsghdr =
*hdr)<br>+{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct snl_parsed_route r =3D { .rtax_weight =3D =
RT_DEFAULT_WEIGHT };<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_state *ss =3D =
&amp;h-&gt;ss_cmd;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (!snl_parse_nlmsg(ss, hdr, =
&amp;snl_rtm_route_parser, &amp;r))<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>// =
20:19:41.333 add route 10.0.0.0/24 gw 10.0.0.1 ifp vtnet0 mtu 1500 table =
inet.0<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>const char *cmd =3D get_action_name(hdr, =
RTM_NEWROUTE);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>int len =3D print_line_prefix(cmd, =
"route");<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>char buf[128];<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>print_prefix(h, buf, sizeof(buf), =
r.rta_dst, r.rtm_dst_len);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>len +=3D strlen(buf) + =
1;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("%s ", buf);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>switch (r.rtm_type) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>case =
RTN_BLACKHOLE:<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("blackhole\n");<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>case =
RTN_UNREACHABLE:<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("unreach(reject)\n");<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>case RTN_PROHIBIT:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	=
</span>printf("prohibit(reject)\n");<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>return;<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (r.rta_multipath !=3D NULL) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>bool =
first =3D true;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>memset(buf, ' ', =
sizeof(buf));<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>buf[len] =3D '\0';<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>for (int i =3D 0; i &lt; =
r.rta_multipath-&gt;num_nhops; i++) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct rta_mpath_nh *nh =3D =
&amp;r.rta_multipath-&gt;nhops[i];<br>+<br>+<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if (!first)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("%s", buf);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>print_nlmsg_route_nhop(h, &amp;r, =
nh, first);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>first =3D false;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>} else =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>struct rta_mpath_nh nh =3D {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>.gw =3D r.rta_gw,<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>.ifindex =
=3D r.rta_oif,<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>.rtax_mtu =3D r.rtax_mtu,<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>};<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>print_nlmsg_route_nhop(h, &amp;r, &amp;nh, =
true);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+}<br>+<br>+static const char *operstate[] =3D {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>"UNKNOWN",<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* 0, IF_OPER_UNKNOWN */<br>+<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>"NOTPRESENT",<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* 1, =
IF_OPER_NOTPRESENT */<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>"DOWN",<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* 2, =
IF_OPER_DOWN */<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>"LLDOWN",<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* 3, IF_OPER_LOWERLAYERDOWN =
*/<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>"TESTING",<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* 4, IF_OPER_TESTING */<br>+<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span>"DORMANT",<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* 5, =
IF_OPER_DORMANT */<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>"UP",<span class=3D"Apple-tab-span"=
 style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* 6, IF_OPER_UP =
*/<br>+};<br>+<br>+static void<br>+print_nlmsg_link(struct nl_helper *h, =
struct nlmsghdr *hdr)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct snl_parsed_link l =3D =
{};<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>struct snl_state *ss =3D &amp;h-&gt;ss_cmd;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(!snl_parse_nlmsg(ss, hdr, &amp;snl_rtm_link_parser, &amp;l))<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>return;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>// 20:19:41.333 add iface#3 =
vtnet0 admin UP oper UP mtu 1500 table inet.0<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>const =
char *cmd =3D get_action_name(hdr, RTM_NEWLINK);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_line_prefix(cmd, "iface");<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("iface#%u %s ", l.ifi_index, l.ifla_ifname);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("admin %s ", (l.ifi_flags &amp; IFF_UP) ? "UP" : =
"DOWN");<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>if (l.ifla_operstate &lt; NL_ARRAY_LEN(operstate))<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("oper %s ", operstate[l.ifla_operstate]);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(l.ifla_mtu &gt; 0)<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("mtu %u ", =
l.ifla_mtu);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space:=
 pre;">	</span>printf("\n");<br>+}<br>+<br>+static =
void<br>+print_nlmsg_addr(struct nl_helper *h, struct nlmsghdr =
*hdr)<br>+{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct snl_parsed_addr attrs =3D {};<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
snl_state *ss =3D &amp;h-&gt;ss_cmd;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(!snl_parse_nlmsg(ss, hdr, &amp;snl_rtm_addr_parser, =
&amp;attrs))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>// add addr 192.168.1.1/24 iface =
vtnet0<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>const char *cmd =3D get_action_name(hdr, RTM_NEWADDR);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_line_prefix(cmd, "addr");<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
buf[128];<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct sockaddr *addr =3D attrs.ifa_local ? =
attrs.ifa_local : attrs.ifa_address;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>print_prefix(h, buf, sizeof(buf), =
addr, attrs.ifa_prefixlen);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("%s ", =
buf);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct snl_parsed_link_simple link =3D {};<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>get_ifdata(h, attrs.ifa_index, &amp;link);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(link.ifi_flags &amp; IFF_POINTOPOINT) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>char =
buf[64];<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_prefix(h, buf, sizeof(buf), attrs.ifa_address, =
-1);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("-&gt; %s ", buf);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("iface %s ", link.ifla_ifname);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("\n");<br>+}<br>+<br>+static const char *nudstate[] =3D =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>"INCOMPLETE",<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* 0x01(0) */<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>"REACHABLE",<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* =
0x02(1) */<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>"STALE",<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* 0x04(2) */<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>"DELAY",<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* 0x08(3) */<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>"PROBE",<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* =
0x10(4) */<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>"FAILED",<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* 0x20(5) =
*/<br>+};<br>+<br>+#define<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>NUD_INCOMPLETE<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>0x01<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>/* No =
lladdr, address resolution in progress */<br>+#define<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>NUD_REACHABLE<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>0x02<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* reachable &amp; recently resolved */<br>+#define<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>NUD_STALE<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>0x04<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* has lladdr but it's stale */<br>+#define<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>NUD_DELAY<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>0x08<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>/* has lladdr, is stale, probes delayed =
*/<br>+#define<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>NUD_PROBE<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>0x10<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* has lladdr, is stale, probes =
sent */<br>+#define<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>NUD_FAILED<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>0x20<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>/* unused */<br>+<br>+<br>+static =
void<br>+print_nlmsg_neigh(struct nl_helper *h, struct nlmsghdr =
*hdr)<br>+{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct snl_parsed_neigh attrs =3D {};<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
snl_state *ss =3D &amp;h-&gt;ss_cmd;<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if =
(!snl_parse_nlmsg(ss, hdr, &amp;snl_rtm_neigh_parser, =
&amp;attrs))<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>return;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>// add addr 192.168.1.1 state %s =
lladdr %s iface vtnet0<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>const char *cmd =3D =
get_action_name(hdr, RTM_NEWNEIGH);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>print_line_prefix(cmd, =
"neigh");<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>char buf[128];<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>print_prefix(h, buf, sizeof(buf), =
attrs.nda_dst, -1);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("%s ", =
buf);<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>struct snl_parsed_link_simple link =3D {};<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>get_ifdata(h, attrs.nda_ifindex, &amp;link);<br>+<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>for =
(unsigned int i =3D 0; i &lt; NL_ARRAY_LEN(nudstate); i++) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>if ((1 =
&lt;&lt; i) &amp; attrs.ndm_state) {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("state %s ", =
nudstate[i]);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>break;<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>}<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (attrs.nda_lladdr !=3D NULL) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>int =
if_type =3D link.ifi_type;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>if ((if_type =3D=3D IFT_ETHER || =
if_type =3D=3D IFT_L2VLAN || if_type =3D=3D IFT_BRIDGE) =
&amp;&amp;<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span =
class=3D"Apple-converted-space">&nbsp;</span>&nbsp;&nbsp;&nbsp;NLA_DATA_LE=
N(attrs.nda_lladdr) =3D=3D ETHER_ADDR_LEN) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>struct =
ether_addr *ll;<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>ll =3D (struct ether_addr =
*)NLA_DATA(attrs.nda_lladdr);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>printf("lladdr %s ", =
ether_ntoa(ll));<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>} else {<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>struct sockaddr_dl sdl =3D =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>.sdl_len =3D sizeof(sdl),<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>.sdl_family =3D =
AF_LINK,<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>.sdl_index =3D attrs.nda_ifindex,<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>.sdl_type =
=3D if_type,<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>.sdl_alen =3D NLA_DATA_LEN(attrs.nda_lladdr),<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>};<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (sdl.sdl_alen &lt; sizeof(sdl.sdl_data)) {<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span>void *ll =
=3D NLA_DATA(attrs.nda_lladdr);<br>+<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>memcpy(sdl.sdl_data, ll, =
sdl.sdl_alen);<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span><span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>printf("lladdr %s ", link_ntoa(&amp;sdl));<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span><span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>}<br>+<br>+<span class=3D"Apple-tab-span" style=3D"white-space: =
pre;">	</span>if (link.ifla_ifname !=3D NULL)<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("iface %s ", link.ifla_ifname);<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>printf("\n");<br>+}<br>+<br>+static =
void<br>+print_nlmsg_generic(struct nl_helper *h, struct nlmsghdr =
*hdr)<br>+{<br>+}<br>+<br>+static void<br>+print_nlmsg(struct nl_helper =
*h, struct nlmsghdr *hdr)<br>+{<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>switch (hdr-&gt;nlmsg_type) =
{<br>+<span class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>case RTM_NEWLINK:<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>case RTM_DELLINK:<br>+<span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	</span><span =
class=3D"Apple-tab-span" style=3D"white-space: pre;">	=
</span>print_nlmsg_link(h, hdr);<br>+<span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span><span class=3D"Apple-tab-span" =
style=3D"white-space: pre;">	</span>break;<br>*** 184 LINES SKIPPED =
***</blockquote></div></blockquote></div><br></body></html>=

--Apple-Mail=_AE460F85-A90B-4D1C-9453-E5B4D7CEC4B9--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?F0DD3830-654C-49F1-B6D6-C17171A30553>