Page MenuHomeFreeBSD

D60659.id189634.diff
No OneTemporary

D60659.id189634.diff

diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -48,8 +48,10 @@
#include <security/audit/audit.h>
#include <net/if.h>
-#include <net/vnet.h>
+
#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#include <net/vnet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#ifdef INET6
@@ -933,7 +935,7 @@
int
linux_socket(struct thread *td, struct linux_socket_args *args)
{
- int retval_socket, type;
+ int retval_socket, type, sock;
sa_family_t domain;
type = args->type & LINUX_SOCK_TYPE_MASK;
@@ -977,6 +979,7 @@
retval_socket = kern_socket(td, domain, type, args->protocol);
if (retval_socket)
return (retval_socket);
+ sock = td->td_retval[0];
if (type == SOCK_RAW
&& (args->protocol == IPPROTO_RAW || args->protocol == 0)
@@ -986,7 +989,7 @@
hdrincl = 1;
/* We ignore any error returned by kern_setsockopt() */
- kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
+ kern_setsockopt(td, sock, IPPROTO_IP, IP_HDRINCL,
&hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
}
#ifdef INET6
@@ -1001,11 +1004,33 @@
v6only = 0;
/* We ignore any error returned by setsockopt() */
- kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
+ kern_setsockopt(td, sock, IPPROTO_IPV6, IPV6_V6ONLY,
&v6only, UIO_SYSSPACE, sizeof(v6only));
}
#endif
+ /*
+ * Linux allows connect() on a DGRAM socket with port 0, where FreeBSD
+ * rejects this in in{,6}_pcbconnect(). Some Linux programs rely on
+ * this for routability checks, so set a flag on the inpcb to allow it.
+ */
+ if (type == SOCK_DGRAM &&
+ (domain == PF_INET || domain == PF_INET6)) {
+ struct file *fp;
+ int error;
+
+ error = getsock(td, sock, &cap_connect_rights, &fp);
+ if (error == 0) {
+ struct inpcb *inp;
+
+ inp = sotoinpcb((struct socket *)fp->f_data);
+ INP_WLOCK(inp);
+ inp->inp_flags2 |= INP_CONNECT_PORT_ZERO;
+ INP_WUNLOCK(inp);
+ fdrop(fp, td);
+ }
+ }
+
return (retval_socket);
}
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
@@ -206,7 +206,7 @@
/*
* Flags for inp_flags2.
*/
-/* 0x00000001 */
+#define INP_CONNECT_PORT_ZERO 0x00000001 /* allow connect with port 0 */
/* 0x00000002 */
/* 0x00000004 */
/* 0x00000008 */
@@ -233,6 +233,7 @@
/* inp_flags2 description for use with printf(9) %b identifier. */
#define INP_FLAGS2_BITS "\20" \
+ "\1INP_CONNECT_PORT_ZERO" \
"\11INP_RECVFLOWID\12INP_RECVRSSBUCKETID" \
"\13INP_RATE_LIMIT_CHANGED\14INP_ORIGDSTADDR" \
"\22INP_2PCP_SET\23INP_2PCP_BIT0\24INP_2PCP_BIT1" \
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
@@ -1149,7 +1149,8 @@
KASSERT(sin->sin_len == sizeof(*sin),
("%s: invalid address length for %p", __func__, sin));
- if (sin->sin_port == 0)
+ if (sin->sin_port == 0 &&
+ !(inp->inp_flags2 & INP_CONNECT_PORT_ZERO))
return (EADDRNOTAVAIL);
anonport = (inp->inp_lport == 0);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -398,7 +398,8 @@
NET_EPOCH_ASSERT();
INP_WLOCK_ASSERT(inp);
- if (sin6->sin6_port == 0)
+ if (sin6->sin6_port == 0 &&
+ !(inp->inp_flags2 & INP_CONNECT_PORT_ZERO))
return (EADDRNOTAVAIL);
if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 13, 11:32 PM (13 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40775592
Default Alt Text
D60659.id189634.diff (3 KB)

Event Timeline