Home | History | Annotate | Line # | Download | only in net
rtsock.c revision 1.115.2.4.4.2
      1  1.115.2.4.4.2      matt /*	$NetBSD: rtsock.c,v 1.115.2.4.4.2 2010/05/13 05:36:49 matt Exp $	*/
      2           1.30    itojun 
      3           1.30    itojun /*
      4           1.30    itojun  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      5           1.30    itojun  * All rights reserved.
      6           1.75     perry  *
      7           1.30    itojun  * Redistribution and use in source and binary forms, with or without
      8           1.30    itojun  * modification, are permitted provided that the following conditions
      9           1.30    itojun  * are met:
     10           1.30    itojun  * 1. Redistributions of source code must retain the above copyright
     11           1.30    itojun  *    notice, this list of conditions and the following disclaimer.
     12           1.30    itojun  * 2. Redistributions in binary form must reproduce the above copyright
     13           1.30    itojun  *    notice, this list of conditions and the following disclaimer in the
     14           1.30    itojun  *    documentation and/or other materials provided with the distribution.
     15           1.30    itojun  * 3. Neither the name of the project nor the names of its contributors
     16           1.30    itojun  *    may be used to endorse or promote products derived from this software
     17           1.30    itojun  *    without specific prior written permission.
     18           1.75     perry  *
     19           1.30    itojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     20           1.30    itojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21           1.30    itojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22           1.30    itojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     23           1.30    itojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24           1.30    itojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25           1.30    itojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26           1.30    itojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27           1.30    itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28           1.30    itojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29           1.30    itojun  * SUCH DAMAGE.
     30           1.30    itojun  */
     31           1.11       cgd 
     32            1.1       cgd /*
     33           1.10   mycroft  * Copyright (c) 1988, 1991, 1993
     34           1.10   mycroft  *	The Regents of the University of California.  All rights reserved.
     35            1.1       cgd  *
     36            1.1       cgd  * Redistribution and use in source and binary forms, with or without
     37            1.1       cgd  * modification, are permitted provided that the following conditions
     38            1.1       cgd  * are met:
     39            1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     40            1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     41            1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     42            1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     43            1.1       cgd  *    documentation and/or other materials provided with the distribution.
     44           1.64       agc  * 3. Neither the name of the University nor the names of its contributors
     45            1.1       cgd  *    may be used to endorse or promote products derived from this software
     46            1.1       cgd  *    without specific prior written permission.
     47            1.1       cgd  *
     48            1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     49            1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     50            1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     51            1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     52            1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     53            1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     54            1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     55            1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     56            1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     57            1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     58            1.1       cgd  * SUCH DAMAGE.
     59            1.1       cgd  *
     60           1.26      fvdl  *	@(#)rtsock.c	8.7 (Berkeley) 10/12/95
     61            1.1       cgd  */
     62           1.54     lukem 
     63           1.54     lukem #include <sys/cdefs.h>
     64  1.115.2.4.4.2      matt __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.115.2.4.4.2 2010/05/13 05:36:49 matt Exp $");
     65           1.31   thorpej 
     66           1.31   thorpej #include "opt_inet.h"
     67            1.1       cgd 
     68            1.5   mycroft #include <sys/param.h>
     69            1.5   mycroft #include <sys/systm.h>
     70           1.10   mycroft #include <sys/proc.h>
     71            1.5   mycroft #include <sys/mbuf.h>
     72            1.5   mycroft #include <sys/socket.h>
     73            1.5   mycroft #include <sys/socketvar.h>
     74            1.5   mycroft #include <sys/domain.h>
     75            1.5   mycroft #include <sys/protosw.h>
     76           1.17  christos #include <sys/sysctl.h>
     77           1.84      elad #include <sys/kauth.h>
     78           1.99        ad #include <sys/intr.h>
     79           1.91    dyoung #ifdef RTSOCK_DEBUG
     80           1.91    dyoung #include <netinet/in.h>
     81           1.91    dyoung #endif /* RTSOCK_DEBUG */
     82           1.17  christos 
     83            1.5   mycroft #include <net/if.h>
     84            1.5   mycroft #include <net/route.h>
     85            1.5   mycroft #include <net/raw_cb.h>
     86            1.1       cgd 
     87           1.17  christos #include <machine/stdarg.h>
     88           1.17  christos 
     89           1.73      matt DOMAIN_DEFINE(routedomain);	/* forward declare and add to link set */
     90           1.58      matt 
     91           1.87  christos struct	sockaddr route_dst = { .sa_len = 2, .sa_family = PF_ROUTE, };
     92           1.87  christos struct	sockaddr route_src = { .sa_len = 2, .sa_family = PF_ROUTE, };
     93           1.99        ad 
     94           1.99        ad int	route_maxqlen = IFQ_MAXLEN;
     95           1.99        ad static struct	ifqueue route_intrq;
     96           1.99        ad static void	*route_sih;
     97           1.10   mycroft 
     98           1.10   mycroft struct walkarg {
     99           1.29    chopps 	int	w_op;
    100           1.29    chopps 	int	w_arg;
    101           1.29    chopps 	int	w_given;
    102           1.29    chopps 	int	w_needed;
    103           1.93  christos 	void *	w_where;
    104           1.29    chopps 	int	w_tmemsize;
    105           1.29    chopps 	int	w_tmemneeded;
    106           1.93  christos 	void *	w_tmem;
    107           1.10   mycroft };
    108            1.1       cgd 
    109           1.93  christos static struct mbuf *rt_msg1(int, struct rt_addrinfo *, void *, int);
    110           1.93  christos static int rt_msg2(int, struct rt_addrinfo *, void *, struct walkarg *, int *);
    111           1.72  christos static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *);
    112           1.78    dyoung static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int,
    113           1.78    dyoung     struct rt_addrinfo *);
    114           1.94    dyoung static int sysctl_dumpentry(struct rtentry *, void *);
    115           1.69      matt static int sysctl_iflist(int, struct walkarg *, int);
    116           1.69      matt static int sysctl_rtable(SYSCTLFN_PROTO);
    117           1.80     perry static inline void rt_adjustcount(int, int);
    118           1.99        ad static void route_enqueue(struct mbuf *, int);
    119           1.10   mycroft 
    120           1.80     perry static inline void
    121           1.69      matt rt_adjustcount(int af, int cnt)
    122           1.27  christos {
    123           1.28  christos 	route_cb.any_count += cnt;
    124           1.27  christos 	switch (af) {
    125           1.27  christos 	case AF_INET:
    126           1.27  christos 		route_cb.ip_count += cnt;
    127           1.27  christos 		return;
    128           1.30    itojun #ifdef INET6
    129           1.30    itojun 	case AF_INET6:
    130           1.30    itojun 		route_cb.ip6_count += cnt;
    131           1.30    itojun 		return;
    132           1.30    itojun #endif
    133           1.27  christos 	case AF_IPX:
    134           1.27  christos 		route_cb.ipx_count += cnt;
    135           1.27  christos 		return;
    136           1.27  christos 	case AF_NS:
    137           1.27  christos 		route_cb.ns_count += cnt;
    138           1.27  christos 		return;
    139           1.27  christos 	case AF_ISO:
    140           1.27  christos 		route_cb.iso_count += cnt;
    141           1.27  christos 		return;
    142           1.27  christos 	}
    143           1.27  christos }
    144           1.27  christos 
    145            1.1       cgd /*ARGSUSED*/
    146            1.9   mycroft int
    147           1.69      matt route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
    148           1.79  christos 	struct mbuf *control, struct lwp *l)
    149            1.1       cgd {
    150           1.39  augustss 	int error = 0;
    151           1.39  augustss 	struct rawcb *rp = sotorawcb(so);
    152            1.1       cgd 	int s;
    153           1.10   mycroft 
    154            1.1       cgd 	if (req == PRU_ATTACH) {
    155          1.101        ad 		sosetlock(so);
    156          1.108  christos 		MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK|M_ZERO);
    157          1.109      cube 		so->so_pcb = rp;
    158            1.1       cgd 	}
    159           1.27  christos 	if (req == PRU_DETACH && rp)
    160           1.27  christos 		rt_adjustcount(rp->rcb_proto.sp_protocol, -1);
    161           1.14   mycroft 	s = splsoftnet();
    162           1.23   thorpej 
    163           1.23   thorpej 	/*
    164           1.23   thorpej 	 * Don't call raw_usrreq() in the attach case, because
    165           1.23   thorpej 	 * we want to allow non-privileged processes to listen on
    166           1.23   thorpej 	 * and send "safe" commands to the routing socket.
    167           1.23   thorpej 	 */
    168           1.23   thorpej 	if (req == PRU_ATTACH) {
    169           1.95    dyoung 		if (l == NULL)
    170           1.23   thorpej 			error = EACCES;
    171           1.23   thorpej 		else
    172           1.23   thorpej 			error = raw_attach(so, (int)(long)nam);
    173           1.23   thorpej 	} else
    174           1.79  christos 		error = raw_usrreq(so, req, m, nam, control, l);
    175           1.23   thorpej 
    176            1.1       cgd 	rp = sotorawcb(so);
    177            1.1       cgd 	if (req == PRU_ATTACH && rp) {
    178            1.1       cgd 		if (error) {
    179          1.112    dyoung 			free(rp, M_PCB);
    180            1.1       cgd 			splx(s);
    181           1.95    dyoung 			return error;
    182            1.1       cgd 		}
    183           1.27  christos 		rt_adjustcount(rp->rcb_proto.sp_protocol, 1);
    184           1.20   mycroft 		rp->rcb_laddr = &route_src;
    185           1.20   mycroft 		rp->rcb_faddr = &route_dst;
    186            1.1       cgd 		soisconnected(so);
    187            1.1       cgd 		so->so_options |= SO_USELOOPBACK;
    188            1.1       cgd 	}
    189            1.1       cgd 	splx(s);
    190           1.95    dyoung 	return error;
    191           1.95    dyoung }
    192           1.95    dyoung 
    193           1.95    dyoung static const struct sockaddr *
    194           1.95    dyoung intern_netmask(const struct sockaddr *mask)
    195           1.95    dyoung {
    196           1.95    dyoung 	struct radix_node *rn;
    197           1.95    dyoung 	extern struct radix_node_head *mask_rnhead;
    198           1.95    dyoung 
    199           1.95    dyoung 	if (mask != NULL &&
    200           1.95    dyoung 	    (rn = rn_search(mask, mask_rnhead->rnh_treetop)))
    201           1.95    dyoung 		mask = (const struct sockaddr *)rn->rn_key;
    202           1.95    dyoung 
    203           1.95    dyoung 	return mask;
    204            1.1       cgd }
    205            1.1       cgd 
    206            1.1       cgd /*ARGSUSED*/
    207            1.9   mycroft int
    208           1.17  christos route_output(struct mbuf *m, ...)
    209            1.1       cgd {
    210           1.99        ad 	struct sockproto proto = { .sp_family = PF_ROUTE, };
    211           1.95    dyoung 	struct rt_msghdr *rtm = NULL;
    212      1.115.2.1       snj 	struct rt_msghdr *old_rtm = NULL;
    213           1.95    dyoung 	struct rtentry *rt = NULL;
    214           1.95    dyoung 	struct rtentry *saved_nrt = NULL;
    215           1.10   mycroft 	struct rt_addrinfo info;
    216      1.115.2.3       snj 	int len, error = 0;
    217           1.95    dyoung 	struct ifnet *ifp = NULL;
    218      1.115.2.3       snj 	struct ifaddr *ifa = NULL;
    219           1.17  christos 	struct socket *so;
    220           1.17  christos 	va_list ap;
    221           1.55  christos 	sa_family_t family;
    222           1.17  christos 
    223           1.17  christos 	va_start(ap, m);
    224           1.17  christos 	so = va_arg(ap, struct socket *);
    225           1.17  christos 	va_end(ap);
    226           1.17  christos 
    227           1.56     perry #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
    228           1.95    dyoung 	if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
    229           1.95    dyoung 	   (m = m_pullup(m, sizeof(int32_t))) == NULL))
    230           1.95    dyoung 		return ENOBUFS;
    231            1.1       cgd 	if ((m->m_flags & M_PKTHDR) == 0)
    232            1.1       cgd 		panic("route_output");
    233            1.1       cgd 	len = m->m_pkthdr.len;
    234            1.1       cgd 	if (len < sizeof(*rtm) ||
    235           1.10   mycroft 	    len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
    236          1.114    dyoung 		info.rti_info[RTAX_DST] = NULL;
    237            1.1       cgd 		senderr(EINVAL);
    238           1.10   mycroft 	}
    239            1.1       cgd 	R_Malloc(rtm, struct rt_msghdr *, len);
    240           1.95    dyoung 	if (rtm == NULL) {
    241          1.114    dyoung 		info.rti_info[RTAX_DST] = NULL;
    242            1.1       cgd 		senderr(ENOBUFS);
    243           1.10   mycroft 	}
    244          1.112    dyoung 	m_copydata(m, 0, len, rtm);
    245           1.10   mycroft 	if (rtm->rtm_version != RTM_VERSION) {
    246          1.114    dyoung 		info.rti_info[RTAX_DST] = NULL;
    247            1.1       cgd 		senderr(EPROTONOSUPPORT);
    248           1.10   mycroft 	}
    249            1.1       cgd 	rtm->rtm_pid = curproc->p_pid;
    250           1.48   thorpej 	memset(&info, 0, sizeof(info));
    251           1.10   mycroft 	info.rti_addrs = rtm->rtm_addrs;
    252  1.115.2.4.4.2      matt 	KASSERT(sizeof(*rtm) == RT_ROUNDUP(sizeof(*rtm)));
    253          1.112    dyoung 	if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm,
    254          1.112    dyoung 	    &info))
    255           1.42       erh 		senderr(EINVAL);
    256           1.45    itojun 	info.rti_flags = rtm->rtm_flags;
    257           1.91    dyoung #ifdef RTSOCK_DEBUG
    258          1.114    dyoung 	if (info.rti_info[RTAX_DST]->sa_family == AF_INET) {
    259          1.114    dyoung 		printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__,
    260          1.115  christos 		    inet_ntoa(((const struct sockaddr_in *)
    261          1.115  christos 		    info.rti_info[RTAX_DST])->sin_addr));
    262           1.91    dyoung 	}
    263           1.91    dyoung #endif /* RTSOCK_DEBUG */
    264          1.115  christos 	if (info.rti_info[RTAX_DST] == NULL ||
    265          1.115  christos 	    (info.rti_info[RTAX_DST]->sa_family >= AF_MAX))
    266           1.26      fvdl 		senderr(EINVAL);
    267          1.115  christos 	if (info.rti_info[RTAX_GATEWAY] != NULL &&
    268          1.115  christos 	    (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
    269            1.1       cgd 		senderr(EINVAL);
    270           1.23   thorpej 
    271           1.23   thorpej 	/*
    272           1.23   thorpej 	 * Verify that the caller has the appropriate privilege; RTM_GET
    273           1.23   thorpej 	 * is the only operation the non-superuser is allowed.
    274           1.23   thorpej 	 */
    275           1.88      elad 	if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE,
    276           1.89      elad 	    0, rtm, NULL, NULL) != 0)
    277           1.23   thorpej 		senderr(EACCES);
    278           1.23   thorpej 
    279            1.1       cgd 	switch (rtm->rtm_type) {
    280           1.10   mycroft 
    281            1.1       cgd 	case RTM_ADD:
    282          1.114    dyoung 		if (info.rti_info[RTAX_GATEWAY] == NULL)
    283            1.1       cgd 			senderr(EINVAL);
    284           1.45    itojun 		error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
    285            1.1       cgd 		if (error == 0 && saved_nrt) {
    286            1.1       cgd 			rt_setmetrics(rtm->rtm_inits,
    287           1.21  christos 			    &rtm->rtm_rmx, &saved_nrt->rt_rmx);
    288            1.1       cgd 			saved_nrt->rt_refcnt--;
    289            1.1       cgd 		}
    290            1.1       cgd 		break;
    291            1.1       cgd 
    292            1.1       cgd 	case RTM_DELETE:
    293           1.45    itojun 		error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
    294           1.16       cgd 		if (error == 0) {
    295           1.16       cgd 			(rt = saved_nrt)->rt_refcnt++;
    296           1.16       cgd 			goto report;
    297           1.16       cgd 		}
    298            1.1       cgd 		break;
    299            1.1       cgd 
    300            1.1       cgd 	case RTM_GET:
    301            1.1       cgd 	case RTM_CHANGE:
    302            1.1       cgd 	case RTM_LOCK:
    303          1.115  christos                 /* XXX This will mask info.rti_info[RTAX_DST] with
    304          1.115  christos 		 * info.rti_info[RTAX_NETMASK] before
    305           1.95    dyoung                  * searching.  It did not used to do that.  --dyoung
    306           1.95    dyoung 		 */
    307          1.103    dyoung 		error = rtrequest1(RTM_GET, &info, &rt);
    308           1.95    dyoung 		if (error != 0)
    309           1.95    dyoung 			senderr(error);
    310           1.61    itojun 		if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
    311           1.95    dyoung 			struct radix_node *rn;
    312           1.61    itojun 
    313          1.115  christos 			if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt),
    314          1.115  christos 			    info.rti_info[RTAX_DST]->sa_len) != 0)
    315           1.61    itojun 				senderr(ESRCH);
    316          1.115  christos 			info.rti_info[RTAX_NETMASK] = intern_netmask(
    317          1.115  christos 			    info.rti_info[RTAX_NETMASK]);
    318           1.95    dyoung 			for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
    319          1.115  christos 				if (info.rti_info[RTAX_NETMASK] ==
    320          1.115  christos 				    (const struct sockaddr *)rn->rn_mask)
    321           1.61    itojun 					break;
    322           1.95    dyoung 			if (rn == NULL)
    323           1.61    itojun 				senderr(ETOOMANYREFS);
    324           1.95    dyoung 			rt = (struct rtentry *)rn;
    325           1.61    itojun 		}
    326           1.37    itojun 
    327           1.59    itojun 		switch (rtm->rtm_type) {
    328            1.1       cgd 		case RTM_GET:
    329           1.16       cgd 		report:
    330          1.114    dyoung 			info.rti_info[RTAX_DST] = rt_getkey(rt);
    331          1.114    dyoung 			info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
    332          1.114    dyoung 			info.rti_info[RTAX_NETMASK] = rt_mask(rt);
    333           1.91    dyoung 			if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0)
    334           1.91    dyoung 				;
    335           1.91    dyoung 			else if ((ifp = rt->rt_ifp) != NULL) {
    336           1.91    dyoung 				const struct ifaddr *rtifa;
    337          1.114    dyoung 				info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
    338           1.91    dyoung                                 /* rtifa used to be simply rt->rt_ifa.
    339           1.91    dyoung                                  * If rt->rt_ifa != NULL, then
    340           1.91    dyoung                                  * rt_get_ifa() != NULL.  So this
    341           1.91    dyoung                                  * ought to still be safe. --dyoung
    342           1.91    dyoung 				 */
    343           1.91    dyoung 				rtifa = rt_get_ifa(rt);
    344          1.114    dyoung 				info.rti_info[RTAX_IFA] = rtifa->ifa_addr;
    345           1.91    dyoung #ifdef RTSOCK_DEBUG
    346          1.115  christos 				if (info.rti_info[RTAX_IFA]->sa_family ==
    347          1.115  christos 				    AF_INET) {
    348           1.91    dyoung 					printf("%s: copying out RTAX_IFA %s ",
    349          1.115  christos 					    __func__, inet_ntoa(
    350          1.115  christos 					    (const struct sockaddr_in *)
    351          1.115  christos 					    info.rti_info[RTAX_IFA])->sin_addr);
    352          1.115  christos 					printf("for info.rti_info[RTAX_DST] %s "
    353          1.115  christos 					    "ifa_getifa %p ifa_seqno %p\n",
    354          1.115  christos 					    inet_ntoa(
    355          1.115  christos 					    (const struct sockaddr_in *)
    356          1.115  christos 					    info.rti_info[RTAX_DST])->sin_addr),
    357          1.115  christos 					    (void *)rtifa->ifa_getifa,
    358          1.115  christos 					    rtifa->ifa_seqno);
    359           1.37    itojun 				}
    360           1.91    dyoung #endif /* RTSOCK_DEBUG */
    361          1.115  christos 				if (ifp->if_flags & IFF_POINTOPOINT) {
    362          1.115  christos 					info.rti_info[RTAX_BRD] =
    363          1.115  christos 					    rtifa->ifa_dstaddr;
    364          1.115  christos 				} else
    365          1.114    dyoung 					info.rti_info[RTAX_BRD] = NULL;
    366           1.91    dyoung 				rtm->rtm_index = ifp->if_index;
    367           1.91    dyoung 			} else {
    368          1.114    dyoung 				info.rti_info[RTAX_IFP] = NULL;
    369          1.114    dyoung 				info.rti_info[RTAX_IFA] = NULL;
    370            1.1       cgd 			}
    371           1.95    dyoung 			(void)rt_msg2(rtm->rtm_type, &info, NULL, NULL, &len);
    372            1.1       cgd 			if (len > rtm->rtm_msglen) {
    373      1.115.2.1       snj 				old_rtm = rtm;
    374      1.115.2.1       snj 				R_Malloc(rtm, struct rt_msghdr *, len);
    375      1.115.2.1       snj 				if (rtm == NULL)
    376            1.1       cgd 					senderr(ENOBUFS);
    377      1.115.2.1       snj 				(void)memcpy(rtm, old_rtm, old_rtm->rtm_msglen);
    378            1.1       cgd 			}
    379          1.111  christos 			(void)rt_msg2(rtm->rtm_type, &info, rtm, NULL, 0);
    380            1.1       cgd 			rtm->rtm_flags = rt->rt_flags;
    381            1.1       cgd 			rtm->rtm_rmx = rt->rt_rmx;
    382           1.10   mycroft 			rtm->rtm_addrs = info.rti_addrs;
    383            1.1       cgd 			break;
    384            1.1       cgd 
    385            1.1       cgd 		case RTM_CHANGE:
    386           1.45    itojun 			/*
    387           1.45    itojun 			 * new gateway could require new ifaddr, ifp;
    388           1.45    itojun 			 * flags may also be different; ifp may be specified
    389           1.45    itojun 			 * by ll sockaddr when protocol address is ambiguous
    390           1.45    itojun 			 */
    391           1.45    itojun 			if ((error = rt_getifa(&info)) != 0)
    392           1.45    itojun 				senderr(error);
    393          1.115  christos 			if (info.rti_info[RTAX_GATEWAY] &&
    394          1.115  christos 			    rt_setgate(rt, info.rti_info[RTAX_GATEWAY]))
    395            1.1       cgd 				senderr(EDQUOT);
    396           1.35    itojun 			/* new gateway could require new ifaddr, ifp;
    397           1.35    itojun 			   flags may also be different; ifp may be specified
    398           1.35    itojun 			   by ll sockaddr when protocol address is ambiguous */
    399          1.115  christos 			if (info.rti_info[RTAX_IFP] &&
    400          1.115  christos 			    (ifa = ifa_ifwithnet(info.rti_info[RTAX_IFP])) &&
    401          1.115  christos 			    (ifp = ifa->ifa_ifp) && (info.rti_info[RTAX_IFA] ||
    402          1.115  christos 			    info.rti_info[RTAX_GATEWAY])) {
    403          1.115  christos 				ifa = ifaof_ifpforaddr(info.rti_info[RTAX_IFA] ?
    404          1.115  christos 				    info.rti_info[RTAX_IFA] :
    405          1.115  christos 				    info.rti_info[RTAX_GATEWAY], ifp);
    406          1.115  christos 			} else if ((info.rti_info[RTAX_IFA] &&
    407          1.115  christos 			    (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) ||
    408          1.115  christos 			    (info.rti_info[RTAX_GATEWAY] &&
    409          1.115  christos 			    (ifa = ifa_ifwithroute(rt->rt_flags,
    410          1.115  christos 			    rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) {
    411           1.35    itojun 				ifp = ifa->ifa_ifp;
    412          1.115  christos 			}
    413           1.35    itojun 			if (ifa) {
    414      1.115.2.3       snj 				struct ifaddr *oifa = rt->rt_ifa;
    415           1.35    itojun 				if (oifa != ifa) {
    416           1.90    dyoung 					if (oifa && oifa->ifa_rtrequest) {
    417           1.90    dyoung 						oifa->ifa_rtrequest(RTM_DELETE,
    418           1.90    dyoung 						    rt, &info);
    419           1.90    dyoung 					}
    420           1.90    dyoung 					rt_replace_ifa(rt, ifa);
    421           1.90    dyoung 					rt->rt_ifp = ifp;
    422           1.35    itojun 				}
    423           1.35    itojun 			}
    424            1.1       cgd 			rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
    425           1.21  christos 			    &rt->rt_rmx);
    426           1.35    itojun 			if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
    427           1.45    itojun 				rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
    428          1.115  christos 			/*FALLTHROUGH*/
    429            1.1       cgd 		case RTM_LOCK:
    430           1.10   mycroft 			rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
    431            1.1       cgd 			rt->rt_rmx.rmx_locks |=
    432           1.21  christos 			    (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
    433            1.1       cgd 			break;
    434            1.1       cgd 		}
    435           1.10   mycroft 		break;
    436            1.1       cgd 
    437            1.1       cgd 	default:
    438            1.1       cgd 		senderr(EOPNOTSUPP);
    439            1.1       cgd 	}
    440            1.1       cgd 
    441            1.1       cgd flush:
    442            1.1       cgd 	if (rtm) {
    443            1.1       cgd 		if (error)
    444            1.1       cgd 			rtm->rtm_errno = error;
    445           1.75     perry 		else
    446            1.1       cgd 			rtm->rtm_flags |= RTF_DONE;
    447            1.1       cgd 	}
    448          1.115  christos 	family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family :
    449          1.115  christos 	    0;
    450      1.115.2.1       snj 	/* We cannot free old_rtm until we have stopped using the
    451      1.115.2.1       snj 	 * pointers in info, some of which may point to sockaddrs
    452      1.115.2.1       snj 	 * in old_rtm.
    453      1.115.2.1       snj 	 */
    454      1.115.2.1       snj 	if (old_rtm != NULL)
    455      1.115.2.1       snj 		Free(old_rtm);
    456            1.1       cgd 	if (rt)
    457            1.1       cgd 		rtfree(rt);
    458            1.1       cgd     {
    459           1.95    dyoung 	struct rawcb *rp = NULL;
    460            1.1       cgd 	/*
    461            1.1       cgd 	 * Check to see if we don't want our own messages.
    462            1.1       cgd 	 */
    463            1.1       cgd 	if ((so->so_options & SO_USELOOPBACK) == 0) {
    464            1.1       cgd 		if (route_cb.any_count <= 1) {
    465            1.1       cgd 			if (rtm)
    466            1.1       cgd 				Free(rtm);
    467            1.1       cgd 			m_freem(m);
    468           1.95    dyoung 			return error;
    469            1.1       cgd 		}
    470            1.1       cgd 		/* There is another listener, so construct message */
    471            1.1       cgd 		rp = sotorawcb(so);
    472            1.1       cgd 	}
    473            1.1       cgd 	if (rtm) {
    474          1.112    dyoung 		m_copyback(m, 0, rtm->rtm_msglen, rtm);
    475           1.47    itojun 		if (m->m_pkthdr.len < rtm->rtm_msglen) {
    476           1.46    itojun 			m_freem(m);
    477           1.46    itojun 			m = NULL;
    478           1.47    itojun 		} else if (m->m_pkthdr.len > rtm->rtm_msglen)
    479           1.46    itojun 			m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
    480            1.1       cgd 		Free(rtm);
    481            1.1       cgd 	}
    482            1.1       cgd 	if (rp)
    483            1.1       cgd 		rp->rcb_proto.sp_family = 0; /* Avoid us */
    484           1.55  christos 	if (family)
    485           1.99        ad 		proto.sp_protocol = family;
    486           1.46    itojun 	if (m)
    487           1.99        ad 		raw_input(m, &proto, &route_src, &route_dst);
    488            1.1       cgd 	if (rp)
    489            1.1       cgd 		rp->rcb_proto.sp_family = PF_ROUTE;
    490            1.1       cgd     }
    491           1.95    dyoung 	return error;
    492            1.1       cgd }
    493            1.1       cgd 
    494            1.9   mycroft void
    495           1.69      matt rt_setmetrics(u_long which, const struct rt_metrics *in, struct rt_metrics *out)
    496            1.1       cgd {
    497            1.1       cgd #define metric(f, e) if (which & (f)) out->e = in->e;
    498            1.1       cgd 	metric(RTV_RPIPE, rmx_recvpipe);
    499            1.1       cgd 	metric(RTV_SPIPE, rmx_sendpipe);
    500            1.1       cgd 	metric(RTV_SSTHRESH, rmx_ssthresh);
    501            1.1       cgd 	metric(RTV_RTT, rmx_rtt);
    502            1.1       cgd 	metric(RTV_RTTVAR, rmx_rttvar);
    503            1.1       cgd 	metric(RTV_HOPCOUNT, rmx_hopcount);
    504            1.1       cgd 	metric(RTV_MTU, rmx_mtu);
    505            1.1       cgd 	metric(RTV_EXPIRE, rmx_expire);
    506            1.1       cgd #undef metric
    507            1.1       cgd }
    508            1.1       cgd 
    509           1.42       erh static int
    510          1.115  christos rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim,
    511          1.115  christos     struct rt_addrinfo *rtinfo)
    512           1.10   mycroft {
    513           1.69      matt 	const struct sockaddr *sa = NULL;	/* Quell compiler warning */
    514           1.39  augustss 	int i;
    515           1.10   mycroft 
    516          1.112    dyoung 	for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
    517           1.10   mycroft 		if ((rtinfo->rti_addrs & (1 << i)) == 0)
    518           1.10   mycroft 			continue;
    519      1.115.2.1       snj 		rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp;
    520      1.115.2.4       snj 		RT_ADVANCE(cp, sa);
    521           1.10   mycroft 	}
    522           1.44     enami 
    523          1.115  christos 	/*
    524          1.115  christos 	 * Check for extra addresses specified, except RTM_GET asking
    525          1.115  christos 	 * for interface info.
    526          1.115  christos 	 */
    527           1.72  christos 	if (rtmtype == RTM_GET) {
    528          1.115  christos 		if (((rtinfo->rti_addrs &
    529          1.115  christos 		    (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0)
    530           1.95    dyoung 			return 1;
    531          1.114    dyoung 	} else if ((rtinfo->rti_addrs & (~0 << i)) != 0)
    532          1.114    dyoung 		return 1;
    533           1.44     enami 	/* Check for bad data length.  */
    534           1.44     enami 	if (cp != cplim) {
    535          1.112    dyoung 		if (i == RTAX_NETMASK + 1 && sa != NULL &&
    536      1.115.2.4       snj 		    cp - RT_ROUNDUP(sa->sa_len) + sa->sa_len == cplim)
    537           1.44     enami 			/*
    538          1.114    dyoung 			 * The last sockaddr was info.rti_info[RTAX_NETMASK].
    539           1.44     enami 			 * We accept this for now for the sake of old
    540           1.44     enami 			 * binaries or third party softwares.
    541           1.44     enami 			 */
    542           1.44     enami 			;
    543           1.44     enami 		else
    544           1.95    dyoung 			return 1;
    545           1.44     enami 	}
    546           1.95    dyoung 	return 0;
    547            1.1       cgd }
    548            1.1       cgd 
    549           1.10   mycroft static struct mbuf *
    550           1.93  christos rt_msg1(int type, struct rt_addrinfo *rtinfo, void *data, int datalen)
    551            1.1       cgd {
    552           1.39  augustss 	struct rt_msghdr *rtm;
    553           1.39  augustss 	struct mbuf *m;
    554           1.39  augustss 	int i;
    555           1.68      matt 	const struct sockaddr *sa;
    556           1.47    itojun 	int len, dlen;
    557            1.1       cgd 
    558           1.47    itojun 	m = m_gethdr(M_DONTWAIT, MT_DATA);
    559           1.95    dyoung 	if (m == NULL)
    560           1.95    dyoung 		return m;
    561           1.58      matt 	MCLAIM(m, &routedomain.dom_mowner);
    562           1.10   mycroft 	switch (type) {
    563           1.47    itojun 
    564           1.10   mycroft 	case RTM_DELADDR:
    565           1.10   mycroft 	case RTM_NEWADDR:
    566           1.47    itojun 		len = sizeof(struct ifa_msghdr);
    567           1.10   mycroft 		break;
    568           1.10   mycroft 
    569           1.32    bouyer #ifdef COMPAT_14
    570           1.32    bouyer 	case RTM_OIFINFO:
    571           1.47    itojun 		len = sizeof(struct if_msghdr14);
    572           1.32    bouyer 		break;
    573           1.32    bouyer #endif
    574           1.32    bouyer 
    575           1.10   mycroft 	case RTM_IFINFO:
    576           1.47    itojun 		len = sizeof(struct if_msghdr);
    577           1.10   mycroft 		break;
    578           1.10   mycroft 
    579           1.36   thorpej 	case RTM_IFANNOUNCE:
    580           1.78    dyoung 	case RTM_IEEE80211:
    581           1.47    itojun 		len = sizeof(struct if_announcemsghdr);
    582           1.36   thorpej 		break;
    583           1.36   thorpej 
    584           1.10   mycroft 	default:
    585           1.47    itojun 		len = sizeof(struct rt_msghdr);
    586           1.46    itojun 	}
    587  1.115.2.4.4.2      matt 	len = RT_ROUNDUP(len);
    588           1.47    itojun 	if (len > MHLEN + MLEN)
    589           1.34    itojun 		panic("rt_msg1: message too long");
    590           1.47    itojun 	else if (len > MHLEN) {
    591           1.32    bouyer 		m->m_next = m_get(M_DONTWAIT, MT_DATA);
    592           1.47    itojun 		if (m->m_next == NULL) {
    593           1.32    bouyer 			m_freem(m);
    594           1.95    dyoung 			return NULL;
    595           1.32    bouyer 		}
    596           1.58      matt 		MCLAIM(m->m_next, m->m_owner);
    597           1.47    itojun 		m->m_pkthdr.len = len;
    598           1.47    itojun 		m->m_len = MHLEN;
    599           1.47    itojun 		m->m_next->m_len = len - MHLEN;
    600           1.47    itojun 	} else {
    601           1.47    itojun 		m->m_pkthdr.len = m->m_len = len;
    602           1.32    bouyer 	}
    603           1.95    dyoung 	m->m_pkthdr.rcvif = NULL;
    604           1.32    bouyer 	m_copyback(m, 0, datalen, data);
    605          1.107  christos 	if (len > datalen)
    606          1.107  christos 		(void)memset(mtod(m, char *) + datalen, 0, len - datalen);
    607            1.1       cgd 	rtm = mtod(m, struct rt_msghdr *);
    608           1.10   mycroft 	for (i = 0; i < RTAX_MAX; i++) {
    609           1.10   mycroft 		if ((sa = rtinfo->rti_info[i]) == NULL)
    610           1.10   mycroft 			continue;
    611           1.10   mycroft 		rtinfo->rti_addrs |= (1 << i);
    612      1.115.2.4       snj 		dlen = RT_ROUNDUP(sa->sa_len);
    613           1.76  christos 		m_copyback(m, len, dlen, sa);
    614           1.10   mycroft 		len += dlen;
    615           1.47    itojun 	}
    616  1.115.2.4.4.2      matt 	KASSERT(len == RT_ROUNDUP(len));
    617           1.47    itojun 	if (m->m_pkthdr.len != len) {
    618           1.47    itojun 		m_freem(m);
    619           1.95    dyoung 		return NULL;
    620           1.10   mycroft 	}
    621            1.1       cgd 	rtm->rtm_msglen = len;
    622            1.1       cgd 	rtm->rtm_version = RTM_VERSION;
    623            1.1       cgd 	rtm->rtm_type = type;
    624           1.95    dyoung 	return m;
    625           1.10   mycroft }
    626           1.10   mycroft 
    627           1.29    chopps /*
    628           1.29    chopps  * rt_msg2
    629           1.29    chopps  *
    630           1.29    chopps  *	 fills 'cp' or 'w'.w_tmem with the routing socket message and
    631           1.29    chopps  *		returns the length of the message in 'lenp'.
    632           1.29    chopps  *
    633           1.29    chopps  * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold
    634           1.29    chopps  *	the message
    635           1.29    chopps  * otherwise walkarg's w_needed is updated and if the user buffer is
    636           1.29    chopps  *	specified and w_needed indicates space exists the information is copied
    637           1.29    chopps  *	into the temp space (w_tmem). w_tmem is [re]allocated if necessary,
    638           1.29    chopps  *	if the allocation fails ENOBUFS is returned.
    639           1.29    chopps  */
    640           1.10   mycroft static int
    641           1.93  christos rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct walkarg *w,
    642           1.69      matt 	int *lenp)
    643           1.10   mycroft {
    644           1.39  augustss 	int i;
    645           1.10   mycroft 	int len, dlen, second_time = 0;
    646           1.93  christos 	char *cp0, *cp = cpv;
    647           1.10   mycroft 
    648           1.10   mycroft 	rtinfo->rti_addrs = 0;
    649           1.10   mycroft again:
    650           1.10   mycroft 	switch (type) {
    651           1.10   mycroft 
    652           1.10   mycroft 	case RTM_DELADDR:
    653           1.10   mycroft 	case RTM_NEWADDR:
    654           1.10   mycroft 		len = sizeof(struct ifa_msghdr);
    655           1.10   mycroft 		break;
    656           1.32    bouyer #ifdef COMPAT_14
    657           1.32    bouyer 	case RTM_OIFINFO:
    658           1.32    bouyer 		len = sizeof(struct if_msghdr14);
    659           1.32    bouyer 		break;
    660           1.32    bouyer #endif
    661           1.10   mycroft 
    662           1.10   mycroft 	case RTM_IFINFO:
    663           1.10   mycroft 		len = sizeof(struct if_msghdr);
    664           1.10   mycroft 		break;
    665           1.10   mycroft 
    666           1.10   mycroft 	default:
    667           1.10   mycroft 		len = sizeof(struct rt_msghdr);
    668           1.10   mycroft 	}
    669  1.115.2.4.4.2      matt 	len = RT_ROUNDUP(len);
    670           1.17  christos 	if ((cp0 = cp) != NULL)
    671           1.10   mycroft 		cp += len;
    672           1.10   mycroft 	for (i = 0; i < RTAX_MAX; i++) {
    673           1.68      matt 		const struct sockaddr *sa;
    674           1.10   mycroft 
    675           1.95    dyoung 		if ((sa = rtinfo->rti_info[i]) == NULL)
    676           1.10   mycroft 			continue;
    677           1.10   mycroft 		rtinfo->rti_addrs |= (1 << i);
    678      1.115.2.4       snj 		dlen = RT_ROUNDUP(sa->sa_len);
    679           1.10   mycroft 		if (cp) {
    680          1.111  christos 			(void)memcpy(cp, sa, (size_t)dlen);
    681           1.10   mycroft 			cp += dlen;
    682           1.10   mycroft 		}
    683            1.1       cgd 		len += dlen;
    684            1.1       cgd 	}
    685           1.95    dyoung 	if (cp == NULL && w != NULL && !second_time) {
    686           1.39  augustss 		struct walkarg *rw = w;
    687           1.10   mycroft 
    688           1.10   mycroft 		rw->w_needed += len;
    689           1.10   mycroft 		if (rw->w_needed <= 0 && rw->w_where) {
    690           1.10   mycroft 			if (rw->w_tmemsize < len) {
    691           1.10   mycroft 				if (rw->w_tmem)
    692           1.10   mycroft 					free(rw->w_tmem, M_RTABLE);
    693          1.111  christos 				rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT);
    694           1.17  christos 				if (rw->w_tmem)
    695           1.10   mycroft 					rw->w_tmemsize = len;
    696          1.111  christos 				else
    697          1.111  christos 					rw->w_tmemsize = 0;
    698           1.10   mycroft 			}
    699           1.10   mycroft 			if (rw->w_tmem) {
    700           1.10   mycroft 				cp = rw->w_tmem;
    701           1.10   mycroft 				second_time = 1;
    702           1.10   mycroft 				goto again;
    703           1.29    chopps 			} else {
    704           1.29    chopps 				rw->w_tmemneeded = len;
    705           1.95    dyoung 				return ENOBUFS;
    706           1.29    chopps 			}
    707           1.10   mycroft 		}
    708            1.1       cgd 	}
    709  1.115.2.4.4.2      matt 	KASSERT(len == RT_ROUNDUP(len));
    710           1.10   mycroft 	if (cp) {
    711           1.39  augustss 		struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
    712           1.10   mycroft 
    713           1.10   mycroft 		rtm->rtm_version = RTM_VERSION;
    714           1.10   mycroft 		rtm->rtm_type = type;
    715           1.10   mycroft 		rtm->rtm_msglen = len;
    716            1.1       cgd 	}
    717           1.29    chopps 	if (lenp)
    718           1.29    chopps 		*lenp = len;
    719           1.95    dyoung 	return 0;
    720           1.10   mycroft }
    721           1.10   mycroft 
    722           1.10   mycroft /*
    723           1.10   mycroft  * This routine is called to generate a message from the routing
    724           1.51       wiz  * socket indicating that a redirect has occurred, a routing lookup
    725           1.10   mycroft  * has failed, or that a protocol has detected timeouts to a particular
    726           1.10   mycroft  * destination.
    727           1.10   mycroft  */
    728           1.10   mycroft void
    729           1.69      matt rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
    730           1.10   mycroft {
    731           1.32    bouyer 	struct rt_msghdr rtm;
    732           1.39  augustss 	struct mbuf *m;
    733           1.68      matt 	const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
    734           1.10   mycroft 
    735           1.10   mycroft 	if (route_cb.any_count == 0)
    736           1.10   mycroft 		return;
    737           1.48   thorpej 	memset(&rtm, 0, sizeof(rtm));
    738           1.32    bouyer 	rtm.rtm_flags = RTF_DONE | flags;
    739           1.32    bouyer 	rtm.rtm_errno = error;
    740          1.110    dyoung 	m = rt_msg1(type, rtinfo, &rtm, sizeof(rtm));
    741           1.95    dyoung 	if (m == NULL)
    742            1.1       cgd 		return;
    743           1.32    bouyer 	mtod(m, struct rt_msghdr *)->rtm_addrs = rtinfo->rti_addrs;
    744           1.99        ad 	route_enqueue(m, sa ? sa->sa_family : 0);
    745           1.10   mycroft }
    746           1.10   mycroft 
    747           1.10   mycroft /*
    748           1.10   mycroft  * This routine is called to generate a message from the routing
    749           1.10   mycroft  * socket indicating that the status of a network interface has changed.
    750           1.10   mycroft  */
    751           1.10   mycroft void
    752           1.69      matt rt_ifmsg(struct ifnet *ifp)
    753           1.10   mycroft {
    754           1.32    bouyer 	struct if_msghdr ifm;
    755           1.32    bouyer #ifdef COMPAT_14
    756           1.32    bouyer 	struct if_msghdr14 oifm;
    757           1.32    bouyer #endif
    758           1.10   mycroft 	struct mbuf *m;
    759           1.10   mycroft 	struct rt_addrinfo info;
    760           1.10   mycroft 
    761           1.10   mycroft 	if (route_cb.any_count == 0)
    762           1.10   mycroft 		return;
    763           1.48   thorpej 	memset(&info, 0, sizeof(info));
    764           1.48   thorpej 	memset(&ifm, 0, sizeof(ifm));
    765           1.32    bouyer 	ifm.ifm_index = ifp->if_index;
    766           1.32    bouyer 	ifm.ifm_flags = ifp->if_flags;
    767           1.32    bouyer 	ifm.ifm_data = ifp->if_data;
    768           1.32    bouyer 	ifm.ifm_addrs = 0;
    769          1.110    dyoung 	m = rt_msg1(RTM_IFINFO, &info, &ifm, sizeof(ifm));
    770           1.95    dyoung 	if (m == NULL)
    771           1.32    bouyer 		return;
    772           1.99        ad 	route_enqueue(m, 0);
    773           1.32    bouyer #ifdef COMPAT_14
    774           1.48   thorpej 	memset(&info, 0, sizeof(info));
    775           1.48   thorpej 	memset(&oifm, 0, sizeof(oifm));
    776           1.32    bouyer 	oifm.ifm_index = ifp->if_index;
    777           1.32    bouyer 	oifm.ifm_flags = ifp->if_flags;
    778           1.32    bouyer 	oifm.ifm_data.ifi_type = ifp->if_data.ifi_type;
    779           1.32    bouyer 	oifm.ifm_data.ifi_addrlen = ifp->if_data.ifi_addrlen;
    780           1.32    bouyer 	oifm.ifm_data.ifi_hdrlen = ifp->if_data.ifi_hdrlen;
    781           1.32    bouyer 	oifm.ifm_data.ifi_mtu = ifp->if_data.ifi_mtu;
    782           1.32    bouyer 	oifm.ifm_data.ifi_metric = ifp->if_data.ifi_metric;
    783           1.32    bouyer 	oifm.ifm_data.ifi_baudrate = ifp->if_data.ifi_baudrate;
    784           1.32    bouyer 	oifm.ifm_data.ifi_ipackets = ifp->if_data.ifi_ipackets;
    785           1.32    bouyer 	oifm.ifm_data.ifi_ierrors = ifp->if_data.ifi_ierrors;
    786           1.32    bouyer 	oifm.ifm_data.ifi_opackets = ifp->if_data.ifi_opackets;
    787           1.32    bouyer 	oifm.ifm_data.ifi_oerrors = ifp->if_data.ifi_oerrors;
    788           1.32    bouyer 	oifm.ifm_data.ifi_collisions = ifp->if_data.ifi_collisions;
    789           1.32    bouyer 	oifm.ifm_data.ifi_ibytes = ifp->if_data.ifi_ibytes;
    790           1.32    bouyer 	oifm.ifm_data.ifi_obytes = ifp->if_data.ifi_obytes;
    791           1.32    bouyer 	oifm.ifm_data.ifi_imcasts = ifp->if_data.ifi_imcasts;
    792           1.32    bouyer 	oifm.ifm_data.ifi_omcasts = ifp->if_data.ifi_omcasts;
    793           1.32    bouyer 	oifm.ifm_data.ifi_iqdrops = ifp->if_data.ifi_iqdrops;
    794           1.32    bouyer 	oifm.ifm_data.ifi_noproto = ifp->if_data.ifi_noproto;
    795           1.32    bouyer 	oifm.ifm_data.ifi_lastchange = ifp->if_data.ifi_lastchange;
    796           1.32    bouyer 	oifm.ifm_addrs = 0;
    797          1.110    dyoung 	m = rt_msg1(RTM_OIFINFO, &info, &oifm, sizeof(oifm));
    798           1.95    dyoung 	if (m == NULL)
    799           1.10   mycroft 		return;
    800           1.99        ad 	route_enqueue(m, 0);
    801           1.32    bouyer #endif
    802            1.1       cgd }
    803            1.1       cgd 
    804            1.1       cgd /*
    805           1.10   mycroft  * This is called to generate messages from the routing socket
    806           1.10   mycroft  * indicating a network interface has had addresses associated with it.
    807           1.10   mycroft  * if we ever reverse the logic and replace messages TO the routing
    808           1.10   mycroft  * socket indicate a request to configure interfaces, then it will
    809           1.10   mycroft  * be unnecessary as the routing socket will automatically generate
    810           1.10   mycroft  * copies of it.
    811           1.10   mycroft  */
    812           1.10   mycroft void
    813           1.69      matt rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
    814           1.10   mycroft {
    815           1.10   mycroft 	struct rt_addrinfo info;
    816           1.95    dyoung 	const struct sockaddr *sa = NULL;
    817           1.10   mycroft 	int pass;
    818           1.17  christos 	struct mbuf *m = NULL;
    819           1.10   mycroft 	struct ifnet *ifp = ifa->ifa_ifp;
    820           1.10   mycroft 
    821           1.10   mycroft 	if (route_cb.any_count == 0)
    822           1.10   mycroft 		return;
    823           1.10   mycroft 	for (pass = 1; pass < 3; pass++) {
    824           1.48   thorpej 		memset(&info, 0, sizeof(info));
    825           1.10   mycroft 		if ((cmd == RTM_ADD && pass == 1) ||
    826           1.10   mycroft 		    (cmd == RTM_DELETE && pass == 2)) {
    827           1.32    bouyer 			struct ifa_msghdr ifam;
    828           1.10   mycroft 			int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
    829           1.10   mycroft 
    830          1.114    dyoung 			info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
    831          1.114    dyoung 			info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
    832          1.114    dyoung 			info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
    833          1.114    dyoung 			info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
    834           1.48   thorpej 			memset(&ifam, 0, sizeof(ifam));
    835           1.32    bouyer 			ifam.ifam_index = ifp->if_index;
    836           1.32    bouyer 			ifam.ifam_metric = ifa->ifa_metric;
    837           1.32    bouyer 			ifam.ifam_flags = ifa->ifa_flags;
    838          1.110    dyoung 			m = rt_msg1(ncmd, &info, &ifam, sizeof(ifam));
    839           1.32    bouyer 			if (m == NULL)
    840           1.10   mycroft 				continue;
    841           1.32    bouyer 			mtod(m, struct ifa_msghdr *)->ifam_addrs =
    842           1.32    bouyer 			    info.rti_addrs;
    843           1.10   mycroft 		}
    844           1.10   mycroft 		if ((cmd == RTM_ADD && pass == 2) ||
    845           1.10   mycroft 		    (cmd == RTM_DELETE && pass == 1)) {
    846           1.32    bouyer 			struct rt_msghdr rtm;
    847           1.75     perry 
    848           1.95    dyoung 			if (rt == NULL)
    849           1.10   mycroft 				continue;
    850          1.114    dyoung 			info.rti_info[RTAX_NETMASK] = rt_mask(rt);
    851          1.114    dyoung 			info.rti_info[RTAX_DST] = sa = rt_getkey(rt);
    852          1.114    dyoung 			info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
    853           1.48   thorpej 			memset(&rtm, 0, sizeof(rtm));
    854           1.32    bouyer 			rtm.rtm_index = ifp->if_index;
    855           1.32    bouyer 			rtm.rtm_flags |= rt->rt_flags;
    856           1.32    bouyer 			rtm.rtm_errno = error;
    857          1.110    dyoung 			m = rt_msg1(cmd, &info, &rtm, sizeof(rtm));
    858           1.32    bouyer 			if (m == NULL)
    859           1.10   mycroft 				continue;
    860           1.32    bouyer 			mtod(m, struct rt_msghdr *)->rtm_addrs = info.rti_addrs;
    861           1.10   mycroft 		}
    862          1.104  christos #ifdef DIAGNOSTIC
    863          1.104  christos 		if (m == NULL)
    864          1.105  dholland 			panic("%s: called with wrong command", __func__);
    865          1.104  christos #endif
    866           1.99        ad 		route_enqueue(m, sa ? sa->sa_family : 0);
    867           1.10   mycroft 	}
    868           1.36   thorpej }
    869           1.36   thorpej 
    870           1.78    dyoung static struct mbuf *
    871           1.78    dyoung rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
    872           1.78    dyoung     struct rt_addrinfo *info)
    873           1.78    dyoung {
    874           1.78    dyoung 	struct if_announcemsghdr ifan;
    875           1.78    dyoung 
    876           1.78    dyoung 	memset(info, 0, sizeof(*info));
    877           1.78    dyoung 	memset(&ifan, 0, sizeof(ifan));
    878           1.78    dyoung 	ifan.ifan_index = ifp->if_index;
    879           1.78    dyoung 	strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name));
    880           1.78    dyoung 	ifan.ifan_what = what;
    881          1.111  christos 	return rt_msg1(type, info, &ifan, sizeof(ifan));
    882           1.78    dyoung }
    883           1.78    dyoung 
    884           1.36   thorpej /*
    885           1.36   thorpej  * This is called to generate routing socket messages indicating
    886           1.36   thorpej  * network interface arrival and departure.
    887           1.36   thorpej  */
    888           1.36   thorpej void
    889           1.69      matt rt_ifannouncemsg(struct ifnet *ifp, int what)
    890           1.36   thorpej {
    891           1.36   thorpej 	struct mbuf *m;
    892           1.36   thorpej 	struct rt_addrinfo info;
    893           1.36   thorpej 
    894           1.36   thorpej 	if (route_cb.any_count == 0)
    895           1.36   thorpej 		return;
    896           1.78    dyoung 	m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
    897           1.78    dyoung 	if (m == NULL)
    898           1.78    dyoung 		return;
    899           1.99        ad 	route_enqueue(m, 0);
    900           1.78    dyoung }
    901           1.78    dyoung 
    902           1.78    dyoung /*
    903           1.78    dyoung  * This is called to generate routing socket messages indicating
    904           1.78    dyoung  * IEEE80211 wireless events.
    905           1.78    dyoung  * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
    906           1.78    dyoung  */
    907           1.78    dyoung void
    908           1.78    dyoung rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
    909           1.78    dyoung {
    910           1.78    dyoung 	struct mbuf *m;
    911           1.78    dyoung 	struct rt_addrinfo info;
    912           1.78    dyoung 
    913           1.78    dyoung 	if (route_cb.any_count == 0)
    914           1.78    dyoung 		return;
    915           1.78    dyoung 	m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
    916           1.78    dyoung 	if (m == NULL)
    917           1.36   thorpej 		return;
    918           1.78    dyoung 	/*
    919           1.78    dyoung 	 * Append the ieee80211 data.  Try to stick it in the
    920           1.78    dyoung 	 * mbuf containing the ifannounce msg; otherwise allocate
    921           1.78    dyoung 	 * a new mbuf and append.
    922           1.78    dyoung 	 *
    923           1.78    dyoung 	 * NB: we assume m is a single mbuf.
    924           1.78    dyoung 	 */
    925           1.78    dyoung 	if (data_len > M_TRAILINGSPACE(m)) {
    926           1.78    dyoung 		struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
    927           1.78    dyoung 		if (n == NULL) {
    928           1.78    dyoung 			m_freem(m);
    929           1.78    dyoung 			return;
    930           1.78    dyoung 		}
    931           1.78    dyoung 		(void)memcpy(mtod(n, void *), data, data_len);
    932           1.78    dyoung 		n->m_len = data_len;
    933           1.78    dyoung 		m->m_next = n;
    934           1.78    dyoung 	} else if (data_len > 0) {
    935           1.98      matt 		(void)memcpy(mtod(m, uint8_t *) + m->m_len, data, data_len);
    936           1.78    dyoung 		m->m_len += data_len;
    937           1.78    dyoung 	}
    938           1.78    dyoung 	if (m->m_flags & M_PKTHDR)
    939           1.78    dyoung 		m->m_pkthdr.len += data_len;
    940           1.78    dyoung 	mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
    941           1.99        ad 	route_enqueue(m, 0);
    942           1.10   mycroft }
    943           1.10   mycroft 
    944           1.10   mycroft /*
    945           1.10   mycroft  * This is used in dumping the kernel table via sysctl().
    946            1.1       cgd  */
    947           1.40    simonb static int
    948           1.94    dyoung sysctl_dumpentry(struct rtentry *rt, void *v)
    949            1.1       cgd {
    950           1.39  augustss 	struct walkarg *w = v;
    951           1.10   mycroft 	int error = 0, size;
    952           1.10   mycroft 	struct rt_addrinfo info;
    953            1.1       cgd 
    954           1.10   mycroft 	if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
    955           1.10   mycroft 		return 0;
    956           1.48   thorpej 	memset(&info, 0, sizeof(info));
    957          1.114    dyoung 	info.rti_info[RTAX_DST] = rt_getkey(rt);
    958          1.114    dyoung 	info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
    959          1.114    dyoung 	info.rti_info[RTAX_NETMASK] = rt_mask(rt);
    960           1.16       cgd 	if (rt->rt_ifp) {
    961           1.91    dyoung 		const struct ifaddr *rtifa;
    962          1.114    dyoung 		info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr;
    963           1.91    dyoung 		/* rtifa used to be simply rt->rt_ifa.  If rt->rt_ifa != NULL,
    964           1.91    dyoung 		 * then rt_get_ifa() != NULL.  So this ought to still be safe.
    965           1.91    dyoung 		 * --dyoung
    966           1.91    dyoung 		 */
    967           1.91    dyoung 		rtifa = rt_get_ifa(rt);
    968          1.114    dyoung 		info.rti_info[RTAX_IFA] = rtifa->ifa_addr;
    969           1.16       cgd 		if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
    970          1.114    dyoung 			info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr;
    971           1.16       cgd 	}
    972           1.29    chopps 	if ((error = rt_msg2(RTM_GET, &info, 0, w, &size)))
    973           1.95    dyoung 		return error;
    974           1.29    chopps 	if (w->w_where && w->w_tmem && w->w_needed <= 0) {
    975           1.39  augustss 		struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
    976           1.10   mycroft 
    977           1.10   mycroft 		rtm->rtm_flags = rt->rt_flags;
    978           1.10   mycroft 		rtm->rtm_use = rt->rt_use;
    979           1.10   mycroft 		rtm->rtm_rmx = rt->rt_rmx;
    980           1.83  christos 		KASSERT(rt->rt_ifp != NULL);
    981           1.10   mycroft 		rtm->rtm_index = rt->rt_ifp->if_index;
    982           1.10   mycroft 		rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
    983           1.10   mycroft 		rtm->rtm_addrs = info.rti_addrs;
    984           1.21  christos 		if ((error = copyout(rtm, w->w_where, size)) != 0)
    985           1.10   mycroft 			w->w_where = NULL;
    986           1.10   mycroft 		else
    987           1.93  christos 			w->w_where = (char *)w->w_where + size;
    988           1.10   mycroft 	}
    989           1.95    dyoung 	return error;
    990           1.10   mycroft }
    991            1.1       cgd 
    992           1.40    simonb static int
    993           1.69      matt sysctl_iflist(int af, struct walkarg *w, int type)
    994           1.10   mycroft {
    995           1.39  augustss 	struct ifnet *ifp;
    996           1.39  augustss 	struct ifaddr *ifa;
    997           1.10   mycroft 	struct	rt_addrinfo info;
    998           1.10   mycroft 	int	len, error = 0;
    999           1.10   mycroft 
   1000           1.48   thorpej 	memset(&info, 0, sizeof(info));
   1001           1.74      matt 	IFNET_FOREACH(ifp) {
   1002           1.10   mycroft 		if (w->w_arg && w->w_arg != ifp->if_index)
   1003           1.10   mycroft 			continue;
   1004           1.97    dyoung 		if (IFADDR_EMPTY(ifp))
   1005           1.81    rpaulo 			continue;
   1006          1.114    dyoung 		info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
   1007           1.59    itojun 		switch (type) {
   1008           1.32    bouyer 		case NET_RT_IFLIST:
   1009          1.111  christos 			error = rt_msg2(RTM_IFINFO, &info, NULL, w, &len);
   1010           1.32    bouyer 			break;
   1011           1.32    bouyer #ifdef COMPAT_14
   1012           1.32    bouyer 		case NET_RT_OIFLIST:
   1013          1.111  christos 			error = rt_msg2(RTM_OIFINFO, &info, NULL, w, &len);
   1014           1.32    bouyer 			break;
   1015           1.32    bouyer #endif
   1016           1.32    bouyer 		default:
   1017           1.32    bouyer 			panic("sysctl_iflist(1)");
   1018           1.32    bouyer 		}
   1019           1.32    bouyer 		if (error)
   1020           1.95    dyoung 			return error;
   1021          1.114    dyoung 		info.rti_info[RTAX_IFP] = NULL;
   1022           1.29    chopps 		if (w->w_where && w->w_tmem && w->w_needed <= 0) {
   1023           1.59    itojun 			switch (type) {
   1024           1.32    bouyer 			case NET_RT_IFLIST: {
   1025           1.39  augustss 				struct if_msghdr *ifm;
   1026           1.32    bouyer 
   1027           1.32    bouyer 				ifm = (struct if_msghdr *)w->w_tmem;
   1028           1.32    bouyer 				ifm->ifm_index = ifp->if_index;
   1029           1.32    bouyer 				ifm->ifm_flags = ifp->if_flags;
   1030           1.32    bouyer 				ifm->ifm_data = ifp->if_data;
   1031           1.32    bouyer 				ifm->ifm_addrs = info.rti_addrs;
   1032           1.32    bouyer 				error = copyout(ifm, w->w_where, len);
   1033           1.32    bouyer 				if (error)
   1034           1.95    dyoung 					return error;
   1035           1.93  christos 				w->w_where = (char *)w->w_where + len;
   1036           1.32    bouyer 				break;
   1037           1.32    bouyer 			}
   1038           1.10   mycroft 
   1039           1.32    bouyer #ifdef COMPAT_14
   1040           1.32    bouyer 			case NET_RT_OIFLIST: {
   1041           1.39  augustss 				struct if_msghdr14 *ifm;
   1042           1.32    bouyer 
   1043           1.32    bouyer 				ifm = (struct if_msghdr14 *)w->w_tmem;
   1044           1.32    bouyer 				ifm->ifm_index = ifp->if_index;
   1045           1.32    bouyer 				ifm->ifm_flags = ifp->if_flags;
   1046           1.32    bouyer 				ifm->ifm_data.ifi_type = ifp->if_data.ifi_type;
   1047           1.32    bouyer 				ifm->ifm_data.ifi_addrlen =
   1048           1.32    bouyer 				    ifp->if_data.ifi_addrlen;
   1049           1.32    bouyer 				ifm->ifm_data.ifi_hdrlen =
   1050           1.32    bouyer 				    ifp->if_data.ifi_hdrlen;
   1051           1.32    bouyer 				ifm->ifm_data.ifi_mtu = ifp->if_data.ifi_mtu;
   1052           1.32    bouyer 				ifm->ifm_data.ifi_metric =
   1053           1.32    bouyer 				    ifp->if_data.ifi_metric;
   1054           1.32    bouyer 				ifm->ifm_data.ifi_baudrate =
   1055           1.32    bouyer 				    ifp->if_data.ifi_baudrate;
   1056           1.32    bouyer 				ifm->ifm_data.ifi_ipackets =
   1057           1.32    bouyer 				    ifp->if_data.ifi_ipackets;
   1058           1.32    bouyer 				ifm->ifm_data.ifi_ierrors =
   1059           1.32    bouyer 				    ifp->if_data.ifi_ierrors;
   1060           1.32    bouyer 				ifm->ifm_data.ifi_opackets =
   1061           1.32    bouyer 				    ifp->if_data.ifi_opackets;
   1062           1.32    bouyer 				ifm->ifm_data.ifi_oerrors =
   1063           1.32    bouyer 				    ifp->if_data.ifi_oerrors;
   1064           1.32    bouyer 				ifm->ifm_data.ifi_collisions =
   1065           1.32    bouyer 				    ifp->if_data.ifi_collisions;
   1066           1.32    bouyer 				ifm->ifm_data.ifi_ibytes =
   1067           1.32    bouyer 				    ifp->if_data.ifi_ibytes;
   1068           1.32    bouyer 				ifm->ifm_data.ifi_obytes =
   1069           1.32    bouyer 				    ifp->if_data.ifi_obytes;
   1070           1.32    bouyer 				ifm->ifm_data.ifi_imcasts =
   1071           1.32    bouyer 				    ifp->if_data.ifi_imcasts;
   1072           1.32    bouyer 				ifm->ifm_data.ifi_omcasts =
   1073           1.32    bouyer 				    ifp->if_data.ifi_omcasts;
   1074           1.32    bouyer 				ifm->ifm_data.ifi_iqdrops =
   1075           1.32    bouyer 				    ifp->if_data.ifi_iqdrops;
   1076           1.32    bouyer 				ifm->ifm_data.ifi_noproto =
   1077           1.32    bouyer 				    ifp->if_data.ifi_noproto;
   1078           1.32    bouyer 				ifm->ifm_data.ifi_lastchange =
   1079           1.32    bouyer 				    ifp->if_data.ifi_lastchange;
   1080           1.32    bouyer 				ifm->ifm_addrs = info.rti_addrs;
   1081           1.32    bouyer 				error = copyout(ifm, w->w_where, len);
   1082           1.32    bouyer 				if (error)
   1083           1.95    dyoung 					return error;
   1084           1.93  christos 				w->w_where = (char *)w->w_where + len;
   1085           1.32    bouyer 				break;
   1086           1.32    bouyer 			}
   1087           1.32    bouyer #endif
   1088           1.32    bouyer 			default:
   1089           1.32    bouyer 				panic("sysctl_iflist(2)");
   1090           1.32    bouyer 			}
   1091           1.10   mycroft 		}
   1092           1.97    dyoung 		IFADDR_FOREACH(ifa, ifp) {
   1093           1.10   mycroft 			if (af && af != ifa->ifa_addr->sa_family)
   1094           1.10   mycroft 				continue;
   1095          1.114    dyoung 			info.rti_info[RTAX_IFA] = ifa->ifa_addr;
   1096          1.114    dyoung 			info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
   1097          1.114    dyoung 			info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
   1098           1.29    chopps 			if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len)))
   1099           1.95    dyoung 				return error;
   1100           1.29    chopps 			if (w->w_where && w->w_tmem && w->w_needed <= 0) {
   1101           1.39  augustss 				struct ifa_msghdr *ifam;
   1102           1.10   mycroft 
   1103           1.10   mycroft 				ifam = (struct ifa_msghdr *)w->w_tmem;
   1104           1.10   mycroft 				ifam->ifam_index = ifa->ifa_ifp->if_index;
   1105           1.10   mycroft 				ifam->ifam_flags = ifa->ifa_flags;
   1106           1.10   mycroft 				ifam->ifam_metric = ifa->ifa_metric;
   1107           1.10   mycroft 				ifam->ifam_addrs = info.rti_addrs;
   1108           1.17  christos 				error = copyout(w->w_tmem, w->w_where, len);
   1109           1.17  christos 				if (error)
   1110           1.95    dyoung 					return error;
   1111           1.93  christos 				w->w_where = (char *)w->w_where + len;
   1112           1.10   mycroft 			}
   1113           1.10   mycroft 		}
   1114          1.115  christos 		info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
   1115          1.115  christos 		    info.rti_info[RTAX_BRD] = NULL;
   1116           1.10   mycroft 	}
   1117           1.95    dyoung 	return 0;
   1118            1.1       cgd }
   1119            1.1       cgd 
   1120           1.40    simonb static int
   1121           1.65    atatat sysctl_rtable(SYSCTLFN_ARGS)
   1122            1.1       cgd {
   1123           1.65    atatat 	void 	*where = oldp;
   1124           1.65    atatat 	size_t	*given = oldlenp;
   1125           1.65    atatat 	const void *new = newp;
   1126           1.10   mycroft 	int	i, s, error = EINVAL;
   1127           1.10   mycroft 	u_char  af;
   1128            1.1       cgd 	struct	walkarg w;
   1129            1.1       cgd 
   1130           1.66    atatat 	if (namelen == 1 && name[0] == CTL_QUERY)
   1131           1.95    dyoung 		return sysctl_query(SYSCTLFN_CALL(rnode));
   1132           1.66    atatat 
   1133           1.10   mycroft 	if (new)
   1134           1.95    dyoung 		return EPERM;
   1135           1.10   mycroft 	if (namelen != 3)
   1136           1.95    dyoung 		return EINVAL;
   1137           1.10   mycroft 	af = name[0];
   1138           1.29    chopps 	w.w_tmemneeded = 0;
   1139           1.29    chopps 	w.w_tmemsize = 0;
   1140           1.29    chopps 	w.w_tmem = NULL;
   1141           1.29    chopps again:
   1142           1.29    chopps 	/* we may return here if a later [re]alloc of the t_mem buffer fails */
   1143           1.29    chopps 	if (w.w_tmemneeded) {
   1144          1.111  christos 		w.w_tmem = malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK);
   1145           1.29    chopps 		w.w_tmemsize = w.w_tmemneeded;
   1146           1.29    chopps 		w.w_tmemneeded = 0;
   1147           1.29    chopps 	}
   1148           1.29    chopps 	w.w_op = name[1];
   1149           1.29    chopps 	w.w_arg = name[2];
   1150           1.10   mycroft 	w.w_given = *given;
   1151            1.1       cgd 	w.w_needed = 0 - w.w_given;
   1152           1.29    chopps 	w.w_where = where;
   1153            1.1       cgd 
   1154           1.14   mycroft 	s = splsoftnet();
   1155           1.10   mycroft 	switch (w.w_op) {
   1156           1.10   mycroft 
   1157           1.10   mycroft 	case NET_RT_DUMP:
   1158           1.10   mycroft 	case NET_RT_FLAGS:
   1159           1.10   mycroft 		for (i = 1; i <= AF_MAX; i++)
   1160           1.94    dyoung 			if ((af == 0 || af == i) &&
   1161           1.94    dyoung 			    (error = rt_walktree(i, sysctl_dumpentry, &w)))
   1162           1.10   mycroft 				break;
   1163           1.10   mycroft 		break;
   1164           1.10   mycroft 
   1165           1.32    bouyer #ifdef COMPAT_14
   1166           1.32    bouyer 	case NET_RT_OIFLIST:
   1167           1.32    bouyer 		error = sysctl_iflist(af, &w, w.w_op);
   1168           1.32    bouyer 		break;
   1169           1.32    bouyer #endif
   1170           1.32    bouyer 
   1171           1.10   mycroft 	case NET_RT_IFLIST:
   1172           1.32    bouyer 		error = sysctl_iflist(af, &w, w.w_op);
   1173            1.1       cgd 	}
   1174           1.10   mycroft 	splx(s);
   1175           1.29    chopps 
   1176           1.29    chopps 	/* check to see if we couldn't allocate memory with NOWAIT */
   1177           1.29    chopps 	if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded)
   1178           1.29    chopps 		goto again;
   1179           1.29    chopps 
   1180           1.10   mycroft 	if (w.w_tmem)
   1181           1.10   mycroft 		free(w.w_tmem, M_RTABLE);
   1182            1.1       cgd 	w.w_needed += w.w_given;
   1183           1.10   mycroft 	if (where) {
   1184           1.93  christos 		*given = (char *)w.w_where - (char *)where;
   1185           1.10   mycroft 		if (*given < w.w_needed)
   1186           1.95    dyoung 			return ENOMEM;
   1187           1.10   mycroft 	} else {
   1188           1.10   mycroft 		*given = (11 * w.w_needed) / 10;
   1189           1.10   mycroft 	}
   1190           1.95    dyoung 	return error;
   1191            1.1       cgd }
   1192            1.1       cgd 
   1193            1.1       cgd /*
   1194           1.99        ad  * Routing message software interrupt routine
   1195           1.99        ad  */
   1196           1.99        ad static void
   1197           1.99        ad route_intr(void *cookie)
   1198           1.99        ad {
   1199           1.99        ad 	struct sockproto proto = { .sp_family = PF_ROUTE, };
   1200           1.99        ad 	struct mbuf *m;
   1201           1.99        ad 	int s;
   1202           1.99        ad 
   1203          1.101        ad 	mutex_enter(softnet_lock);
   1204          1.101        ad 	KERNEL_LOCK(1, NULL);
   1205           1.99        ad 	while (!IF_IS_EMPTY(&route_intrq)) {
   1206           1.99        ad 		s = splnet();
   1207           1.99        ad 		IF_DEQUEUE(&route_intrq, m);
   1208           1.99        ad 		splx(s);
   1209           1.99        ad 		if (m == NULL)
   1210           1.99        ad 			break;
   1211          1.100      yamt 		proto.sp_protocol = M_GETCTX(m, uintptr_t);
   1212           1.99        ad 		raw_input(m, &proto, &route_src, &route_dst);
   1213           1.99        ad 	}
   1214          1.101        ad 	KERNEL_UNLOCK_ONE(NULL);
   1215          1.101        ad 	mutex_exit(softnet_lock);
   1216           1.99        ad }
   1217           1.99        ad 
   1218           1.99        ad /*
   1219           1.99        ad  * Enqueue a message to the software interrupt routine.
   1220           1.99        ad  */
   1221           1.99        ad static void
   1222           1.99        ad route_enqueue(struct mbuf *m, int family)
   1223           1.99        ad {
   1224           1.99        ad 	int s, wasempty;
   1225           1.99        ad 
   1226           1.99        ad 	s = splnet();
   1227           1.99        ad 	if (IF_QFULL(&route_intrq)) {
   1228           1.99        ad 		IF_DROP(&route_intrq);
   1229           1.99        ad 		m_freem(m);
   1230           1.99        ad 	} else {
   1231           1.99        ad 		wasempty = IF_IS_EMPTY(&route_intrq);
   1232           1.99        ad 		M_SETCTX(m, (uintptr_t)family);
   1233           1.99        ad 		IF_ENQUEUE(&route_intrq, m);
   1234           1.99        ad 		if (wasempty)
   1235           1.99        ad 			softint_schedule(route_sih);
   1236           1.99        ad 	}
   1237           1.99        ad 	splx(s);
   1238           1.99        ad }
   1239           1.99        ad 
   1240           1.99        ad void
   1241           1.99        ad rt_init(void)
   1242           1.99        ad {
   1243           1.99        ad 
   1244           1.99        ad 	route_intrq.ifq_maxlen = route_maxqlen;
   1245          1.101        ad 	route_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
   1246          1.101        ad 	    route_intr, NULL);
   1247           1.99        ad }
   1248           1.99        ad 
   1249           1.99        ad /*
   1250            1.1       cgd  * Definitions of protocols supported in the ROUTE domain.
   1251            1.1       cgd  */
   1252          1.101        ad PR_WRAP_USRREQ(route_usrreq)
   1253          1.101        ad #define	route_usrreq	route_usrreq_wrapper
   1254            1.1       cgd 
   1255           1.70      matt const struct protosw routesw[] = {
   1256           1.92      matt 	{
   1257           1.92      matt 		.pr_type = SOCK_RAW,
   1258           1.92      matt 		.pr_domain = &routedomain,
   1259           1.92      matt 		.pr_flags = PR_ATOMIC|PR_ADDR,
   1260           1.92      matt 		.pr_input = raw_input,
   1261           1.92      matt 		.pr_output = route_output,
   1262           1.92      matt 		.pr_ctlinput = raw_ctlinput,
   1263           1.92      matt 		.pr_usrreq = route_usrreq,
   1264           1.92      matt 		.pr_init = raw_init,
   1265           1.92      matt 	},
   1266           1.92      matt };
   1267           1.69      matt 
   1268           1.69      matt struct domain routedomain = {
   1269           1.87  christos 	.dom_family = PF_ROUTE,
   1270           1.87  christos 	.dom_name = "route",
   1271           1.87  christos 	.dom_init = route_init,
   1272           1.87  christos 	.dom_protosw = routesw,
   1273           1.95    dyoung 	.dom_protoswNPROTOSW = &routesw[__arraycount(routesw)],
   1274            1.1       cgd };
   1275            1.1       cgd 
   1276           1.65    atatat SYSCTL_SETUP(sysctl_net_route_setup, "sysctl net.route subtree setup")
   1277           1.65    atatat {
   1278           1.85      elad 	const struct sysctlnode *rnode = NULL;
   1279           1.85      elad 
   1280           1.67    atatat 	sysctl_createv(clog, 0, NULL, NULL,
   1281           1.67    atatat 		       CTLFLAG_PERMANENT,
   1282           1.65    atatat 		       CTLTYPE_NODE, "net", NULL,
   1283           1.65    atatat 		       NULL, 0, NULL, 0,
   1284           1.65    atatat 		       CTL_NET, CTL_EOL);
   1285           1.65    atatat 
   1286           1.85      elad 	sysctl_createv(clog, 0, NULL, &rnode,
   1287           1.67    atatat 		       CTLFLAG_PERMANENT,
   1288           1.71    atatat 		       CTLTYPE_NODE, "route",
   1289           1.71    atatat 		       SYSCTL_DESCR("PF_ROUTE information"),
   1290           1.65    atatat 		       NULL, 0, NULL, 0,
   1291           1.65    atatat 		       CTL_NET, PF_ROUTE, CTL_EOL);
   1292           1.67    atatat 	sysctl_createv(clog, 0, NULL, NULL,
   1293           1.67    atatat 		       CTLFLAG_PERMANENT,
   1294           1.71    atatat 		       CTLTYPE_NODE, "rtable",
   1295           1.71    atatat 		       SYSCTL_DESCR("Routing table information"),
   1296           1.65    atatat 		       sysctl_rtable, 0, NULL, 0,
   1297           1.65    atatat 		       CTL_NET, PF_ROUTE, 0 /* any protocol */, CTL_EOL);
   1298           1.85      elad 	sysctl_createv(clog, 0, &rnode, NULL,
   1299           1.85      elad 		       CTLFLAG_PERMANENT,
   1300           1.85      elad 		       CTLTYPE_STRUCT, "stats",
   1301           1.85      elad 		       SYSCTL_DESCR("Routing statistics"),
   1302           1.85      elad 		       NULL, 0, &rtstat, sizeof(rtstat),
   1303           1.85      elad 		       CTL_CREATE, CTL_EOL);
   1304           1.65    atatat }
   1305