diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in_pcb.c | 121 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 7 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 11 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 16 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 12 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 24 |
6 files changed, 150 insertions, 41 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 0ceb29fa4e6..5d8e28ff09c 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.68 2003/10/25 12:15:24 markus Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.69 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -955,6 +955,15 @@ in_pcbrehash(inp) int in_pcbnotifymiss = 0; #endif +/* + * The in(6)_pcbhashlookup functions are used to locate connected sockets + * quickly: + * faddr.fport <-> laddr.lport + * No wildcard matching is done so that listening sockets are not found. + * If the functions return NULL in(6)_pcblookup_listen can be used to + * find a listening/bound socket that may accept the connection. + * After those two lookups no other are necessary. + */ struct inpcb * in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) struct inpcbtable *table; @@ -1029,7 +1038,7 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) } #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { - printf("in6_pcblookup_connect: faddr="); + printf("in6_pcbhashlookup: faddr="); printf(" fport=%d laddr=", ntohs(fport)); printf(" lport=%d\n", ntohs(lport)); } @@ -1038,4 +1047,112 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) } #endif /* INET6 */ +/* + * The in(6)_pcblookup_listen functions are used to locate listening + * sockets quickly. This are sockets with unspecified foreign address + * and port: + * *.* <-> laddr.lport + * *.* <-> *.lport + */ +struct inpcb * +in_pcblookup_listen(table, laddr, lport_arg) + struct inpcbtable *table; + struct in_addr laddr; + u_int lport_arg; +{ + struct inpcbhead *head; + register struct inpcb *inp; + u_int16_t lport = lport_arg; + + head = INPCBHASH(table, &zeroin_addr, 0, &laddr, lport); + LIST_FOREACH(inp, head, inp_hash) { +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + continue; /*XXX*/ +#endif + if (inp->inp_lport == lport && inp->inp_fport == 0 && + inp->inp_laddr.s_addr == laddr.s_addr && + inp->inp_faddr.s_addr == INADDR_ANY) + break; + } + if (inp == NULL && laddr.s_addr != INADDR_ANY) { + head = INPCBHASH(table, &zeroin_addr, 0, &zeroin_addr, lport); + LIST_FOREACH(inp, head, inp_hash) { +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + continue; /*XXX*/ +#endif + if (inp->inp_lport == lport && inp->inp_fport == 0 && + inp->inp_laddr.s_addr == INADDR_ANY && + inp->inp_faddr.s_addr == INADDR_ANY) + break; + } + } +#ifdef DIAGNOSTIC + if (inp == NULL && in_pcbnotifymiss) { + printf("in_pcblookup_listen: laddr=%08x lport=%d\n", + ntohl(laddr.s_addr), ntohs(lport)); + } +#endif + /* + * 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 != NULL && inp != head->lh_first) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + return (inp); +} + +#ifdef INET6 +struct inpcb * +in6_pcblookup_listen(table, laddr, lport_arg) + struct inpcbtable *table; + struct in6_addr *laddr; + u_int lport_arg; +{ + struct inpcbhead *head; + register struct inpcb *inp; + u_int16_t lport = lport_arg; + head = IN6PCBHASH(table, &zeroin6_addr, 0, laddr, lport); + LIST_FOREACH(inp, head, inp_hash) { + if (!(inp->inp_flags & INP_IPV6)) + continue; + if (inp->inp_lport == lport && inp->inp_fport == 0 && + IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr) && + IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) + break; + } + if (inp == NULL && !IN6_IS_ADDR_UNSPECIFIED(laddr)) { + head = IN6PCBHASH(table, &zeroin6_addr, 0, + &zeroin6_addr, lport); + LIST_FOREACH(inp, head, inp_hash) { + if (!(inp->inp_flags & INP_IPV6)) + continue; + if (inp->inp_lport == lport && inp->inp_fport == 0 && + IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) && + IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) + break; + } + } +#ifdef DIAGNOSTIC + if (inp == NULL && in_pcbnotifymiss) { + printf("in6_pcblookup_listen: laddr= lport=%d\n", + ntohs(lport)); + } +#endif + /* + * 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 != NULL && inp != head->lh_first) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + return (inp); +} +#endif /* INET6 */ diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 684c941b634..5f5ec71b589 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.46 2003/10/25 12:15:24 markus Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.47 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -238,10 +238,15 @@ void in_pcbdisconnect(void *); struct inpcb * in_pcbhashlookup(struct inpcbtable *, struct in_addr, u_int, struct in_addr, u_int); +struct inpcb * + in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int); #ifdef INET6 struct inpcb * in6_pcbhashlookup(struct inpcbtable *, struct in6_addr *, u_int, struct in6_addr *, u_int); +struct inpcb * + in6_pcblookup_listen(struct inpcbtable *, + struct in6_addr *, u_int); int in6_pcbbind(struct inpcb *, struct mbuf *); int in6_pcbconnect(struct inpcb *, struct mbuf *); int in6_setsockaddr(struct inpcb *, struct mbuf *); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 5ceeb6ccc9b..a786851a75a 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.133 2003/10/01 21:41:05 itojun Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.134 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -670,14 +670,13 @@ findpcb: switch (af) { #ifdef INET6 case AF_INET6: - inp = in_pcblookup(&tcbtable, &ip6->ip6_src, - th->th_sport, &ip6->ip6_dst, th->th_dport, - INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + inp = in6_pcblookup_listen(&tcbtable, + &ip6->ip6_dst, th->th_dport); break; #endif /* INET6 */ case AF_INET: - inp = in_pcblookup(&tcbtable, &ip->ip_src, th->th_sport, - &ip->ip_dst, th->th_dport, INPLOOKUP_WILDCARD); + inp = in_pcblookup_listen(&tcbtable, + ip->ip_dst, th->th_dport); break; } /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index e5ecf5c0ee2..e2110b8b23a 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.69 2003/10/01 21:41:05 itojun Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.70 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -839,10 +839,6 @@ tcp6_ctlinput(cmd, sa, d) th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr, th.th_sport)) valid++; - else if (in_pcblookup(&tcbtable, &sa6->sin6_addr, - th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr, - th.th_sport, INPLOOKUP_IPV6)) - valid++; /* * Depending on the value of "valid" and routing table @@ -893,10 +889,12 @@ tcp_ctlinput(cmd, sa, v) * Verify that the packet in the icmp payload refers * to an existing TCP connection. */ - if (in_pcblookup(&tcbtable, - &ip->ip_dst, th->th_dport, - &ip->ip_src, th->th_sport, - INPLOOKUP_WILDCARD)) { + /* + * XXX is it possible to get a valid PRC_MSGSIZE error for + * a non-established connection? + */ + if (in_pcbhashlookup(&tcbtable, + ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport)) { struct icmp *icp; icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip)); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 501efc21a7b..ff9983289b7 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.71 2003/06/09 07:40:25 itojun Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.72 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -834,15 +834,13 @@ tcp_ident(oldp, oldlenp, newp, newlen) switch (tir.faddr.ss_family) { #ifdef INET6 case AF_INET6: - inp = in_pcblookup(&tcbtable, &f6, - fin6->sin6_port, &l6, lin6->sin6_port, - INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + inp = in6_pcblookup_listen(&tcbtable, + &l6, lin6->sin6_port); break; #endif case AF_INET: - inp = in_pcblookup(&tcbtable, &fin->sin_addr, - fin->sin_port, &lin->sin_addr, lin->sin_port, - INPLOOKUP_WILDCARD); + inp = in_pcblookup_listen(&tcbtable, + lin->sin_addr, lin->sin_port); break; } } diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 9e5842d6087..6a36106dafc 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.91 2003/07/09 22:03:16 itojun Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.92 2003/11/04 21:43:16 markus Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -483,14 +483,12 @@ udp_input(struct mbuf *m, ...) ++udpstat.udps_pcbhashmiss; #ifdef INET6 if (ip6) { - inp = in_pcblookup(&udbtable, - (struct in_addr *)&(ip6->ip6_src), - uh->uh_sport, (struct in_addr *)&(ip6->ip6_dst), - uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + inp = in6_pcblookup_listen(&udbtable, + &ip6->ip6_dst, uh->uh_dport); } else #endif /* INET6 */ - inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport, - &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); + inp = in_pcblookup_listen(&udbtable, + ip->ip_dst, uh->uh_dport); if (inp == 0) { udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { @@ -665,7 +663,6 @@ udp6_ctlinput(cmd, sa, d) int off; void *cmdarg; struct ip6ctlparam *ip6cp = NULL; - struct in6_addr finaldst; struct udp_portonly { u_int16_t uh_sport; u_int16_t uh_dport; @@ -770,13 +767,9 @@ udp6_ctlinput(cmd, sa, d) * corresponding to the address in the ICMPv6 message * payload. */ - if (in6_pcbhashlookup(&udbtable, &finaldst, + if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr, uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport)) valid = 1; - else if (in_pcblookup(&udbtable, &sa6.sin6_addr, - uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, - INPLOOKUP_IPV6)) - valid = 1; #if 0 /* * As the use of sendto(2) is fairly popular, @@ -785,9 +778,8 @@ udp6_ctlinput(cmd, sa, d) * We should at least check if the local address (= s) * is really ours. */ - else if (in_pcblookup(&udbtable, &sa6.sin6_addr, - uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, - INPLOOKUP_WILDCARD | INPLOOKUP_IPV6)) + else if (in6_pcblookup_listen(&udbtable, + &sa6_src.sin6_addr, uh.uh_sport)) valid = 1; #endif |