projects
/
unix-history
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
tags
|
clone url
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
bug fixes from elz and utcsrgv!thomson
[unix-history]
/
usr
/
src
/
sys
/
netinet
/
in_pcb.c
diff --git
a/usr/src/sys/netinet/in_pcb.c
b/usr/src/sys/netinet/in_pcb.c
index
81e2b5d
..
ad13011
100644
(file)
--- a/
usr/src/sys/netinet/in_pcb.c
+++ b/
usr/src/sys/netinet/in_pcb.c
@@
-1,4
+1,4
@@
-/* in_pcb.c 4.
17 82/02/27
*/
+/* in_pcb.c 4.
24 82/03/30
*/
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
@@
-10,7
+10,9
@@
#include "../net/in.h"
#include "../net/in_systm.h"
#include "../net/if.h"
#include "../net/in.h"
#include "../net/in_systm.h"
#include "../net/if.h"
+#include "../net/route.h"
#include "../net/in_pcb.h"
#include "../net/in_pcb.h"
+#include "../h/protosw.h"
/*
* Routines to manage internet protocol control blocks.
/*
* Routines to manage internet protocol control blocks.
@@
-67,20
+69,29
@@
COUNT(IN_PCBATTACH);
if (sin) {
if (sin->sin_family != AF_INET)
return (EAFNOSUPPORT);
if (sin) {
if (sin->sin_family != AF_INET)
return (EAFNOSUPPORT);
- if (sin->sin_addr.s_addr &&
- if_ifwithaddr(sin->sin_addr.s_addr) == 0)
- return (EADDRNOTAVAIL);
+ if (sin->sin_addr.s_addr) {
+ int tport = sin->sin_port;
+
+ sin->sin_port = 0; /* yech... */
+ if (if_ifwithaddr((struct sockaddr *)sin) == 0)
+ return (EADDRNOTAVAIL);
+ sin->sin_port = tport;
+ }
lport = sin->sin_port;
if (lport) {
u_short aport = lport;
lport = sin->sin_port;
if (lport) {
u_short aport = lport;
+ int wild = 0;
#if vax
aport = htons(aport);
#endif
/* GROSS */
if (aport < IPPORT_RESERVED && u.u_uid != 0)
return (EPERM);
#if vax
aport = htons(aport);
#endif
/* GROSS */
if (aport < IPPORT_RESERVED && u.u_uid != 0)
return (EPERM);
+ if ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
+ (so->so_options & SO_ACCEPTCONN) == 0)
+ wild = INPLOOKUP_WILDCARD;
if (in_pcblookup(head,
if (in_pcblookup(head,
- zeroin_addr, 0, sin->sin_addr, lport,
0
))
+ zeroin_addr, 0, sin->sin_addr, lport,
wild
))
return (EADDRINUSE);
}
}
return (EADDRINUSE);
}
}
@@
-115,11
+126,18
@@
bad:
return (ENOBUFS);
}
return (ENOBUFS);
}
+/*
+ * 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, sin)
struct inpcb *inp;
struct sockaddr_in *sin;
{
struct ifnet *ifp;
in_pcbconnect(inp, sin)
struct inpcb *inp;
struct sockaddr_in *sin;
{
struct ifnet *ifp;
+ struct sockaddr_in *ifaddr;
COUNT(IN_PCBCONNECT);
if (sin->sin_family != AF_INET)
COUNT(IN_PCBCONNECT);
if (sin->sin_family != AF_INET)
@@
-127,14
+145,28
@@
COUNT(IN_PCBCONNECT);
if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0)
return (EADDRNOTAVAIL);
if (inp->inp_laddr.s_addr == 0) {
if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0)
return (EADDRNOTAVAIL);
if (inp->inp_laddr.s_addr == 0) {
- ifp = if_ifonnetof(sin->sin_addr.s_addr);
- if (ifp == 0)
- ifp = ifnet;
- inp->inp_laddr = ifp->if_addr;
+ ifp = if_ifonnetof(sin->sin_addr.s_net);
+ if (ifp == 0) {
+ ifp = if_ifwithaf(AF_INET);
+ if (ifp == 0)
+ return (EADDRNOTAVAIL); /* XXX */
+ }
+ ifaddr = (struct sockaddr_in *)&ifp->if_addr;
}
if (in_pcblookup(inp->inp_head,
}
if (in_pcblookup(inp->inp_head,
- sin->sin_addr, sin->sin_port, inp->inp_laddr, inp->inp_lport, 0))
+ sin->sin_addr,
+ sin->sin_port,
+ inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
+ inp->inp_lport,
+ 0))
return (EADDRINUSE);
return (EADDRINUSE);
+ if (inp->inp_laddr.s_addr == 0) {
+ struct sockaddr_in *sin2 =
+ (struct sockaddr_in *)&inp->inp_socket->so_addr;
+
+ inp->inp_laddr = ifaddr->sin_addr;
+ sin2->sin_addr = inp->inp_laddr;
+ }
inp->inp_faddr = sin->sin_addr;
inp->inp_fport = sin->sin_port;
return (0);
inp->inp_faddr = sin->sin_addr;
inp->inp_fport = sin->sin_port;
return (0);
@@
-157,6
+189,7
@@
in_pcbdisconnect(inp)
COUNT(IN_PCBDISCONNECT);
inp->inp_faddr.s_addr = 0;
COUNT(IN_PCBDISCONNECT);
inp->inp_faddr.s_addr = 0;
+ inp->inp_fport = 0;
if (inp->inp_socket->so_state & SS_USERGONE)
in_pcbdetach(inp);
}
if (inp->inp_socket->so_state & SS_USERGONE)
in_pcbdetach(inp);
}
@@
-168,24
+201,21
@@
in_pcbdetach(inp)
so->so_pcb = 0;
sofree(so);
so->so_pcb = 0;
sofree(so);
+ if (inp->inp_route.ro_rt)
+ rtfree(inp->inp_route.ro_rt);
remque(inp);
(void) m_free(dtom(inp));
}
/*
remque(inp);
(void) m_free(dtom(inp));
}
/*
- * Look for a control block to accept a segment.
- * First choice is an exact address match.
- * Second choice is a match with either the foreign or the local
- * address specified.
- *
* SHOULD ALLOW MATCH ON MULTI-HOMING ONLY
*/
struct inpcb *
* SHOULD ALLOW MATCH ON MULTI-HOMING ONLY
*/
struct inpcb *
-in_pcblookup(head, faddr, fport, laddr, lport,
enter
)
+in_pcblookup(head, faddr, fport, laddr, lport,
flags
)
struct inpcb *head;
struct in_addr faddr, laddr;
u_short fport, lport;
struct inpcb *head;
struct in_addr faddr, laddr;
u_short fport, lport;
- int
enter
;
+ int
flags
;
{
register struct inpcb *inp, *match = 0;
int matchwild = 3, wildcard;
{
register struct inpcb *inp, *match = 0;
int matchwild = 3, wildcard;
@@
-195,20
+225,25
@@
in_pcblookup(head, faddr, fport, laddr, lport, enter)
continue;
wildcard = 0;
if (inp->inp_laddr.s_addr != 0) {
continue;
wildcard = 0;
if (inp->inp_laddr.s_addr != 0) {
- if (inp->inp_laddr.s_addr != laddr.s_addr)
+ if (laddr.s_addr == 0)
+ wildcard++;
+ else if (inp->inp_laddr.s_addr != laddr.s_addr)
continue;
} else {
if (laddr.s_addr != 0)
wildcard++;
}
if (inp->inp_faddr.s_addr != 0) {
continue;
} else {
if (laddr.s_addr != 0)
wildcard++;
}
if (inp->inp_faddr.s_addr != 0) {
- if (inp->inp_faddr.s_addr != faddr.s_addr)
+ if (faddr.s_addr == 0)
+ wildcard++;
+ else if (inp->inp_faddr.s_addr != faddr.s_addr ||
+ inp->inp_fport != fport)
continue;
} else {
if (faddr.s_addr != 0)
wildcard++;
}
continue;
} else {
if (faddr.s_addr != 0)
wildcard++;
}
- if (
enter == 0 && wildcard
)
+ if (
wildcard && (flags & INPLOOKUP_WILDCARD) == 0
)
continue;
if (wildcard < matchwild) {
match = inp;
continue;
if (wildcard < matchwild) {
match = inp;
@@
-217,9
+252,5
@@
in_pcblookup(head, faddr, fport, laddr, lport, enter)
break;
}
}
break;
}
}
- if (match && enter) {
- match->inp_laddr = laddr;
- in_setsockaddr(match);
- }
return (match);
}
return (match);
}