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

📄 in_pcb.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* in_pcb.c - internet protocol control block routines *//* Copyright 1984 - 2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1986, 1991, 1993, 1995 *	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. * *	@(#)in_pcb.c	8.4 (Berkeley) 5/24/95 *//*modification history--------------------01g,12oct01,rae  merge from truestack ver 01k, base 01f (SPR #69867 etc.)01f,05oct97,vin  changed ip_freemoptions for new multicasting changes.01e,01jul97,vin  added rtMissMsgHook for scalability of routing sockets.01d,31mar97,vin  integrated with FREEBSD 2.2.1 for hashlookups of pcbs01c,05feb97,rjc  changed for tos routing.01b,05dec96,vin  replaced malloc with MALLOC and free with FREE(),01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02k of in_pcb.c*//*DESCRIPTION*/#include "vxWorks.h"#include "net/systm.h"#include "errno.h"#include "net/mbuf.h"#include "sys/socket.h"#include "net/socketvar.h"#include "sys/ioctl.h"#include "net/if.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "net/route.h"#include "netinet/in_pcb.h"#include "netinet/in_var.h"#include "netinet/ip_var.h"#include "net/protosw.h"#include "routeEnhLib.h"#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endif /* VIRTUAL_STACK */#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif#endifstruct	in_addr   zeroin_addr;#ifdef VIRTUAL_STACK#define IN_IFADDR _in_ifaddr#else#define IN_IFADDR in_ifaddr#endif#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_INPCB_MODULE;   /* Value for in_pcb.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */#endif    /* INCLUDE_WVNET */#endifintin_pcballoc(so, pcbinfo)	struct socket *so;	struct inpcbinfo *pcbinfo;{	register struct inpcb *inp;	int s;	MALLOC(inp, struct inpcb *, sizeof(*inp), MT_PCB, M_DONTWAIT);	if (inp == NULL)            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */            WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 13, 1,                              WV_NETEVENT_PCBALLOC_NOBUFS, so->so_fd)#endif  /* INCLUDE_WVNET */#endif            return (ENOBUFS);            }	bzero((caddr_t)inp, sizeof(*inp));	inp->inp_pcbinfo = pcbinfo;	inp->inp_socket = so;	s = splnet();	LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);	in_pcbinshash(inp);	splx(s);	so->so_pcb = (caddr_t)inp;	return (0);}intin_pcbbind(inp, nam)	register struct inpcb *inp;	struct mbuf *nam;{	register struct socket *so = inp->inp_socket;	unsigned short *lastport = &inp->inp_pcbinfo->lastport;	struct sockaddr_in *sin;	u_short lport = 0;	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */    WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 23, 11,                      WV_NETEVENT_PCBBIND_START, so->so_fd)#endif  /* INCLUDE_WVNET */#endif#ifdef VIRTUAL_STACK	if (_in_ifaddr == 0)#else	if (in_ifaddr == 0)#endif /* VIRTUAL_STACK */            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 10, 2,                             WV_NETEVENT_PCBBIND_NOADDR, so->so_fd)#endif  /* INCLUDE_WVNET */#endif            return (EADDRNOTAVAIL);            }	if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_ERROR, 11, 3,                             WV_NETEVENT_PCBBIND_BADSOCK, so->so_fd,                             inp->inp_laddr.s_addr, inp->inp_lport)#endif  /* INCLUDE_WVNET */#endif            return (EINVAL);            }	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&	    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||	     (so->so_options & SO_ACCEPTCONN) == 0))		wild = INPLOOKUP_WILDCARD;	if (nam) {		sin = mtod(nam, struct sockaddr_in *);		if (nam->m_len != sizeof (*sin))                    {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 12, 4,                              WV_NETEVENT_PCBBIND_BADADDRLEN,                             so->so_fd, nam->m_len)#endif  /* INCLUDE_WVNET */#endif                    return (EINVAL);                    }#ifdef notdef		/*		 * We should check the family, but old programs		 * incorrectly fail to initialize it.		 */		if (sin->sin_family != AF_INET)			return (EAFNOSUPPORT);#endif		lport = sin->sin_port;		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {			/*			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;			 * allow complete duplication of binding if			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set			 * and a multicast address is bound on both			 * new and duplicated sockets.			 */			if (so->so_options & SO_REUSEADDR)				reuseport = SO_REUSEADDR|SO_REUSEPORT;		} else if (sin->sin_addr.s_addr != INADDR_ANY) {			sin->sin_port = 0;		/* yech... */			if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)                            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 13, 5,                              WV_NETEVENT_PCBBIND_BADADDR,                             so->so_fd, sin->sin_addr.s_addr)#endif  /* INCLUDE_WVNET */#endif                            return (EADDRNOTAVAIL);                            }		}		if (lport) {			struct inpcb *t;			/* GROSS */#if 0 /* XXX took out because we are always in super user mode. */			if (ntohs(lport) < IPPORT_RESERVED &&			    (error = suser(p->p_ucred, &p->p_acflag)))				return (EACCES);#endif			t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0,			    sin->sin_addr, lport, wild);			if (t && (reuseport & t->inp_socket->so_options) == 0)                            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 14, 6,                              WV_NETEVENT_PCBBIND_BADPORT, so->so_fd, lport)#endif  /* INCLUDE_WVNET */#endif                            return (EADDRINUSE);                            }		}		inp->inp_laddr = sin->sin_addr;	}	if (lport == 0)		do {			++*lastport;			if (*lastport < IPPORT_RESERVED ||			    *lastport > IPPORT_USERRESERVED)				*lastport = IPPORT_RESERVED;			lport = htons(*lastport);		} while (in_pcblookup(inp->inp_pcbinfo,			    zeroin_addr, 0, inp->inp_laddr, lport, wild));	inp->inp_lport = lport;	in_pcbrehash(inp);	return (0);}/* *   Transform old in_pcbconnect() into an inner subroutine for new *   in_pcbconnect(): Do some validity-checking on the remote *   address (in mbuf 'nam') and then determine local host address *   (i.e., which interface) to use to access that remote host. * *   This preserves definition of in_pcbconnect(), while supporting a *   slightly different version for T/TCP.  (This is more than *   a bit of a kludge, but cleaning up the internal interfaces would *   have forced minor changes in every protocol). */intin_pcbladdr(inp, nam, plocal_sin)	register struct inpcb *inp;	struct mbuf *nam;	struct sockaddr_in **plocal_sin;{	struct in_ifaddr *ia;	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);	if (nam->m_len != sizeof (*sin))            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_ERROR, 15, 7,                              WV_NETEVENT_PCBLADDR_BADADDR,                              inp->inp_socket->so_fd, nam->m_len,                              sin->sin_family, sin->sin_port)#endif  /* INCLUDE_WVNET */#endif            return (EINVAL);            }	if (sin->sin_family != AF_INET)            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_ERROR, 15, 7,                              WV_NETEVENT_PCBLADDR_BADADDR,                              inp->inp_socket->so_fd, nam->m_len,                              sin->sin_family, sin->sin_port)#endif  /* INCLUDE_WVNET */#endif            return (EAFNOSUPPORT);            }	if (sin->sin_port == 0)            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_ERROR, 15, 7,                              WV_NETEVENT_PCBLADDR_BADADDR,                              inp->inp_socket->so_fd, nam->m_len,                              sin->sin_family, sin->sin_port)#endif  /* INCLUDE_WVNET */#endif            return (EADDRNOTAVAIL);            }	if (IN_IFADDR)        {		/*		 * If the destination address is INADDR_ANY,		 * use the primary local address.		 * If the supplied address is INADDR_BROADCAST,		 * and the primary interface supports broadcast,		 * choose the broadcast address for that interface.		 */#define	satosin(sa)	((struct sockaddr_in *)(sa))#define sintosa(sin)	((struct sockaddr *)(sin))#define ifatoia(ifa)	((struct in_ifaddr *)(ifa))		if (sin->sin_addr.s_addr == INADDR_ANY)		    sin->sin_addr = IA_SIN(IN_IFADDR)->sin_addr;		else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST)		    {                    for (ia = IN_IFADDR; ia; ia = ia->ia_next) 			 {			 if (ia->ia_ifp->if_flags & IFF_BROADCAST)			     {		             sin->sin_addr = 			         satosin(&IN_IFADDR->ia_next->ia_broadaddr)->sin_addr;                             break;			     }                         }                    }	}	if (inp->inp_laddr.s_addr == INADDR_ANY) {		register struct route *ro;		ia = (struct in_ifaddr *)0;		/*		 * If route is known or can be allocated now,		 * our src addr is taken from the i/f, else punt.		 */		ro = &inp->inp_route;		if (ro->ro_rt &&		    (satosin(&ro->ro_dst)->sin_addr.s_addr !=			sin->sin_addr.s_addr ||		    inp->inp_socket->so_options & SO_DONTROUTE)) {			RTFREE(ro->ro_rt);			ro->ro_rt = (struct rtentry *)0;		}		if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/		    (ro->ro_rt == (struct rtentry *)0 ||		    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {			/* No route yet, so try to acquire one */			ro->ro_dst.sa_family = AF_INET;			ro->ro_dst.sa_len = sizeof(struct sockaddr_in);			((struct sockaddr_in *) &ro->ro_dst)->sin_addr =				sin->sin_addr;                        TOS_SET ((struct sockaddr_in *) &ro->ro_dst, inp->inp_ip.ip_tos);			rtalloc(ro);		}		/*		 * If we found a route, use the address		 * corresponding to the outgoing interface		 * unless it is the loopback (in case a route		 * to our address on another net goes to loopback).		 */		if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))			ia = ifatoia(ro->ro_rt->rt_ifa);		if (ia == 0) {			u_short fport = sin->sin_port;			sin->sin_port = 0;			ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));			if (ia == 0)				ia = ifatoia(ifa_ifwithnet(sintosa(sin)));			sin->sin_port = fport;			if (ia == 0)				ia = IN_IFADDR;			if (ia == 0)                            {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */            WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_ERROR, 15, 7,                              WV_NETEVENT_PCBLADDR_BADADDR,                              inp->inp_socket->so_fd, nam->m_len,                              sin->sin_family, sin->sin_port)#endif  /* INCLUDE_WVNET */#endif                            return (EADDRNOTAVAIL);                            }		}		/*		 * If the destination address is multicast and an outgoing		 * interface has been set as a multicast option, use the		 * address of that interface as our source address.		 */		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&		    inp->inp_moptions != NULL) {			struct ip_moptions *imo;			struct ifnet *ifp;			imo = inp->inp_moptions;			if (imo->imo_multicast_ifp != NULL) {				ifp = imo->imo_multicast_ifp;				for (ia = IN_IFADDR; ia; ia = ia->ia_next)					if (ia->ia_ifp == ifp)						break;

⌨️ 快捷键说明

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