File:  [DragonFly] / src / sys / net / rtsock.c
Revision 1.12: download - view: text, annotated - select for diffs
Thu Apr 22 04:21:29 2004 UTC (10 years ago) by dillon
Branches: MAIN
CVS tags: HEAD
M_NOWAIT -> M_WAITOK or M_INTWAIT conversions.  There is a whole lot of net
code that is improperly using M_NOWAIT.  Also remove now unneeded NULL checks
since malloc will panic rather then return NULL when M_NULLOK is not set.

Use M_INTWAIT|M_NULLOK in some cases (such as route table allocation) in
order to allow malloc to return NULL when the limit for the malloc type
is reached.

    1: /*
    2:  * Copyright (c) 1988, 1991, 1993
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  * 3. All advertising materials mentioning features or use of this software
   14:  *    must display the following acknowledgement:
   15:  *	This product includes software developed by the University of
   16:  *	California, Berkeley and its contributors.
   17:  * 4. Neither the name of the University nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  *
   21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  *
   33:  *	@(#)rtsock.c	8.7 (Berkeley) 10/12/95
   34:  * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
   35:  * $DragonFly: src/sys/net/rtsock.c,v 1.12 2004/04/22 04:21:29 dillon Exp $
   36:  */
   37: 
   38: 
   39: #include <sys/param.h>
   40: #include <sys/systm.h>
   41: #include <sys/kernel.h>
   42: #include <sys/sysctl.h>
   43: #include <sys/proc.h>
   44: #include <sys/malloc.h>
   45: #include <sys/mbuf.h>
   46: #include <sys/protosw.h>
   47: #include <sys/socket.h>
   48: #include <sys/socketvar.h>
   49: #include <sys/domain.h>
   50: 
   51: #include <net/if.h>
   52: #include <net/route.h>
   53: #include <net/raw_cb.h>
   54: 
   55: MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
   56: 
   57: static struct	sockaddr route_dst = { 2, PF_ROUTE, };
   58: static struct	sockaddr route_src = { 2, PF_ROUTE, };
   59: static struct	sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
   60: static struct	sockproto route_proto = { PF_ROUTE, };
   61: 
   62: struct walkarg {
   63: 	int	w_tmemsize;
   64: 	int	w_op, w_arg;
   65: 	caddr_t	w_tmem;
   66: 	struct sysctl_req *w_req;
   67: };
   68: 
   69: static struct mbuf *
   70: 		rt_msg1 (int, struct rt_addrinfo *);
   71: static int	rt_msg2 (int, struct rt_addrinfo *, caddr_t, struct walkarg *);
   72: static int	rt_xaddrs (caddr_t, caddr_t, struct rt_addrinfo *);
   73: static int	sysctl_dumpentry (struct radix_node *rn, void *vw);
   74: static int	sysctl_iflist (int af, struct walkarg *w);
   75: static int	route_output (struct mbuf *, struct socket *,
   76: 		    struct pr_output_info *);
   77: static void	rt_setmetrics (u_long, struct rt_metrics *,
   78: 		    struct rt_metrics *);
   79: 
   80: /* Sleazy use of local variables throughout file, warning!!!! */
   81: #define dst	info.rti_info[RTAX_DST]
   82: #define gate	info.rti_info[RTAX_GATEWAY]
   83: #define netmask	info.rti_info[RTAX_NETMASK]
   84: #define genmask	info.rti_info[RTAX_GENMASK]
   85: #define ifpaddr	info.rti_info[RTAX_IFP]
   86: #define ifaaddr	info.rti_info[RTAX_IFA]
   87: #define brdaddr	info.rti_info[RTAX_BRD]
   88: 
   89: /*
   90:  * It really doesn't make any sense at all for this code to share much
   91:  * with raw_usrreq.c, since its functionality is so restricted.  XXX
   92:  */
   93: static int
   94: rts_abort(struct socket *so)
   95: {
   96: 	int s, error;
   97: 	s = splnet();
   98: 	error = raw_usrreqs.pru_abort(so);
   99: 	splx(s);
  100: 	return error;
  101: }
  102: 
  103: /* pru_accept is EOPNOTSUPP */
  104: 
  105: static int
  106: rts_attach(struct socket *so, int proto, struct pru_attach_info *ai)
  107: {
  108: 	struct rawcb *rp;
  109: 	int s, error;
  110: 
  111: 	if (sotorawcb(so) != 0)
  112: 		return EISCONN;	/* XXX panic? */
  113: 	MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK|M_ZERO);
  114: 	if (rp == 0)
  115: 		return ENOBUFS;
  116: 
  117: 	/*
  118: 	 * The splnet() is necessary to block protocols from sending
  119: 	 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  120: 	 * this PCB is extant but incompletely initialized.
  121: 	 * Probably we should try to do more of this work beforehand and
  122: 	 * eliminate the spl.
  123: 	 */
  124: 	s = splnet();
  125: 	so->so_pcb = (caddr_t)rp;
  126: 	error = raw_attach(so, proto, ai->sb_rlimit);
  127: 	rp = sotorawcb(so);
  128: 	if (error) {
  129: 		splx(s);
  130: 		free(rp, M_PCB);
  131: 		return error;
  132: 	}
  133: 	switch(rp->rcb_proto.sp_protocol) {
  134: 	case AF_INET:
  135: 		route_cb.ip_count++;
  136: 		break;
  137: 	case AF_INET6:
  138: 		route_cb.ip6_count++;
  139: 		break;
  140: 	case AF_IPX:
  141: 		route_cb.ipx_count++;
  142: 		break;
  143: 	case AF_NS:
  144: 		route_cb.ns_count++;
  145: 		break;
  146: 	}
  147: 	rp->rcb_faddr = &route_src;
  148: 	route_cb.any_count++;
  149: 	soisconnected(so);
  150: 	so->so_options |= SO_USELOOPBACK;
  151: 	splx(s);
  152: 	return 0;
  153: }
  154: 
  155: static int
  156: rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  157: {
  158: 	int s, error;
  159: 	s = splnet();
  160: 	error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
  161: 	splx(s);
  162: 	return error;
  163: }
  164: 
  165: static int
  166: rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  167: {
  168: 	int s, error;
  169: 	s = splnet();
  170: 	error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
  171: 	splx(s);
  172: 	return error;
  173: }
  174: 
  175: /* pru_connect2 is EOPNOTSUPP */
  176: /* pru_control is EOPNOTSUPP */
  177: 
  178: static int
  179: rts_detach(struct socket *so)
  180: {
  181: 	struct rawcb *rp = sotorawcb(so);
  182: 	int s, error;
  183: 
  184: 	s = splnet();
  185: 	if (rp != 0) {
  186: 		switch(rp->rcb_proto.sp_protocol) {
  187: 		case AF_INET:
  188: 			route_cb.ip_count--;
  189: 			break;
  190: 		case AF_INET6:
  191: 			route_cb.ip6_count--;
  192: 			break;
  193: 		case AF_IPX:
  194: 			route_cb.ipx_count--;
  195: 			break;
  196: 		case AF_NS:
  197: 			route_cb.ns_count--;
  198: 			break;
  199: 		}
  200: 		route_cb.any_count--;
  201: 	}
  202: 	error = raw_usrreqs.pru_detach(so);
  203: 	splx(s);
  204: 	return error;
  205: }
  206: 
  207: static int
  208: rts_disconnect(struct socket *so)
  209: {
  210: 	int s, error;
  211: 	s = splnet();
  212: 	error = raw_usrreqs.pru_disconnect(so);
  213: 	splx(s);
  214: 	return error;
  215: }
  216: 
  217: /* pru_listen is EOPNOTSUPP */
  218: 
  219: static int
  220: rts_peeraddr(struct socket *so, struct sockaddr **nam)
  221: {
  222: 	int s, error;
  223: 	s = splnet();
  224: 	error = raw_usrreqs.pru_peeraddr(so, nam);
  225: 	splx(s);
  226: 	return error;
  227: }
  228: 
  229: /* pru_rcvd is EOPNOTSUPP */
  230: /* pru_rcvoob is EOPNOTSUPP */
  231: 
  232: static int
  233: rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  234: 	 struct mbuf *control, struct thread *td)
  235: {
  236: 	int s, error;
  237: 	s = splnet();
  238: 	error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
  239: 	splx(s);
  240: 	return error;
  241: }
  242: 
  243: /* pru_sense is null */
  244: 
  245: static int
  246: rts_shutdown(struct socket *so)
  247: {
  248: 	int s, error;
  249: 	s = splnet();
  250: 	error = raw_usrreqs.pru_shutdown(so);
  251: 	splx(s);
  252: 	return error;
  253: }
  254: 
  255: static int
  256: rts_sockaddr(struct socket *so, struct sockaddr **nam)
  257: {
  258: 	int s, error;
  259: 	s = splnet();
  260: 	error = raw_usrreqs.pru_sockaddr(so, nam);
  261: 	splx(s);
  262: 	return error;
  263: }
  264: 
  265: static struct pr_usrreqs route_usrreqs = {
  266: 	rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
  267: 	pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
  268: 	pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
  269: 	rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
  270: 	sosend, soreceive, sopoll
  271: };
  272: 
  273: /*ARGSUSED*/
  274: static int
  275: route_output(struct mbuf *m, struct socket *so, struct pr_output_info *oi)
  276: {
  277: 	struct rt_msghdr *rtm = 0;
  278: 	struct rtentry *rt = 0;
  279: 	struct rtentry *saved_nrt = 0;
  280: 	struct radix_node_head *rnh;
  281: 	struct rt_addrinfo info;
  282: 	int len, error = 0;
  283: 	struct ifnet *ifp = 0;
  284: 	struct ifaddr *ifa = 0;
  285: 
  286: #define senderr(e) { error = e; goto flush;}
  287: 	if (m == 0 || ((m->m_len < sizeof(long)) &&
  288: 		       (m = m_pullup(m, sizeof(long))) == 0))
  289: 		return (ENOBUFS);
  290: 	if ((m->m_flags & M_PKTHDR) == 0)
  291: 		panic("route_output");
  292: 	len = m->m_pkthdr.len;
  293: 	if (len < sizeof(*rtm) ||
  294: 	    len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  295: 		dst = 0;
  296: 		senderr(EINVAL);
  297: 	}
  298: 	R_Malloc(rtm, struct rt_msghdr *, len);
  299: 	if (rtm == 0) {
  300: 		dst = 0;
  301: 		senderr(ENOBUFS);
  302: 	}
  303: 	m_copydata(m, 0, len, (caddr_t)rtm);
  304: 	if (rtm->rtm_version != RTM_VERSION) {
  305: 		dst = 0;
  306: 		senderr(EPROTONOSUPPORT);
  307: 	}
  308: 	rtm->rtm_pid = oi->p_pid;
  309: 	bzero(&info, sizeof(info));
  310: 	info.rti_addrs = rtm->rtm_addrs;
  311: 	if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
  312: 		dst = 0;
  313: 		senderr(EINVAL);
  314: 	}
  315: 	info.rti_flags = rtm->rtm_flags;
  316: 	if (dst == 0 || (dst->sa_family >= AF_MAX)
  317: 	    || (gate != 0 && (gate->sa_family >= AF_MAX)))
  318: 		senderr(EINVAL);
  319: 	if (genmask) {
  320: 		struct radix_node *t;
  321: 		t = rn_addmask((caddr_t)genmask, 0, 1);
  322: 		if (t && Bcmp((caddr_t *)genmask + 1, (caddr_t *)t->rn_key + 1,
  323: 			      *(u_char *)t->rn_key - 1) == 0)
  324: 			genmask = (struct sockaddr *)(t->rn_key);
  325: 		else
  326: 			senderr(ENOBUFS);
  327: 	}
  328: 
  329: 	/*
  330: 	 * Verify that the caller has the appropriate privilege; RTM_GET
  331: 	 * is the only operation the non-superuser is allowed.
  332: 	 */
  333: 	if (rtm->rtm_type != RTM_GET && suser_cred(so->so_cred, 0) != 0)
  334: 		senderr(EPERM);
  335: 
  336: 	switch (rtm->rtm_type) {
  337: 
  338: 	case RTM_ADD:
  339: 		if (gate == 0)
  340: 			senderr(EINVAL);
  341: 		error = rtrequest1(RTM_ADD, &info, &saved_nrt);
  342: 		if (error == 0 && saved_nrt) {
  343: 			rt_setmetrics(rtm->rtm_inits,
  344: 				&rtm->rtm_rmx, &saved_nrt->rt_rmx);
  345: 			saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  346: 			saved_nrt->rt_rmx.rmx_locks |=
  347: 				(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  348: 			saved_nrt->rt_refcnt--;
  349: 			saved_nrt->rt_genmask = genmask;
  350: 		}
  351: 		break;
  352: 
  353: 	case RTM_DELETE:
  354: 		error = rtrequest1(RTM_DELETE, &info, &saved_nrt);
  355: 		if (error == 0) {
  356: 			if ((rt = saved_nrt))
  357: 				rt->rt_refcnt++;
  358: 			goto report;
  359: 		}
  360: 		break;
  361: 
  362: 	case RTM_GET:
  363: 	case RTM_CHANGE:
  364: 	case RTM_LOCK:
  365: 		if ((rnh = rt_tables[dst->sa_family]) == 0) {
  366: 			senderr(EAFNOSUPPORT);
  367: 		} else if ((rt = (struct rtentry *)
  368: 				rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
  369: 			rt->rt_refcnt++;
  370: 		else
  371: 			senderr(ESRCH);
  372: 		switch(rtm->rtm_type) {
  373: 
  374: 		case RTM_GET:
  375: 		report:
  376: 			dst = rt_key(rt);
  377: 			gate = rt->rt_gateway;
  378: 			netmask = rt_mask(rt);
  379: 			genmask = rt->rt_genmask;
  380: 			if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  381: 				ifp = rt->rt_ifp;
  382: 				if (ifp) {
  383: 					ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
  384: 					ifaaddr = rt->rt_ifa->ifa_addr;
  385: 					if (ifp->if_flags & IFF_POINTOPOINT)
  386: 						brdaddr = rt->rt_ifa->ifa_dstaddr;
  387: 					rtm->rtm_index = ifp->if_index;
  388: 				} else {
  389: 					ifpaddr = 0;
  390: 					ifaaddr = 0;
  391: 			    }
  392: 			}
  393: 			len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
  394: 				(struct walkarg *)0);
  395: 			if (len > rtm->rtm_msglen) {
  396: 				struct rt_msghdr *new_rtm;
  397: 				R_Malloc(new_rtm, struct rt_msghdr *, len);
  398: 				if (new_rtm == 0)
  399: 					senderr(ENOBUFS);
  400: 				Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  401: 				Free(rtm); rtm = new_rtm;
  402: 			}
  403: 			(void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
  404: 				(struct walkarg *)0);
  405: 			rtm->rtm_flags = rt->rt_flags;
  406: 			rtm->rtm_rmx = rt->rt_rmx;
  407: 			rtm->rtm_addrs = info.rti_addrs;
  408: 			break;
  409: 
  410: 		case RTM_CHANGE:
  411: 			/* new gateway could require new ifaddr, ifp;
  412: 			   flags may also be different; ifp may be specified
  413: 			   by ll sockaddr when protocol address is ambiguous */
  414: #define	equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
  415: 			if ((rt->rt_flags & RTF_GATEWAY && gate != NULL) ||
  416: 			    ifpaddr != NULL ||
  417: 			    (ifaaddr != NULL &&
  418: 			    !equal(ifaaddr, rt->rt_ifa->ifa_addr))) {
  419: 				if ((error = rt_getifa(&info)) != 0)
  420: 					senderr(error);
  421: 			}
  422: 			if (gate != NULL &&
  423: 			    (error = rt_setgate(rt, rt_key(rt), gate)) != 0)
  424: 				senderr(error);
  425: 			if ((ifa = info.rti_ifa) != NULL) {
  426: 				struct ifaddr *oifa = rt->rt_ifa;
  427: 				if (oifa != ifa) {
  428: 				    if (oifa && oifa->ifa_rtrequest)
  429: 					oifa->ifa_rtrequest(RTM_DELETE, rt,
  430: 					    &info);
  431: 				    IFAFREE(rt->rt_ifa);
  432: 				    rt->rt_ifa = ifa;
  433: 				    ifa->ifa_refcnt++;
  434: 				    rt->rt_ifp = info.rti_ifp;
  435: 				}
  436: 			}
  437: 			rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  438: 					&rt->rt_rmx);
  439: 			if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  440: 			       rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
  441: 			if (genmask)
  442: 				rt->rt_genmask = genmask;
  443: 			/*
  444: 			 * Fall into
  445: 			 */
  446: 		case RTM_LOCK:
  447: 			rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  448: 			rt->rt_rmx.rmx_locks |=
  449: 				(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  450: 			break;
  451: 		}
  452: 		break;
  453: 
  454: 	default:
  455: 		senderr(EOPNOTSUPP);
  456: 	}
  457: 
  458: flush:
  459: 	if (rtm) {
  460: 		if (error)
  461: 			rtm->rtm_errno = error;
  462: 		else
  463: 			rtm->rtm_flags |= RTF_DONE;
  464: 	}
  465: 	if (rt)
  466: 		rtfree(rt);
  467:     {
  468: 	struct rawcb *rp = 0;
  469: 	/*
  470: 	 * Check to see if we don't want our own messages.
  471: 	 */
  472: 	if ((so->so_options & SO_USELOOPBACK) == 0) {
  473: 		if (route_cb.any_count <= 1) {
  474: 			if (rtm)
  475: 				Free(rtm);
  476: 			m_freem(m);
  477: 			return (error);
  478: 		}
  479: 		/* There is another listener, so construct message */
  480: 		rp = sotorawcb(so);
  481: 	}
  482: 	if (rtm) {
  483: 		m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  484: 		if (m->m_pkthdr.len < rtm->rtm_msglen) {
  485: 			m_freem(m);
  486: 			m = NULL;
  487: 		} else if (m->m_pkthdr.len > rtm->rtm_msglen)
  488: 			m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  489: 		Free(rtm);
  490: 	}
  491: 	if (rp)
  492: 		rp->rcb_proto.sp_family = 0; /* Avoid us */
  493: 	if (dst)
  494: 		route_proto.sp_protocol = dst->sa_family;
  495: 	if (m)
  496: 		raw_input(m, &route_proto, &route_src, &route_dst);
  497: 	if (rp)
  498: 		rp->rcb_proto.sp_family = PF_ROUTE;
  499:     }
  500: 	return (error);
  501: }
  502: 
  503: static void
  504: rt_setmetrics(which, in, out)
  505: 	u_long which;
  506: 	struct rt_metrics *in, *out;
  507: {
  508: #define metric(f, e) if (which & (f)) out->e = in->e;
  509: 	metric(RTV_RPIPE, rmx_recvpipe);
  510: 	metric(RTV_SPIPE, rmx_sendpipe);
  511: 	metric(RTV_SSTHRESH, rmx_ssthresh);
  512: 	metric(RTV_RTT, rmx_rtt);
  513: 	metric(RTV_RTTVAR, rmx_rttvar);
  514: 	metric(RTV_HOPCOUNT, rmx_hopcount);
  515: 	metric(RTV_MTU, rmx_mtu);
  516: 	metric(RTV_EXPIRE, rmx_expire);
  517: #undef metric
  518: }
  519: 
  520: #define ROUNDUP(a) \
  521: 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  522: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  523: 
  524: 
  525: /*
  526:  * Extract the addresses of the passed sockaddrs.
  527:  * Do a little sanity checking so as to avoid bad memory references.
  528:  * This data is derived straight from userland.
  529:  */
  530: static int
  531: rt_xaddrs(cp, cplim, rtinfo)
  532: 	caddr_t cp, cplim;
  533: 	struct rt_addrinfo *rtinfo;
  534: {
  535: 	struct sockaddr *sa;
  536: 	int i;
  537: 
  538: 	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  539: 		if ((rtinfo->rti_addrs & (1 << i)) == 0)
  540: 			continue;
  541: 		sa = (struct sockaddr *)cp;
  542: 		/*
  543: 		 * It won't fit.
  544: 		 */
  545: 		if ( (cp + sa->sa_len) > cplim ) {
  546: 			return (EINVAL);
  547: 		}
  548: 
  549: 		/*
  550: 		 * there are no more.. quit now
  551: 		 * If there are more bits, they are in error.
  552: 		 * I've seen this. route(1) can evidently generate these. 
  553: 		 * This causes kernel to core dump.
  554: 		 * for compatibility, If we see this, point to a safe address.
  555: 		 */
  556: 		if (sa->sa_len == 0) {
  557: 			rtinfo->rti_info[i] = &sa_zero;
  558: 			return (0); /* should be EINVAL but for compat */
  559: 		}
  560: 
  561: 		/* accept it */
  562: 		rtinfo->rti_info[i] = sa;
  563: 		ADVANCE(cp, sa);
  564: 	}
  565: 	return (0);
  566: }
  567: 
  568: static struct mbuf *
  569: rt_msg1(type, rtinfo)
  570: 	int type;
  571: 	struct rt_addrinfo *rtinfo;
  572: {
  573: 	struct rt_msghdr *rtm;
  574: 	struct mbuf *m;
  575: 	int i;
  576: 	struct sockaddr *sa;
  577: 	int len, dlen;
  578: 
  579: 	switch (type) {
  580: 
  581: 	case RTM_DELADDR:
  582: 	case RTM_NEWADDR:
  583: 		len = sizeof(struct ifa_msghdr);
  584: 		break;
  585: 
  586: 	case RTM_DELMADDR:
  587: 	case RTM_NEWMADDR:
  588: 		len = sizeof(struct ifma_msghdr);
  589: 		break;
  590: 
  591: 	case RTM_IFINFO:
  592: 		len = sizeof(struct if_msghdr);
  593: 		break;
  594: 
  595: 	case RTM_IFANNOUNCE:
  596: 		len = sizeof(struct if_announcemsghdr);
  597: 		break;
  598: 
  599: 	default:
  600: 		len = sizeof(struct rt_msghdr);
  601: 	}
  602: 	if (len > MCLBYTES)
  603: 		panic("rt_msg1");
  604: 	m = m_gethdr(M_DONTWAIT, MT_DATA);
  605: 	if (m && len > MHLEN) {
  606: 		MCLGET(m, M_DONTWAIT);
  607: 		if ((m->m_flags & M_EXT) == 0) {
  608: 			m_free(m);
  609: 			m = NULL;
  610: 		}
  611: 	}
  612: 	if (m == 0)
  613: 		return (m);
  614: 	m->m_pkthdr.len = m->m_len = len;
  615: 	m->m_pkthdr.rcvif = 0;
  616: 	rtm = mtod(m, struct rt_msghdr *);
  617: 	bzero((caddr_t)rtm, len);
  618: 	for (i = 0; i < RTAX_MAX; i++) {
  619: 		if ((sa = rtinfo->rti_info[i]) == NULL)
  620: 			continue;
  621: 		rtinfo->rti_addrs |= (1 << i);
  622: 		dlen = ROUNDUP(sa->sa_len);
  623: 		m_copyback(m, len, dlen, (caddr_t)sa);
  624: 		len += dlen;
  625: 	}
  626: 	if (m->m_pkthdr.len != len) {
  627: 		m_freem(m);
  628: 		return (NULL);
  629: 	}
  630: 	rtm->rtm_msglen = len;
  631: 	rtm->rtm_version = RTM_VERSION;
  632: 	rtm->rtm_type = type;
  633: 	return (m);
  634: }
  635: 
  636: static int
  637: rt_msg2(type, rtinfo, cp, w)
  638: 	int type;
  639: 	struct rt_addrinfo *rtinfo;
  640: 	caddr_t cp;
  641: 	struct walkarg *w;
  642: {
  643: 	int i;
  644: 	int len, dlen, second_time = 0;
  645: 	caddr_t cp0;
  646: 
  647: 	rtinfo->rti_addrs = 0;
  648: again:
  649: 	switch (type) {
  650: 
  651: 	case RTM_DELADDR:
  652: 	case RTM_NEWADDR:
  653: 		len = sizeof(struct ifa_msghdr);
  654: 		break;
  655: 
  656: 	case RTM_IFINFO:
  657: 		len = sizeof(struct if_msghdr);
  658: 		break;
  659: 
  660: 	default:
  661: 		len = sizeof(struct rt_msghdr);
  662: 	}
  663: 	cp0 = cp;
  664: 	if (cp0)
  665: 		cp += len;
  666: 	for (i = 0; i < RTAX_MAX; i++) {
  667: 		struct sockaddr *sa;
  668: 
  669: 		if ((sa = rtinfo->rti_info[i]) == 0)
  670: 			continue;
  671: 		rtinfo->rti_addrs |= (1 << i);
  672: 		dlen = ROUNDUP(sa->sa_len);
  673: 		if (cp) {
  674: 			bcopy((caddr_t)sa, cp, (unsigned)dlen);
  675: 			cp += dlen;
  676: 		}
  677: 		len += dlen;
  678: 	}
  679: 	len = ALIGN(len);
  680: 	if (cp == 0 && w != NULL && !second_time) {
  681: 		struct walkarg *rw = w;
  682: 
  683: 		if (rw->w_req) {
  684: 			if (rw->w_tmemsize < len) {
  685: 				if (rw->w_tmem)
  686: 					free(rw->w_tmem, M_RTABLE);
  687: 				rw->w_tmem = (caddr_t)malloc(len, M_RTABLE,
  688: 							M_INTWAIT | M_NULLOK);
  689: 				if (rw->w_tmem)
  690: 					rw->w_tmemsize = len;
  691: 			}
  692: 			if (rw->w_tmem) {
  693: 				cp = rw->w_tmem;
  694: 				second_time = 1;
  695: 				goto again;
  696: 			}
  697: 		}
  698: 	}
  699: 	if (cp) {
  700: 		struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  701: 
  702: 		rtm->rtm_version = RTM_VERSION;
  703: 		rtm->rtm_type = type;
  704: 		rtm->rtm_msglen = len;
  705: 	}
  706: 	return (len);
  707: }
  708: 
  709: /*
  710:  * This routine is called to generate a message from the routing
  711:  * socket indicating that a redirect has occured, a routing lookup
  712:  * has failed, or that a protocol has detected timeouts to a particular
  713:  * destination.
  714:  */
  715: void
  716: rt_missmsg(type, rtinfo, flags, error)
  717: 	int type, flags, error;
  718: 	struct rt_addrinfo *rtinfo;
  719: {
  720: 	struct rt_msghdr *rtm;
  721: 	struct mbuf *m;
  722: 	struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  723: 
  724: 	if (route_cb.any_count == 0)
  725: 		return;
  726: 	m = rt_msg1(type, rtinfo);
  727: 	if (m == 0)
  728: 		return;
  729: 	rtm = mtod(m, struct rt_msghdr *);
  730: 	rtm->rtm_flags = RTF_DONE | flags;
  731: 	rtm->rtm_errno = error;
  732: 	rtm->rtm_addrs = rtinfo->rti_addrs;
  733: 	route_proto.sp_protocol = sa ? sa->sa_family : 0;
  734: 	raw_input(m, &route_proto, &route_src, &route_dst);
  735: }
  736: 
  737: /*
  738:  * This routine is called to generate a message from the routing
  739:  * socket indicating that the status of a network interface has changed.
  740:  */
  741: void
  742: rt_ifmsg(ifp)
  743: 	struct ifnet *ifp;
  744: {
  745: 	struct if_msghdr *ifm;
  746: 	struct mbuf *m;
  747: 	struct rt_addrinfo info;
  748: 
  749: 	if (route_cb.any_count == 0)
  750: 		return;
  751: 	bzero((caddr_t)&info, sizeof(info));
  752: 	m = rt_msg1(RTM_IFINFO, &info);
  753: 	if (m == 0)
  754: 		return;
  755: 	ifm = mtod(m, struct if_msghdr *);
  756: 	ifm->ifm_index = ifp->if_index;
  757: 	ifm->ifm_flags = (u_short)ifp->if_flags;
  758: 	ifm->ifm_data = ifp->if_data;
  759: 	ifm->ifm_addrs = 0;
  760: 	route_proto.sp_protocol = 0;
  761: 	raw_input(m, &route_proto, &route_src, &route_dst);
  762: }
  763: 
  764: static void
  765: rt_ifamsg(int cmd, struct ifaddr *ifa)
  766: {
  767: 	struct ifa_msghdr *ifam;
  768: 	struct rt_addrinfo info;
  769: 	struct mbuf *m;
  770: 	struct sockaddr *sa;
  771: 	struct ifnet *ifp = ifa->ifa_ifp;
  772: 
  773: 	bzero(&info, sizeof(info));
  774: 	ifaaddr = sa = ifa->ifa_addr;
  775: 	ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
  776: 	netmask = ifa->ifa_netmask;
  777: 	brdaddr = ifa->ifa_dstaddr;
  778: 	if ((m = rt_msg1(cmd, &info)) == NULL)
  779: 		return;
  780: 	ifam = mtod(m, struct ifa_msghdr *);
  781: 	ifam->ifam_index = ifp->if_index;
  782: 	ifam->ifam_metric = ifa->ifa_metric;
  783: 	ifam->ifam_flags = ifa->ifa_flags;
  784: 	ifam->ifam_addrs = info.rti_addrs;
  785: 
  786: 	route_proto.sp_protocol = sa ? sa->sa_family : 0;
  787: 	raw_input(m, &route_proto, &route_src, &route_dst);
  788: }
  789: 
  790: static void
  791: rt_rtmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
  792: {
  793: 	struct rt_msghdr *rtm;
  794: 	struct rt_addrinfo info;
  795: 	struct mbuf *m;
  796: 	struct sockaddr *sa;
  797: 	struct ifnet *ifp = ifa->ifa_ifp;
  798: 
  799: 	if (rt == NULL)
  800: 		return;
  801: 	bzero(&info, sizeof(info));
  802: 	netmask = rt_mask(rt);
  803: 	dst = sa = rt_key(rt);
  804: 	gate = rt->rt_gateway;
  805: 	if ((m = rt_msg1(cmd, &info)) == NULL)
  806: 		return;
  807: 	rtm = mtod(m, struct rt_msghdr *);
  808: 	rtm->rtm_index = ifp->if_index;
  809: 	rtm->rtm_flags |= rt->rt_flags;
  810: 	rtm->rtm_errno = error;
  811: 	rtm->rtm_addrs = info.rti_addrs;
  812: 
  813: 	route_proto.sp_protocol = sa ? sa->sa_family : 0;
  814: 	raw_input(m, &route_proto, &route_src, &route_dst);
  815: }
  816: 
  817: /*
  818:  * This is called to generate messages from the routing socket
  819:  * indicating a network interface has had addresses associated with it.
  820:  * if we ever reverse the logic and replace messages TO the routing
  821:  * socket indicate a request to configure interfaces, then it will
  822:  * be unnecessary as the routing socket will automatically generate
  823:  * copies of it.
  824:  */
  825: void
  826: rt_newaddrmsg(cmd, ifa, error, rt)
  827: 	int cmd, error;
  828: 	struct ifaddr *ifa;
  829: 	struct rtentry *rt;
  830: {
  831: 	if (route_cb.any_count == 0)
  832: 		return;
  833: 
  834: 	if (cmd == RTM_ADD) {
  835: 		rt_ifamsg(RTM_NEWADDR, ifa);
  836: 		rt_rtmsg(RTM_ADD, ifa, error, rt);
  837: 	} else {
  838: 		KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
  839: 		rt_rtmsg(RTM_DELETE, ifa, error, rt);
  840: 		rt_ifamsg(RTM_DELADDR, ifa);
  841: 	}
  842: }
  843: 
  844: /*
  845:  * This is the analogue to the rt_newaddrmsg which performs the same
  846:  * function but for multicast group memberhips.  This is easier since
  847:  * there is no route state to worry about.
  848:  */
  849: void
  850: rt_newmaddrmsg(cmd, ifma)
  851: 	int cmd;
  852: 	struct ifmultiaddr *ifma;
  853: {
  854: 	struct rt_addrinfo info;
  855: 	struct mbuf *m = 0;
  856: 	struct ifnet *ifp = ifma->ifma_ifp;
  857: 	struct ifma_msghdr *ifmam;
  858: 
  859: 	if (route_cb.any_count == 0)
  860: 		return;
  861: 
  862: 	bzero((caddr_t)&info, sizeof(info));
  863: 	ifaaddr = ifma->ifma_addr;
  864: 	if (ifp && TAILQ_FIRST(&ifp->if_addrhead))
  865: 		ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
  866: 	else
  867: 		ifpaddr = NULL;
  868: 	/*
  869: 	 * If a link-layer address is present, present it as a ``gateway''
  870: 	 * (similarly to how ARP entries, e.g., are presented).
  871: 	 */
  872: 	gate = ifma->ifma_lladdr;
  873: 	if ((m = rt_msg1(cmd, &info)) == NULL)
  874: 		return;
  875: 	ifmam = mtod(m, struct ifma_msghdr *);
  876: 	ifmam->ifmam_index = ifp->if_index;
  877: 	ifmam->ifmam_addrs = info.rti_addrs;
  878: 	route_proto.sp_protocol = ifma->ifma_addr->sa_family;
  879: 	raw_input(m, &route_proto, &route_src, &route_dst);
  880: }
  881: 
  882: /*
  883:  * This is called to generate routing socket messages indicating
  884:  * network interface arrival and departure.
  885:  */
  886: void
  887: rt_ifannouncemsg(ifp, what)
  888: 	struct ifnet *ifp;
  889: 	int what;
  890: {
  891: 	struct if_announcemsghdr *ifan;
  892: 	struct mbuf *m;
  893: 	struct rt_addrinfo info;
  894: 
  895: 	if (route_cb.any_count == 0)
  896: 		return;
  897: 	bzero((caddr_t)&info, sizeof(info));
  898: 	m = rt_msg1(RTM_IFANNOUNCE, &info);
  899: 	if (m == NULL)
  900: 		return;
  901: 	ifan = mtod(m, struct if_announcemsghdr *);
  902: 	ifan->ifan_index = ifp->if_index;
  903: 	strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
  904: 	ifan->ifan_what = what;
  905: 	route_proto.sp_protocol = 0;
  906: 	raw_input(m, &route_proto, &route_src, &route_dst);
  907:  }
  908: 
  909: /*
  910:  * This is used in dumping the kernel table via sysctl().
  911:  */
  912: int
  913: sysctl_dumpentry(rn, vw)
  914: 	struct radix_node *rn;
  915: 	void *vw;
  916: {
  917: 	struct walkarg *w = vw;
  918: 	struct rtentry *rt = (struct rtentry *)rn;
  919: 	int error = 0, size;
  920: 	struct rt_addrinfo info;
  921: 
  922: 	if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  923: 		return 0;
  924: 	bzero((caddr_t)&info, sizeof(info));
  925: 	dst = rt_key(rt);
  926: 	gate = rt->rt_gateway;
  927: 	netmask = rt_mask(rt);
  928: 	genmask = rt->rt_genmask;
  929: 	if (rt->rt_ifp) {
  930: 		ifpaddr = TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
  931: 		ifaaddr = rt->rt_ifa->ifa_addr;
  932: 		if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
  933: 			brdaddr = rt->rt_ifa->ifa_dstaddr;
  934: 	}
  935: 	size = rt_msg2(RTM_GET, &info, 0, w);
  936: 	if (w->w_req && w->w_tmem) {
  937: 		struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
  938: 
  939: 		rtm->rtm_flags = rt->rt_flags;
  940: 		rtm->rtm_use = rt->rt_use;
  941: 		rtm->rtm_rmx = rt->rt_rmx;
  942: 		rtm->rtm_index = rt->rt_ifp->if_index;
  943: 		rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
  944: 		rtm->rtm_addrs = info.rti_addrs;
  945: 		error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
  946: 		return (error);
  947: 	}
  948: 	return (error);
  949: }
  950: 
  951: int
  952: sysctl_iflist(af, w)
  953: 	int	af;
  954: 	struct	walkarg *w;
  955: {
  956: 	struct ifnet *ifp;
  957: 	struct ifaddr *ifa;
  958: 	struct	rt_addrinfo info;
  959: 	int	len, error = 0;
  960: 
  961: 	bzero((caddr_t)&info, sizeof(info));
  962: 	TAILQ_FOREACH(ifp, &ifnet, if_link) {
  963: 		if (w->w_arg && w->w_arg != ifp->if_index)
  964: 			continue;
  965: 		ifa = TAILQ_FIRST(&ifp->if_addrhead);
  966: 		ifpaddr = ifa->ifa_addr;
  967: 		len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
  968: 		ifpaddr = 0;
  969: 		if (w->w_req && w->w_tmem) {
  970: 			struct if_msghdr *ifm;
  971: 
  972: 			ifm = (struct if_msghdr *)w->w_tmem;
  973: 			ifm->ifm_index = ifp->if_index;
  974: 			ifm->ifm_flags = (u_short)ifp->if_flags;
  975: 			ifm->ifm_data = ifp->if_data;
  976: 			ifm->ifm_addrs = info.rti_addrs;
  977: 			error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
  978: 			if (error)
  979: 				return (error);
  980: 		}
  981: 		while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) {
  982: 			if (af && af != ifa->ifa_addr->sa_family)
  983: 				continue;
  984: 			if (curproc->p_ucred->cr_prison && prison_if(curthread, ifa->ifa_addr))
  985: 				continue;
  986: 			ifaaddr = ifa->ifa_addr;
  987: 			netmask = ifa->ifa_netmask;
  988: 			brdaddr = ifa->ifa_dstaddr;
  989: 			len = rt_msg2(RTM_NEWADDR, &info, 0, w);
  990: 			if (w->w_req && w->w_tmem) {
  991: 				struct ifa_msghdr *ifam;
  992: 
  993: 				ifam = (struct ifa_msghdr *)w->w_tmem;
  994: 				ifam->ifam_index = ifa->ifa_ifp->if_index;
  995: 				ifam->ifam_flags = ifa->ifa_flags;
  996: 				ifam->ifam_metric = ifa->ifa_metric;
  997: 				ifam->ifam_addrs = info.rti_addrs;
  998: 				error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
  999: 				if (error)
 1000: 					return (error);
 1001: 			}
 1002: 		}
 1003: 		ifaaddr = netmask = brdaddr = 0;
 1004: 	}
 1005: 	return (0);
 1006: }
 1007: 
 1008: static int
 1009: sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 1010: {
 1011: 	int	*name = (int *)arg1;
 1012: 	u_int	namelen = arg2;
 1013: 	struct radix_node_head *rnh;
 1014: 	int	i, s, error = EINVAL;
 1015: 	u_char  af;
 1016: 	struct	walkarg w;
 1017: 
 1018: 	name ++;
 1019: 	namelen--;
 1020: 	if (req->newptr)
 1021: 		return (EPERM);
 1022: 	if (namelen != 3)
 1023: 		return (EINVAL);
 1024: 	af = name[0];
 1025: 	Bzero(&w, sizeof(w));
 1026: 	w.w_op = name[1];
 1027: 	w.w_arg = name[2];
 1028: 	w.w_req = req;
 1029: 
 1030: 	s = splnet();
 1031: 	switch (w.w_op) {
 1032: 
 1033: 	case NET_RT_DUMP:
 1034: 	case NET_RT_FLAGS:
 1035: 		for (i = 1; i <= AF_MAX; i++)
 1036: 			if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
 1037: 			    (error = rnh->rnh_walktree(rnh,
 1038: 							sysctl_dumpentry, &w)))
 1039: 				break;
 1040: 		break;
 1041: 
 1042: 	case NET_RT_IFLIST:
 1043: 		error = sysctl_iflist(af, &w);
 1044: 	}
 1045: 	splx(s);
 1046: 	if (w.w_tmem)
 1047: 		free(w.w_tmem, M_RTABLE);
 1048: 	return (error);
 1049: }
 1050: 
 1051: SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
 1052: 
 1053: /*
 1054:  * Definitions of protocols supported in the ROUTE domain.
 1055:  */
 1056: 
 1057: extern struct domain routedomain;		/* or at least forward */
 1058: 
 1059: static struct protosw routesw[] = {
 1060: { SOCK_RAW,	&routedomain,	0,		PR_ATOMIC|PR_ADDR,
 1061:   0,		route_output,	raw_ctlinput,	0,
 1062:   cpu0_soport,
 1063:   raw_init,	0,		0,		0,
 1064:   &route_usrreqs
 1065: }
 1066: };
 1067: 
 1068: static struct domain routedomain =
 1069:     { PF_ROUTE, "route", 0, 0, 0,
 1070:       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
 1071: 
 1072: DOMAIN_SET(route);