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

📄 in_pcb.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
			}		}	/*	 * Don't do pcblookup call here; return interface in plocal_sin	 * and exit to caller, that will do the lookup.	 */		*plocal_sin = &ia->ia_addr;	}	return(0);}/* * Outer subroutine: * 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. */intin_pcbconnect(inp, nam)	register struct inpcb *inp;	struct mbuf *nam;{	struct sockaddr_in *ifaddr;	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);	int error;	/*	 *   Call inner routine, to assign local interface address.	 */	if ((error = in_pcbladdr(inp, nam, &ifaddr)))		return(error);	if (in_pcblookuphash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,	    inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,	    inp->inp_lport, 0) != NULL)		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;	in_pcbrehash(inp);	return (0);}voidin_pcbdisconnect(inp)	struct inpcb *inp;{	inp->inp_faddr.s_addr = INADDR_ANY;	inp->inp_fport = 0;	in_pcbrehash(inp);	if (inp->inp_socket->so_state & SS_NOFDREF)		in_pcbdetach(inp);}voidin_pcbdetach(inp)	struct inpcb *inp;{	struct socket *so = inp->inp_socket;	struct inpcbinfo *ipi = inp->inp_pcbinfo;	int s;	inp->inp_gencnt = ++ipi->ipi_gencnt;	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);	ip_freemoptions(inp->inp_moptions);	s = splnet();	LIST_REMOVE(inp, inp_hash);	LIST_REMOVE(inp, inp_list);	splx(s);	FREE(inp, M_PCB);}voidin_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;}voidin_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. */voidin_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)	struct inpcbhead *head;	struct sockaddr *dst;	u_int fport_arg, lport_arg;	struct in_addr laddr;	int cmd;	void (*notify) __P((struct inpcb *, int));{	register struct inpcb *inp, *oinp;	struct in_addr faddr;	u_short fport = fport_arg, lport = lport_arg;	int errnum, s;	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;	}	errnum = inetctlerrmap[cmd];	s = splnet();	for (inp = head->lh_first; inp != NULL;) {		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_list.le_next;			continue;		}		oinp = inp;		inp = inp->inp_list.le_next;		if (notify)			(*notify)(oinp, errnum);	}	splx(s);}/* * 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. */voidin_losing(inp)	struct inpcb *inp;{	register struct rtentry *rt;	struct rt_addrinfo info;	if ((rt = inp->inp_route.ro_rt)) {		inp->inp_route.ro_rt = 0;		bzero((caddr_t)&info, sizeof(info));		info.rti_info[RTAX_DST] =			(struct sockaddr *)&inp->inp_route.ro_dst;		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;		info.rti_info[RTAX_NETMASK] = rt_mask(rt);		rt_missmsg(RTM_LOSING, &info, 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);		else		/*		 * A new route can be allocated		 * the next time output is attempted.		 */			rtfree(rt);	}}/* * After a routing change, flush old routing * and allocate a (hopefully) better one. */static voidin_rtchange(inp, errnum)	register struct inpcb *inp;	int errnum;{	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(pcbinfo, faddr, fport_arg, laddr, lport_arg, wild_okay)	struct inpcbinfo *pcbinfo;	struct in_addr faddr, laddr;	u_int fport_arg, lport_arg;	int wild_okay;{	register struct inpcb *inp, *match = NULL;	int matchwild = 3, wildcard;	u_short fport = fport_arg, lport = lport_arg;	int s;	s = splnet();	for (inp = pcbinfo->listhead->lh_first; inp != NULL; inp = inp->inp_list.le_next) {		if (inp->inp_lport != lport)			continue;		wildcard = 0;		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 (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 (wildcard && wild_okay == 0)			continue;		if (wildcard < matchwild) {			match = inp;			matchwild = wildcard;			if (matchwild == 0) {				break;			}		}	}	splx(s);	return (match);}/* * Lookup PCB in hash list. */struct inpcb *in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)	struct inpcbinfo *pcbinfo;	struct in_addr faddr, laddr;	u_int fport_arg, lport_arg;	int wildcard;{	struct inpcbhead *head;	register struct inpcb *inp;	u_short fport = fport_arg, lport = lport_arg;	int s;	s = splnet();	/*	 * First look for an exact match.	 */	head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {		if (inp->inp_faddr.s_addr == faddr.s_addr &&		    inp->inp_laddr.s_addr == laddr.s_addr &&		    inp->inp_fport == fport &&		    inp->inp_lport == lport)			goto found;	}	if (wildcard) {		struct inpcb *local_wild = NULL;		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];		for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {			if (inp->inp_faddr.s_addr == INADDR_ANY &&			    inp->inp_fport == 0 && inp->inp_lport == lport) {				if (inp->inp_laddr.s_addr == laddr.s_addr)					goto found;				else if (inp->inp_laddr.s_addr == INADDR_ANY)					local_wild = inp;			}		}		if (local_wild != NULL) {			inp = local_wild;			goto found;		}	}	splx(s);	return (NULL);found:	/*	 * Move PCB to head of this hash chain so that it can be	 * found more quickly in the future.	 * XXX - this is a pessimization on machines with few	 * concurrent connections.	 */	if (inp != head->lh_first) {		LIST_REMOVE(inp, inp_hash);		LIST_INSERT_HEAD(head, inp, inp_hash);	}	splx(s);	return (inp);}/* * Insert PCB into hash chain. Must be called at splnet. */static voidin_pcbinshash(inp)	struct inpcb *inp;{	struct inpcbhead *head;	head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,		 inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];	LIST_INSERT_HEAD(head, inp, inp_hash);}voidin_pcbrehash(inp)	struct inpcb *inp;{	struct inpcbhead *head;	int s;	s = splnet();	LIST_REMOVE(inp, inp_hash);	head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,		inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];	LIST_INSERT_HEAD(head, inp, inp_hash);	inp->inp_pcbinfo->ipi_count--;	splx(s);}

⌨️ 快捷键说明

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