diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/truss/print.c | 1 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/socket.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_socket.c | 19 | ||||
-rw-r--r-- | usr/src/uts/common/inet/udp/udp.c | 24 | ||||
-rw-r--r-- | usr/src/uts/common/inet/udp/udp_opt_data.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/inet/udp_impl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/netinet/udp.h | 2 |
7 files changed, 53 insertions, 4 deletions
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index 66a9d7387e..2b59676e30 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -2001,6 +2001,7 @@ udp_optname(private_t *pri, long val) case UDP_RCVHDR: return ("UDP_RCVHDR"); case UDP_NAT_T_ENDPOINT: return ("UDP_NAT_T_ENDPOINT"); case UDP_SRCPORT_HASH: return ("UDP_SRCPORT_HASH"); + case UDP_SND_TO_CONNECTED: return ("UDP_SND_TO_CONNECTED"); default: (void) snprintf(pri->code_buf, sizeof (pri->code_buf), "0x%lx", diff --git a/usr/src/lib/brand/lx/lx_brand/common/socket.c b/usr/src/lib/brand/lx/lx_brand/common/socket.c index 264d7ad345..d5f7161524 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/socket.c +++ b/usr/src/lib/brand/lx/lx_brand/common/socket.c @@ -1090,6 +1090,10 @@ lx_setsockopt(int sockfd, int level, int optname, void *optval, int optlen) strcmp(lx_cmd_name, "traceroute") == 0) return (0); + if (optname == LX_IP_RECVERR && + strcmp(lx_cmd_name, "mount.nfs") == 0) + return (0); + if (optname == LX_IP_MTU_DISCOVER) { /* * Native programs such as traceroute use IP_DONTFRAG diff --git a/usr/src/uts/common/brand/lx/syscall/lx_socket.c b/usr/src/uts/common/brand/lx/syscall/lx_socket.c index 1b4b24aa86..023c61b082 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_socket.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_socket.c @@ -48,6 +48,8 @@ #include <netpacket/packet.h> #include <sockcommon.h> #include <socktpi_impl.h> +#include <netinet/udp.h> +#include <sys/sdt.h> #include <sys/lx_brand.h> #include <sys/lx_socket.h> @@ -1177,7 +1179,7 @@ lx_connect(long sock, uintptr_t name, socklen_t namelen) } /* - * Ensure the name is size appropriately before we alloc memory and + * Ensure the name is sized appropriately before we alloc memory and * copy it in from userspace. We need at least the address family to * make later sizing decisions. */ @@ -1213,6 +1215,21 @@ lx_connect(long sock, uintptr_t name, socklen_t namelen) mutex_exit(&sad->lxsad_lock); } + /* + * When connecting to a UDP socket, configure it so that future + * sendto/sendmsg operations are allowed to specify a destination + * address. See the Posix spec. for sendto(2). Linux allows this while + * illumos would return EISCONN if the option is not set. + */ + if (error == 0 && so->so_protocol == IPPROTO_UDP && + (so->so_family == AF_INET || so->so_family == AF_INET6)) { + int val = 1; + + DTRACE_PROBE(lx__connect__udp); + (void) socket_setsockopt(so, IPPROTO_UDP, UDP_SND_TO_CONNECTED, + &val, sizeof (val), CRED()); + } + releasef(sock); if (addr != NULL) { diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c index eec3beddd2..7f468a190e 100644 --- a/usr/src/uts/common/inet/udp/udp.c +++ b/usr/src/uts/common/inet/udp/udp.c @@ -1673,6 +1673,11 @@ udp_opt_get(conn_t *connp, t_scalar_t level, t_scalar_t name, *i1 = udp->udp_vxlanhash; mutex_exit(&connp->conn_lock); return (sizeof (int)); + case UDP_SND_TO_CONNECTED: + mutex_enter(&connp->conn_lock); + *i1 = udp->udp_snd_to_conn ? 1 : 0; + mutex_exit(&connp->conn_lock); + return (sizeof (int)); } } mutex_enter(&connp->conn_lock); @@ -1828,6 +1833,11 @@ udp_do_opt_set(conn_opt_arg_t *coa, int level, int name, } /* Fully handled this option. */ return (0); + case UDP_SND_TO_CONNECTED: + mutex_enter(&connp->conn_lock); + udp->udp_snd_to_conn = onoff; + mutex_exit(&connp->conn_lock); + return (0); } break; } @@ -6051,6 +6061,7 @@ udp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg, ushort_t ipversion; pid_t pid = curproc->p_pid; ip_xmit_attr_t *ixa; + boolean_t snd_to_conn; ASSERT(DB_TYPE(mp) == M_DATA); @@ -6088,10 +6099,21 @@ udp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg, else return (error); } - if (udp->udp_state == TS_DATA_XFER) { + + /* + * Check if we're allowed to send to a connection on which we've + * already called 'connect'. The posix spec. allows both behaviors but + * historically we've returned an error if already connected. The + * client can allow this via a sockopt. + */ + mutex_enter(&connp->conn_lock); + snd_to_conn = (udp->udp_snd_to_conn != 0); + mutex_exit(&connp->conn_lock); + if (udp->udp_state == TS_DATA_XFER && !snd_to_conn) { UDPS_BUMP_MIB(us, udpOutErrors); return (EISCONN); } + error = proto_verify_ip_addr(connp->conn_family, (struct sockaddr *)msg->msg_name, msg->msg_namelen); if (error != 0) { diff --git a/usr/src/uts/common/inet/udp/udp_opt_data.c b/usr/src/uts/common/inet/udp/udp_opt_data.c index fec3dec4c9..847e2cdde6 100644 --- a/usr/src/uts/common/inet/udp/udp_opt_data.c +++ b/usr/src/uts/common/inet/udp/udp_opt_data.c @@ -293,7 +293,9 @@ opdes_t udp_opt_arr[] = { }, { UDP_NAT_T_ENDPOINT, IPPROTO_UDP, OA_RW, OA_RW, OP_PRIVPORT, 0, sizeof (int), 0 }, -{ UDP_SRCPORT_HASH, IPPROTO_UDP, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int), 0 } +{ UDP_SRCPORT_HASH, IPPROTO_UDP, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int), 0 }, +{ UDP_SND_TO_CONNECTED, IPPROTO_UDP, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int), + 0 } }; /* diff --git a/usr/src/uts/common/inet/udp_impl.h b/usr/src/uts/common/inet/udp_impl.h index 3b07abc309..ebba10c0f7 100644 --- a/usr/src/uts/common/inet/udp_impl.h +++ b/usr/src/uts/common/inet/udp_impl.h @@ -182,8 +182,9 @@ typedef struct udp_s { udp_vxlanhash: 1, /* UDP_SRCPORT_HASH option */ /* Because there's only VXLAN, cheat */ /* and only use a single bit */ + udp_snd_to_conn: 1, /* UDP_SND_TO_CONNECTED option */ - udp_pad_to_bit_31 : 28; + udp_pad_to_bit_31 : 27; /* Following 2 fields protected by the uf_lock */ struct udp_s *udp_bind_hash; /* Bind hash chain */ diff --git a/usr/src/uts/common/netinet/udp.h b/usr/src/uts/common/netinet/udp.h index fb9f8a0976..74cff75d43 100644 --- a/usr/src/uts/common/netinet/udp.h +++ b/usr/src/uts/common/netinet/udp.h @@ -1,6 +1,7 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2015 Joyent, Inc. */ /* @@ -34,6 +35,7 @@ struct udphdr { #define UDP_RCVHDR 0x0102 /* for internal use only */ #define UDP_NAT_T_ENDPOINT 0x0103 /* for internal use only */ #define UDP_SRCPORT_HASH 0x0104 /* for internal use only */ +#define UDP_SND_TO_CONNECTED 0x0105 /* for internal use only */ /* * Hash definitions for UDP_SRCPORT_HASH that effectively tell UDP how to go |