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

📄 in_pcb.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
字号:
/* $Id: in_pcb.c,v 1.2 1996/01/16 14:22:09 chris Exp $ *//* * Copyright (c) 1982, 1986, 1991 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	7.14 (Berkeley) 4/20/91 */#include "param.h"#include "systm.h"#include "malloc.h"#include "mbuf.h"#include "protosw.h"#include "socket.h"#include "socketvar.h"#include "ioctl.h"#include "../net/if.h"#include "../net/route.h"#include "in.h"#include "in_systm.h"#include "ip.h"#include "in_pcb.h"#include "in_var.h"struct	in_addr zeroin_addr;in_pcballoc(so, head)	struct socket *so;	struct inpcb *head;{	struct mbuf *m;	register struct inpcb *inp;	m = m_getclr(M_DONTWAIT, MT_PCB);	if (m == NULL)		return (ENOBUFS);	inp = mtod(m, struct inpcb *);	inp->inp_head = head;	inp->inp_socket = so;	insque(inp, head);	so->so_pcb = (caddr_t)inp;	return (0);}	in_pcbbind(inp, nam)	register struct inpcb *inp;	struct mbuf *nam;{	register struct socket *so = inp->inp_socket;	register struct inpcb *head = inp->inp_head;	register struct sockaddr_in *sin;	u_short lport = 0;	if (in_ifaddr == 0)		return (EADDRNOTAVAIL);	if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)		return (EINVAL);	if (nam == 0)		goto noname;	sin = mtod(nam, struct sockaddr_in *);	if (nam->m_len != sizeof (*sin))		return (EINVAL);	if (sin->sin_addr.s_addr != INADDR_ANY) {		int tport = sin->sin_port;		sin->sin_port = 0;		/* yech... */		if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)			return (EADDRNOTAVAIL);		sin->sin_port = tport;	}	lport = sin->sin_port;	if (lport) {		u_short aport = ntohs(lport);		int wild = 0;		/* GROSS */		if (aport < IPPORT_RESERVED && (so->so_state & SS_PRIV) == 0)			return (EACCES);		/* even GROSSER, but this is the Internet */		if ((so->so_options & SO_REUSEADDR) == 0 &&		    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||		     (so->so_options & SO_ACCEPTCONN) == 0))			wild = INPLOOKUP_WILDCARD;		if (in_pcblookup(head,		    zeroin_addr, 0, sin->sin_addr, lport, wild))			return (EADDRINUSE);	}	inp->inp_laddr = sin->sin_addr;noname:	if (lport == 0)		do {			if (head->inp_lport++ < IPPORT_RESERVED ||			    head->inp_lport > IPPORT_USERRESERVED)				head->inp_lport = IPPORT_RESERVED;			lport = htons(head->inp_lport);		} while (in_pcblookup(head,			    zeroin_addr, 0, inp->inp_laddr, lport, 0));	inp->inp_lport = lport;	return (0);}/* * Connect from a socket to a specified address. * Both address and port must be specified in argument sin. * If don't have a local address for this socket yet, * then pick one. */in_pcbconnect(inp, nam)	register struct inpcb *inp;	struct mbuf *nam;{	struct in_ifaddr *ia;	struct sockaddr_in *ifaddr;	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);	if (nam->m_len != sizeof (*sin))		return (EINVAL);	if (sin->sin_family != AF_INET)		return (EAFNOSUPPORT);	if (sin->sin_port == 0)		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))		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 &&		  (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))		    sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;	}	if (inp->inp_laddr.s_addr == INADDR_ANY) {		register struct route *ro;		struct ifnet *ifp;		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;			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 && (ifp = ro->ro_rt->rt_ifp) &&		    (ifp->if_flags & IFF_LOOPBACK) == 0)			for (ia = in_ifaddr; ia; ia = ia->ia_next)				if (ia->ia_ifp == ifp)					break;		if (ia == 0) {			int fport = sin->sin_port;			sin->sin_port = 0;			ia = (struct in_ifaddr *)			    ifa_ifwithdstaddr((struct sockaddr *)sin);			sin->sin_port = fport;			if (ia == 0)				ia = in_iaonnetof(in_netof(sin->sin_addr));			if (ia == 0)				ia = in_ifaddr;			if (ia == 0)				return (EADDRNOTAVAIL);		}		ifaddr = (struct sockaddr_in *)&ia->ia_addr;	}	if (in_pcblookup(inp->inp_head,	    sin->sin_addr,	    sin->sin_port,	    inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,	    inp->inp_lport,	    0))		return (EADDRINUSE);	if (inp->inp_laddr.s_addr == INADDR_ANY) {		if (inp->inp_lport == 0)			(void)in_pcbbind(inp, (struct mbuf *)0);		inp->inp_laddr = ifaddr->sin_addr;	}	inp->inp_faddr = sin->sin_addr;	inp->inp_fport = sin->sin_port;	return (0);}in_pcbdisconnect(inp)	struct inpcb *inp;{	inp->inp_faddr.s_addr = INADDR_ANY;	inp->inp_fport = 0;	if (inp->inp_socket->so_state & SS_NOFDREF)		in_pcbdetach(inp);}in_pcbdetach(inp)	struct inpcb *inp;{	struct socket *so = inp->inp_socket;	so->so_pcb = 0;	sofree(so);	if (inp->inp_options)		(void)m_free(inp->inp_options);	if (inp->inp_route.ro_rt)		rtfree(inp->inp_route.ro_rt);	remque(inp);	(void) m_free(dtom(inp));}in_setsockaddr(inp, nam)	register struct inpcb *inp;	struct mbuf *nam;{	register struct sockaddr_in *sin;		nam->m_len = sizeof (*sin);	sin = mtod(nam, struct sockaddr_in *);	bzero((caddr_t)sin, sizeof (*sin));	sin->sin_family = AF_INET;	sin->sin_len = sizeof(*sin);	sin->sin_port = inp->inp_lport;	sin->sin_addr = inp->inp_laddr;}in_setpeeraddr(inp, nam)	struct inpcb *inp;	struct mbuf *nam;{	register struct sockaddr_in *sin;		nam->m_len = sizeof (*sin);	sin = mtod(nam, struct sockaddr_in *);	bzero((caddr_t)sin, sizeof (*sin));	sin->sin_family = AF_INET;	sin->sin_len = sizeof(*sin);	sin->sin_port = inp->inp_fport;	sin->sin_addr = inp->inp_faddr;}/* * Pass some notification to all connections of a protocol * associated with address dst.  The local address and/or port numbers * may be specified to limit the search.  The "usual action" will be * taken, depending on the ctlinput cmd.  The caller must filter any * cmds that are uninteresting (e.g., no error in the map). * Call the protocol specific routine (if any) to report * any errors for each matching socket. * * Must be called at splnet. */in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify)	struct inpcb *head;	struct sockaddr *dst;	u_short fport, lport;	struct in_addr laddr;	int cmd, (*notify)();{	register struct inpcb *inp, *oinp;	struct in_addr faddr;	int errno;	int in_rtchange();	extern u_char inetctlerrmap[];	if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)		return;	faddr = ((struct sockaddr_in *)dst)->sin_addr;	if (faddr.s_addr == INADDR_ANY)		return;	/*	 * Redirects go to all references to the destination,	 * and use in_rtchange to invalidate the route cache.	 * Dead host indications: notify all references to the destination.	 * Otherwise, if we have knowledge of the local port and address,	 * deliver only to that socket.	 */	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {		fport = 0;		lport = 0;		laddr.s_addr = 0;		if (cmd != PRC_HOSTDEAD)			notify = in_rtchange;	}	errno = inetctlerrmap[cmd];	for (inp = head->inp_next; inp != head;) {		if (inp->inp_faddr.s_addr != faddr.s_addr ||		    inp->inp_socket == 0 ||		    (lport && inp->inp_lport != lport) ||		    (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||		    (fport && inp->inp_fport != fport)) {			inp = inp->inp_next;			continue;		}		oinp = inp;		inp = inp->inp_next;		if (notify)			(*notify)(oinp, errno);	}}/* * Check for alternatives when higher level complains * about service problems.  For now, invalidate cached * routing information.  If the route was created dynamically * (by a redirect), time to try a default gateway again. */in_losing(inp)	struct inpcb *inp;{	register struct rtentry *rt;	if ((rt = inp->inp_route.ro_rt)) {		rt_missmsg(RTM_LOSING, &inp->inp_route.ro_dst,			    rt->rt_gateway, (struct sockaddr *)rt_mask(rt),			    (struct sockaddr *)0, rt->rt_flags, 0);		if (rt->rt_flags & RTF_DYNAMIC)			(void) rtrequest(RTM_DELETE, rt_key(rt),				rt->rt_gateway, rt_mask(rt), rt->rt_flags, 				(struct rtentry **)0);		inp->inp_route.ro_rt = 0;		rtfree(rt);		/*		 * A new route can be allocated		 * the next time output is attempted.		 */	}}/* * After a routing change, flush old routing * and allocate a (hopefully) better one. */in_rtchange(inp)	register struct inpcb *inp;{	if (inp->inp_route.ro_rt) {		rtfree(inp->inp_route.ro_rt);		inp->inp_route.ro_rt = 0;		/*		 * A new route can be allocated the next time		 * output is attempted.		 */	}}struct inpcb *in_pcblookup(head, faddr, fport, laddr, lport, flags)	struct inpcb *head;	struct in_addr faddr, laddr;	u_short fport, lport;	int flags;{	register struct inpcb *inp, *match = 0;	int matchwild = 3, wildcard;	for (inp = head->inp_next; inp != head; inp = inp->inp_next) {		if (inp->inp_lport != lport)			continue;		wildcard = 0;		if (inp->inp_laddr.s_addr != INADDR_ANY) {			if (laddr.s_addr == INADDR_ANY)				wildcard++;			else if (inp->inp_laddr.s_addr != laddr.s_addr)				continue;		} else {			if (laddr.s_addr != INADDR_ANY)				wildcard++;		}		if (inp->inp_faddr.s_addr != INADDR_ANY) {			if (faddr.s_addr == INADDR_ANY)				wildcard++;			else if (inp->inp_faddr.s_addr != faddr.s_addr ||			    inp->inp_fport != fport)				continue;		} else {			if (faddr.s_addr != INADDR_ANY)				wildcard++;		}		if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)			continue;		if (wildcard < matchwild) {			match = inp;			matchwild = wildcard;			if (matchwild == 0)				break;		}	}	return (match);}

⌨️ 快捷键说明

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