Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175743563
D60659.id189634.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D60659.id189634.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60659: linux: Allow connect() on DGRAM sockets with port 0
Attached
Detach File
Event Timeline
Log In to Comment