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

📄 in_pcb.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
					if (ia->ia_ifp == ifp)						break;				if (ia == 0)					return (EADDRNOTAVAIL);			}		}		ifaddr = satosin(&ia->ia_addr);	}	if (in_pcbhashlookup(inp->inp_table, 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 &&		    in_pcbbind(inp, (struct mbuf *)0) == EADDRNOTAVAIL)			return (EADDRNOTAVAIL);		inp->inp_laddr = ifaddr->sin_addr;	}	inp->inp_faddr = sin->sin_addr;	inp->inp_fport = sin->sin_port;	in_pcbrehash(inp);#ifdef IPSEC	return (check_ipsec_policy(inp, 0));#else	return (0);#endif}voidin_pcbdisconnect(v)	void *v;{	struct inpcb *inp = v;#ifdef INET6	if (sotopf(inp->inp_socket) == PF_INET6) {		inp->inp_faddr6 = in6addr_any;		/* Disconnected AF_INET6 sockets cannot be "v4-mapped" */		inp->inp_flags &= ~INP_IPV6_MAPPED;	} else#endif		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(v)	void *v;{	struct inpcb *inp = v;	struct socket *so = inp->inp_socket;	int s;	so->so_pcb = 0;	sofree(so);	if (inp->inp_options)		(void)m_freem(inp->inp_options);	if (inp->inp_route.ro_rt)		rtfree(inp->inp_route.ro_rt);#ifdef NOTUSED_BY_PMON#ifdef INET6	if (inp->inp_flags & INP_IPV6_MCAST)		ipv6_freemoptions(inp->inp_moptions6);	else #endif /* INET6 */		ip_freemoptions(inp->inp_moptions);#endif /* NOTUSED_BY_PMON */#ifdef IPSEC	/* XXX IPsec cleanup here */	s = spltdb();	if (inp->inp_tdb)		TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next);	splx(s);#endif	s = splnet();	LIST_REMOVE(inp, inp_hash);	CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue);	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;	#ifdef INET6	if (sotopf(inp->inp_socket) == PF_INET6)		in6_setpeeraddr(inp, nam);#endif /* INET6 */	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 splsoftnet. */voidin_pcbnotify(table, dst, fport_arg, laddr, lport_arg, errno, notify)	struct inpcbtable *table;	struct sockaddr *dst;	u_int fport_arg, lport_arg;	struct in_addr laddr;	int errno;	void (*notify) __P((struct inpcb *, int));{	register struct inpcb *inp, *oinp;	struct in_addr faddr;	u_int16_t fport = fport_arg, lport = lport_arg;#ifdef INET6	/*	 * See in6_pcbnotify() for IPv6 codepath.  By the time this	 * gets called, the addresses passed are either definitely IPv4 or	 * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses.	 */#endif /* INET6 */	if (dst->sa_family != AF_INET)		return;	faddr = satosin(dst)->sin_addr;	if (faddr.s_addr == INADDR_ANY)		return;	for (inp = table->inpt_queue.cqh_first;	    inp != (struct inpcb *)&table->inpt_queue;) {		if (inp->inp_faddr.s_addr != faddr.s_addr ||		    inp->inp_socket == 0 ||		    inp->inp_fport != fport ||		    inp->inp_lport != lport ||		    inp->inp_laddr.s_addr != laddr.s_addr) {			inp = inp->inp_queue.cqe_next;			continue;		}		oinp = inp;		inp = inp->inp_queue.cqe_next;		if (notify)			(*notify)(oinp, errno);	}}voidin_pcbnotifyall(table, dst, errno, notify)	struct inpcbtable *table;	struct sockaddr *dst;	int errno;	void (*notify) __P((struct inpcb *, int));{	register struct inpcb *inp, *oinp;	struct in_addr faddr;#ifdef INET6	/*	 * See in6_pcbnotify() for IPv6 codepath.  By the time this	 * gets called, the addresses passed are either definitely IPv4 or	 * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses.	 */#endif /* INET6 */	if (dst->sa_family != AF_INET)		return;	faddr = satosin(dst)->sin_addr;	if (faddr.s_addr == INADDR_ANY)		return;	for (inp = table->inpt_queue.cqh_first;	    inp != (struct inpcb *)&table->inpt_queue;) {		if (inp->inp_faddr.s_addr != faddr.s_addr ||		    inp->inp_socket == 0) {			inp = inp->inp_queue.cqe_next;			continue;		}		oinp = inp;		inp = inp->inp_queue.cqe_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. */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] = &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. */voidin_rtchange(inp, errno)	register struct inpcb *inp;	int errno;{	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(table, faddrp, fport_arg, laddrp, lport_arg, flags)	struct inpcbtable *table;	void *faddrp, *laddrp;	u_int fport_arg, lport_arg;	int flags;{	register struct inpcb *inp, *match = 0;	int matchwild = 3, wildcard;	u_int16_t fport = fport_arg, lport = lport_arg;	struct in_addr faddr = *(struct in_addr *)faddrp;	struct in_addr laddr = *(struct in_addr *)laddrp;	for (inp = table->inpt_queue.cqh_first;	    inp != (struct inpcb *)&table->inpt_queue;	    inp = inp->inp_queue.cqe_next) {		if (inp->inp_lport != lport)			continue;		wildcard = 0;#ifdef INET6		if (flags & INPLOOKUP_IPV6) {			struct in6_addr *laddr6 = (struct in6_addr *)laddrp;			struct in6_addr *faddr6 = (struct in6_addr *)faddrp;			/* 			 * Always skip AF_INET sockets when looking for AF_INET6			 * addresses.  The only problem with this comes if the			 * PF_INET6 addresses are v4-mapped addresses.  From what			 * I've been able to see, none of the callers cause such			 * a situation to occur.  If such a situation DID occur,			 * then it is possible to miss a matching PCB.			 */			if (!(inp->inp_flags & INP_IPV6))				continue;			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {				if (IN6_IS_ADDR_UNSPECIFIED(laddr6))					wildcard++;				else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6))					continue;			} else {				if (!IN6_IS_ADDR_UNSPECIFIED(laddr6))					wildcard++;			}			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {				if (IN6_IS_ADDR_UNSPECIFIED(faddr6))					wildcard++;				else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,				    faddr6) || inp->inp_fport != fport)					continue;			} else {				if (!IN6_IS_ADDR_UNSPECIFIED(faddr6))					wildcard++;			}		} else {#endif /* INET6 */			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++;			}#ifdef INET6		}#endif /* INET6 */		if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) &&		    wildcard < matchwild) {			match = inp;			if ((matchwild = wildcard) == 0)				break;		}	}	return (match);}voidin_pcbrehash(inp)	struct inpcb *inp;{	struct inpcbtable *table = inp->inp_table;	int s;	s = splnet();	LIST_REMOVE(inp, inp_hash);#ifdef INET6	if (inp->inp_flags & INP_IPV6) {		LIST_INSERT_HEAD(IN6PCBHASH(table, &inp->inp_faddr6,		    inp->inp_fport, &inp->inp_laddr6, inp->inp_lport),		    inp, inp_hash);	} else {#endif /* INET6 */		LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr,		    inp->inp_fport, &inp->inp_laddr, inp->inp_lport),		    inp, inp_hash);#ifdef INET6	}#endif /* INET6 */	splx(s);}#ifdef DIAGNOSTICint	in_pcbnotifymiss = 0;#endifstruct inpcb *in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)	struct inpcbtable *table;	struct in_addr faddr, laddr;	u_int fport_arg, lport_arg;{	struct inpcbhead *head;	register struct inpcb *inp;	u_int16_t fport = fport_arg, lport = lport_arg;	head = INPCBHASH(table, &faddr, fport, &laddr, lport);	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {		if (inp->inp_faddr.s_addr == faddr.s_addr &&		    inp->inp_fport == fport &&		    inp->inp_lport == lport &&		    inp->inp_laddr.s_addr == laddr.s_addr) {			/*			 * Move this PCB to the head of hash chain so that			 * repeated accesses are quicker.  This is analogous to			 * the historic single-entry PCB cache.			 */			if (inp != head->lh_first) {				LIST_REMOVE(inp, inp_hash);				LIST_INSERT_HEAD(head, inp, inp_hash);			}			break;		}	}#ifdef DIAGNOSTIC	if (inp == NULL && in_pcbnotifymiss) {		printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n",		    ntohl(faddr.s_addr), ntohs(fport),		    ntohl(laddr.s_addr), ntohs(lport));	}#endif	return (inp);}#ifdef INET6struct inpcb *in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)	struct inpcbtable *table;	struct in6_addr *faddr, *laddr;	u_int fport_arg, lport_arg;{	struct inpcbhead *head;	register struct inpcb *inp;	u_int16_t fport = fport_arg, lport = lport_arg;	head = IN6PCBHASH(table, faddr, fport, laddr, lport);	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {		if (!(inp->inp_flags & INP_IPV6))			continue;		if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) &&		    inp->inp_fport == fport && inp->inp_lport == lport &&		    IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr)) {			/*			 * Move this PCB to the head of hash chain so that			 * repeated accesses are quicker.  This is analogous to			 * the historic single-entry PCB cache.			 */			if (inp != head->lh_first) {				LIST_REMOVE(inp, inp_hash);				LIST_INSERT_HEAD(head, inp, inp_hash);			}			break;		}	}#ifdef DIAGNOSTIC	if (inp == NULL && in_pcbnotifymiss) {		printf("in6_pcblookup_connect: faddr=");		printf(" fport=%d laddr=", ntohs(fport));		printf(" lport=%d\n", ntohs(lport));	}#endif	return (inp);}#endif /* INET6 */

⌨️ 快捷键说明

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