Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111080309
D49142.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D49142.diff
View Options
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -645,8 +645,6 @@
int in_pcbbind_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *,
u_short *, int, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr_in *, struct ucred *);
-int in_pcbconnect_setup(const struct inpcb *, struct sockaddr_in *,
- in_addr_t *, u_short *, in_addr_t *, u_short *, struct ucred *);
void in_pcbdisconnect(struct inpcb *);
void in_pcbdrop(struct inpcb *);
void in_pcbfree(struct inpcb *);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1088,30 +1088,109 @@
int
in_pcbconnect(struct inpcb *inp, struct sockaddr_in *sin, struct ucred *cred)
{
- u_short lport, fport;
- in_addr_t laddr, faddr;
- int anonport, error;
+ struct in_addr laddr, faddr;
+ u_short lport;
+ int error;
+ bool anonport;
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
KASSERT(in_nullhost(inp->inp_faddr),
("%s: inp is already connected", __func__));
+ KASSERT(sin->sin_family == AF_INET,
+ ("%s: invalid address family for %p", __func__, sin));
+ KASSERT(sin->sin_len == sizeof(*sin),
+ ("%s: invalid address length for %p", __func__, sin));
- lport = inp->inp_lport;
- laddr = inp->inp_laddr.s_addr;
- anonport = (lport == 0);
- error = in_pcbconnect_setup(inp, sin, &laddr, &lport, &faddr, &fport,
- cred);
- if (error)
- return (error);
+ if (sin->sin_port == 0)
+ return (EADDRNOTAVAIL);
+
+ anonport = (inp->inp_lport == 0);
+
+ if (__predict_false(in_broadcast(sin->sin_addr))) {
+ if (!V_connect_inaddr_wild || CK_STAILQ_EMPTY(&V_in_ifaddrhead))
+ return (ENETUNREACH);
+ /*
+ * 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.
+ */
+ if (in_nullhost(sin->sin_addr)) {
+ faddr =
+ IA_SIN(CK_STAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
+ if ((error = prison_get_ip4(cred, &faddr)) != 0)
+ return (error);
+ } else if (sin->sin_addr.s_addr == INADDR_BROADCAST) {
+ if (CK_STAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags
+ & IFF_BROADCAST)
+ faddr = satosin(&CK_STAILQ_FIRST(
+ &V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
+ else
+ faddr = sin->sin_addr;
+ }
+ } else
+ faddr = sin->sin_addr;
+
+ if (in_nullhost(inp->inp_laddr)) {
+ error = in_pcbladdr(inp, &faddr, &laddr, cred);
+ /*
+ * If the destination address is multicast and an outgoing
+ * interface has been set as a multicast option, prefer the
+ * address of that interface as our source address.
+ */
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
+ inp->inp_moptions != NULL &&
+ inp->inp_moptions->imo_multicast_ifp != NULL) {
+ struct ifnet *ifp =
+ inp->inp_moptions->imo_multicast_ifp;
+ struct in_ifaddr *ia;
+
+ CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if (ia->ia_ifp == ifp &&
+ prison_check_ip4(cred,
+ &ia->ia_addr.sin_addr) == 0)
+ break;
+ }
+ if (ia == NULL)
+ return (EADDRNOTAVAIL);
+ laddr = ia->ia_addr.sin_addr;
+ error = 0;
+ }
+ if (error)
+ return (error);
+ } else
+ laddr = inp->inp_laddr;
+
+ if (anonport) {
+ struct sockaddr_in lsin = {
+ .sin_family = AF_INET,
+ .sin_addr = laddr,
+ };
+ struct sockaddr_in fsin = {
+ .sin_family = AF_INET,
+ .sin_addr = faddr,
+ };
+
+ error = in_pcb_lport_dest(inp, (struct sockaddr *)&lsin,
+ &lport, (struct sockaddr *)&fsin, sin->sin_port, cred,
+ INPLOOKUP_WILDCARD);
+ if (error)
+ return (error);
+ } else if (in_pcblookup_hash_locked(inp->inp_pcbinfo, faddr,
+ sin->sin_port, laddr, inp->inp_lport, 0, M_NODOM, RT_ALL_FIBS) !=
+ NULL)
+ return (EADDRINUSE);
+ else
+ lport = inp->inp_lport;
- inp->inp_faddr.s_addr = faddr;
- inp->inp_fport = fport;
+ inp->inp_faddr = faddr;
+ inp->inp_fport = sin->sin_port;
/* Do the initial binding of the local address if required. */
if (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0) {
inp->inp_lport = lport;
- inp->inp_laddr.s_addr = laddr;
+ inp->inp_laddr = laddr;
if (in_pcbinshash(inp) != 0) {
inp->inp_laddr.s_addr = inp->inp_faddr.s_addr =
INADDR_ANY;
@@ -1120,7 +1199,7 @@
}
} else {
inp->inp_lport = lport;
- inp->inp_laddr.s_addr = laddr;
+ inp->inp_laddr = laddr;
if ((inp->inp_flags & INP_INHASHLIST) != 0)
in_pcbrehash(inp);
else
@@ -1354,126 +1433,6 @@
return (error);
}
-/*
- * Set up for a connect from a socket to the specified address.
- * On entry, *laddrp and *lportp should contain the current local
- * address and port for the PCB; these are updated to the values
- * that should be placed in inp_laddr and inp_lport to complete
- * the connect.
- *
- * On success, *faddrp and *fportp will be set to the remote address
- * and port. These are not updated in the error case.
- */
-int
-in_pcbconnect_setup(const struct inpcb *inp, struct sockaddr_in *sin,
- in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp,
- struct ucred *cred)
-{
- struct in_ifaddr *ia;
- struct in_addr laddr, faddr;
- u_short lport, fport;
- int error;
-
- KASSERT(sin->sin_family == AF_INET,
- ("%s: invalid address family for %p", __func__, sin));
- KASSERT(sin->sin_len == sizeof(*sin),
- ("%s: invalid address length for %p", __func__, sin));
-
- /*
- * Because a global state change doesn't actually occur here, a read
- * lock is sufficient.
- */
- NET_EPOCH_ASSERT();
- INP_LOCK_ASSERT(inp);
- INP_HASH_LOCK_ASSERT(inp->inp_pcbinfo);
-
- if (sin->sin_port == 0)
- return (EADDRNOTAVAIL);
- laddr.s_addr = *laddrp;
- lport = *lportp;
- faddr = sin->sin_addr;
- fport = sin->sin_port;
- if (V_connect_inaddr_wild && !CK_STAILQ_EMPTY(&V_in_ifaddrhead)) {
- /*
- * 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.
- */
- if (faddr.s_addr == INADDR_ANY) {
- faddr =
- IA_SIN(CK_STAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
- if ((error = prison_get_ip4(cred, &faddr)) != 0)
- return (error);
- } else if (faddr.s_addr == (u_long)INADDR_BROADCAST) {
- if (CK_STAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
- IFF_BROADCAST)
- faddr = satosin(&CK_STAILQ_FIRST(
- &V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
- }
- } else if (faddr.s_addr == INADDR_ANY) {
- return (ENETUNREACH);
- }
- if (laddr.s_addr == INADDR_ANY) {
- error = in_pcbladdr(inp, &faddr, &laddr, cred);
- /*
- * If the destination address is multicast and an outgoing
- * interface has been set as a multicast option, prefer the
- * address of that interface as our source address.
- */
- if (IN_MULTICAST(ntohl(faddr.s_addr)) &&
- inp->inp_moptions != NULL) {
- struct ip_moptions *imo;
- struct ifnet *ifp;
-
- imo = inp->inp_moptions;
- if (imo->imo_multicast_ifp != NULL) {
- ifp = imo->imo_multicast_ifp;
- CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (ia->ia_ifp == ifp &&
- prison_check_ip4(cred,
- &ia->ia_addr.sin_addr) == 0)
- break;
- }
- if (ia == NULL)
- error = EADDRNOTAVAIL;
- else {
- laddr = ia->ia_addr.sin_addr;
- error = 0;
- }
- }
- }
- if (error)
- return (error);
- }
-
- if (lport != 0) {
- if (in_pcblookup_hash_locked(inp->inp_pcbinfo, faddr,
- fport, laddr, lport, 0, M_NODOM, RT_ALL_FIBS) != NULL)
- return (EADDRINUSE);
- } else {
- struct sockaddr_in lsin, fsin;
-
- bzero(&lsin, sizeof(lsin));
- bzero(&fsin, sizeof(fsin));
- lsin.sin_family = AF_INET;
- lsin.sin_addr = laddr;
- fsin.sin_family = AF_INET;
- fsin.sin_addr = faddr;
- error = in_pcb_lport_dest(inp, (struct sockaddr *) &lsin,
- &lport, (struct sockaddr *)& fsin, fport, cred,
- INPLOOKUP_WILDCARD);
- if (error)
- return (error);
- }
- *laddrp = laddr.s_addr;
- *lportp = lport;
- *faddrp = faddr.s_addr;
- *fportp = fport;
- return (0);
-}
-
void
in_pcbdisconnect(struct inpcb *inp)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 28, 4:03 AM (15 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16874207
Default Alt Text
D49142.diff (8 KB)
Attached To
Mode
D49142: inpcb: inline in_pcbconnect_setup() into in_pcbconnect()
Attached
Detach File
Event Timeline
Log In to Comment