⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsock.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)rtsock.c	8.5 (Berkeley) 11/2/94 *	$Id: rtsock.c,v 1.5 2003/01/03 18:09:25 joel Exp $ */#include <sys/param.h>#include <sys/queue.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/sysctl.h>#include <sys/proc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/domain.h>#include <sys/protosw.h>#include <net/if.h>#include <net/route.h>#include <net/raw_cb.h>static struct	sockaddr route_dst = { 2, PF_ROUTE, };static struct	sockaddr route_src = { 2, PF_ROUTE, };static struct	sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };static struct	sockproto route_proto = { PF_ROUTE, };struct walkarg {	int	w_tmemsize;	int	w_op, w_arg;	caddr_t	w_tmem;	struct sysctl_req *w_req;};static struct mbuf *		rt_msg1 __P((int, struct rt_addrinfo *));static int	rt_msg2 __P((int,		    struct rt_addrinfo *, caddr_t, struct walkarg *));static int	rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));static int	sysctl_dumpentry __P((struct radix_node *rn, void *vw));static int	sysctl_iflist __P((int af, struct walkarg *w));static int	 route_output __P((struct mbuf *, struct socket *));static int	 route_usrreq __P((struct socket *,	    int, struct mbuf *, struct mbuf *, struct mbuf *));static void	 rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));/* Sleazy use of local variables throughout file, warning!!!! */#define dst	info.rti_info[RTAX_DST]#define gate	info.rti_info[RTAX_GATEWAY]#define netmask	info.rti_info[RTAX_NETMASK]#define genmask	info.rti_info[RTAX_GENMASK]#define ifpaddr	info.rti_info[RTAX_IFP]#define ifaaddr	info.rti_info[RTAX_IFA]#define brdaddr	info.rti_info[RTAX_BRD]/*ARGSUSED*/static introute_usrreq(so, req, m, nam, control)	register struct socket *so;	int req;	struct mbuf *m, *nam, *control;{	register int error = 0;	register struct rawcb *rp = sotorawcb(so);	int s;	if (req == PRU_ATTACH) {		MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);		so->so_pcb = (caddr_t)rp;		if (so->so_pcb)			bzero(so->so_pcb, sizeof(*rp));	}	if (req == PRU_DETACH && rp) {		int af = rp->rcb_proto.sp_protocol;		if (af == AF_INET)			route_cb.ip_count--;		else if (af == AF_IPX)			route_cb.ipx_count--;		else if (af == AF_NS)			route_cb.ns_count--;		else if (af == AF_ISO)			route_cb.iso_count--;		route_cb.any_count--;	}	s = splnet();	error = raw_usrreq(so, req, m, nam, control);	rp = sotorawcb(so);	if (req == PRU_ATTACH && rp) {		int af = rp->rcb_proto.sp_protocol;		if (error) {			free((caddr_t)rp, M_PCB);			splx(s);			return (error);		}		if (af == AF_INET)			route_cb.ip_count++;		else if (af == AF_IPX)			route_cb.ipx_count++;		else if (af == AF_NS)			route_cb.ns_count++;		else if (af == AF_ISO)			route_cb.iso_count++;		rp->rcb_faddr = &route_src;		route_cb.any_count++;		soisconnected(so);		so->so_options |= SO_USELOOPBACK;	}	splx(s);	return (error);}/*ARGSUSED*/static introute_output(m, so)	register struct mbuf *m;	struct socket *so;{	register struct rt_msghdr *rtm = 0;	register struct rtentry *rt = 0;	struct rtentry *saved_nrt = 0;	struct radix_node_head *rnh;	struct rt_addrinfo info;	int len, error = 0;	struct ifnet *ifp = 0;	struct ifaddr *ifa = 0;#define senderr(e) { error = e; goto flush;}	if (m == 0 || ((m->m_len < sizeof(long)) &&		       (m = m_pullup(m, sizeof(long))) == 0))		return (ENOBUFS);	if ((m->m_flags & M_PKTHDR) == 0)		panic("route_output");	len = m->m_pkthdr.len;	if (len < sizeof(*rtm) ||	    len != mtod(m, struct rt_msghdr *)->rtm_msglen) {		dst = 0;		senderr(EINVAL);	}	R_Malloc(rtm, struct rt_msghdr *, len);	if (rtm == 0) {		dst = 0;		senderr(ENOBUFS);	}	m_copydata(m, 0, len, (caddr_t)rtm);	if (rtm->rtm_version != RTM_VERSION) {		dst = 0;		senderr(EPROTONOSUPPORT);	}	info.rti_addrs = rtm->rtm_addrs;	if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {		dst = 0;		senderr(EINVAL);	}	if (dst == 0 || (dst->sa_family >= AF_MAX)	    || (gate != 0 && (gate->sa_family >= AF_MAX)))		senderr(EINVAL);	if (genmask) {		struct radix_node *t;		t = rn_addmask((caddr_t)genmask, 0, 1);		if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)			genmask = (struct sockaddr *)(t->rn_key);		else			senderr(ENOBUFS);	}	switch (rtm->rtm_type) {	case RTM_ADD:		if (gate == 0)			senderr(EINVAL);		error = rtrequest(RTM_ADD, dst, gate, netmask,					rtm->rtm_flags, &saved_nrt);		if (error == 0 && saved_nrt) {			rt_setmetrics(rtm->rtm_inits,				&rtm->rtm_rmx, &saved_nrt->rt_rmx);			saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);			saved_nrt->rt_rmx.rmx_locks |=				(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);			saved_nrt->rt_refcnt--;			saved_nrt->rt_genmask = genmask;		}		break;	case RTM_DELETE:		error = rtrequest(RTM_DELETE, dst, gate, netmask,				rtm->rtm_flags, &saved_nrt);		if (error == 0) {			if ((rt = saved_nrt))				rt->rt_refcnt++;			goto report;		}		break;	case RTM_GET:	case RTM_CHANGE:	case RTM_LOCK:		if ((rnh = rt_tables[dst->sa_family]) == 0) {			senderr(EAFNOSUPPORT);		} else if ((rt = (struct rtentry *)				rnh->rnh_lookup(dst, netmask, rnh)))			rt->rt_refcnt++;		else			senderr(ESRCH);		switch(rtm->rtm_type) {		case RTM_GET:		report:			dst = rt_key(rt);			gate = rt->rt_gateway;			netmask = rt_mask(rt);			genmask = rt->rt_genmask;			if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {				ifp = rt->rt_ifp;				if (ifp) {					ifpaddr = ifp->if_addrlist->ifa_addr;					ifaaddr = rt->rt_ifa->ifa_addr;					rtm->rtm_index = ifp->if_index;				} else {					ifpaddr = 0;					ifaaddr = 0;			    }			}			len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,				(struct walkarg *)0);			if (len > rtm->rtm_msglen) {				struct rt_msghdr *new_rtm;				R_Malloc(new_rtm, struct rt_msghdr *, len);				if (new_rtm == 0)					senderr(ENOBUFS);				Bcopy(rtm, new_rtm, rtm->rtm_msglen);				Free(rtm); rtm = new_rtm;			}			(void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,				(struct walkarg *)0);			rtm->rtm_flags = rt->rt_flags;			rtm->rtm_rmx = rt->rt_rmx;			rtm->rtm_addrs = info.rti_addrs;			break;		case RTM_CHANGE:			if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))				senderr(error);			/*			 * If they tried to change things but didn't specify			 * the required gateway, then just use the old one.			 * This can happen if the user tries to change the			 * flags on the default route without changing the			 * default gateway.  Changing flags still doesn't work.			 */			if ((rt->rt_flags & RTF_GATEWAY) && !gate)				gate = rt->rt_gateway;			/* new gateway could require new ifaddr, ifp;			   flags may also be different; ifp may be specified			   by ll sockaddr when protocol address is ambiguous */			if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&			    (ifp = ifa->ifa_ifp) && (ifaaddr || gate))				ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,							ifp);			else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||				 (gate && (ifa = ifa_ifwithroute(rt->rt_flags,							rt_key(rt), gate))))				ifp = ifa->ifa_ifp;			if (ifa) {				register struct ifaddr *oifa = rt->rt_ifa;				if (oifa != ifa) {				    if (oifa && oifa->ifa_rtrequest)					oifa->ifa_rtrequest(RTM_DELETE,								rt, gate);				    IFAFREE(rt->rt_ifa);				    rt->rt_ifa = ifa;				    ifa->ifa_refcnt++;				    rt->rt_ifp = ifp;				}			}			rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,					&rt->rt_rmx);			if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)			       rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);			if (genmask)				rt->rt_genmask = genmask;			/*			 * Fall into			 */		case RTM_LOCK:			rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);			rt->rt_rmx.rmx_locks |=				(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);			break;		}		break;	default:		senderr(EOPNOTSUPP);	}flush:	if (rtm) {		if (error)			rtm->rtm_errno = error;		else			rtm->rtm_flags |= RTF_DONE;	}	if (rt)		rtfree(rt);    {	register struct rawcb *rp = 0;	/*	 * Check to see if we don't want our own messages.	 */	if ((so->so_options & SO_USELOOPBACK) == 0) {		if (route_cb.any_count <= 1) {			if (rtm)				Free(rtm);			m_freem(m);			return (error);		}		/* There is another listener, so construct message */		rp = sotorawcb(so);	}	if (rtm) {		m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);		Free(rtm);	}	if (rp)		rp->rcb_proto.sp_family = 0; /* Avoid us */	if (dst)		route_proto.sp_protocol = dst->sa_family;	raw_input(m, &route_proto, &route_src, &route_dst);	if (rp)		rp->rcb_proto.sp_family = PF_ROUTE;    }	return (error);}static voidrt_setmetrics(which, in, out)	u_long which;	register struct rt_metrics *in, *out;{#define metric(f, e) if (which & (f)) out->e = in->e;	metric(RTV_RPIPE, rmx_recvpipe);	metric(RTV_SPIPE, rmx_sendpipe);	metric(RTV_SSTHRESH, rmx_ssthresh);	metric(RTV_RTT, rmx_rtt);	metric(RTV_RTTVAR, rmx_rttvar);	metric(RTV_HOPCOUNT, rmx_hopcount);	metric(RTV_MTU, rmx_mtu);	metric(RTV_EXPIRE, rmx_expire);#undef metric}#define ROUNDUP(a) \	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))/* * Extract the addresses of the passed sockaddrs. * Do a little sanity checking so as to avoid bad memory references. * This data is derived straight from userland. */static intrt_xaddrs(cp, cplim, rtinfo)	register caddr_t cp, cplim;	register struct rt_addrinfo *rtinfo;{	register struct sockaddr *sa;	register int i;	bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {		if ((rtinfo->rti_addrs & (1 << i)) == 0)			continue;		sa = (struct sockaddr *)cp;		/*		 * It won't fit.		 */		if ( (cp + sa->sa_len) > cplim ) {			return (EINVAL);		}		/*		 * there are no more.. quit now		 * If there are more bits, they are in error.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -