1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1473 ja97890 * Common Development and Distribution License (the "License"). 6 1473 ja97890 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8477 Rao * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel /* Copyright (c) 1990 Mentat Inc. */ 26 0 stevel 27 0 stevel #include <sys/types.h> 28 0 stevel #include <sys/stream.h> 29 0 stevel #include <sys/stropts.h> 30 0 stevel #include <sys/strlog.h> 31 0 stevel #include <sys/strsun.h> 32 0 stevel #define _SUN_TPI_VERSION 2 33 0 stevel #include <sys/tihdr.h> 34 0 stevel #include <sys/timod.h> 35 0 stevel #include <sys/ddi.h> 36 0 stevel #include <sys/sunddi.h> 37 0 stevel #include <sys/strsubr.h> 38 0 stevel #include <sys/suntpi.h> 39 0 stevel #include <sys/xti_inet.h> 40 0 stevel #include <sys/kmem.h> 41 11042 Erik #include <sys/cred_impl.h> 42 0 stevel #include <sys/policy.h> 43 11042 Erik #include <sys/priv.h> 44 0 stevel #include <sys/ucred.h> 45 0 stevel #include <sys/zone.h> 46 0 stevel 47 0 stevel #include <sys/socket.h> 48 8348 Eric #include <sys/socketvar.h> 49 741 masputra #include <sys/sockio.h> 50 0 stevel #include <sys/vtrace.h> 51 2958 dr146992 #include <sys/sdt.h> 52 0 stevel #include <sys/debug.h> 53 0 stevel #include <sys/isa_defs.h> 54 0 stevel #include <sys/random.h> 55 0 stevel #include <netinet/in.h> 56 0 stevel #include <netinet/ip6.h> 57 0 stevel #include <netinet/icmp6.h> 58 0 stevel #include <netinet/udp.h> 59 0 stevel 60 0 stevel #include <inet/common.h> 61 0 stevel #include <inet/ip.h> 62 741 masputra #include <inet/ip_impl.h> 63 11042 Erik #include <inet/ipsec_impl.h> 64 0 stevel #include <inet/ip6.h> 65 0 stevel #include <inet/ip_ire.h> 66 741 masputra #include <inet/ip_if.h> 67 741 masputra #include <inet/ip_multi.h> 68 2535 sangeeta #include <inet/ip_ndp.h> 69 8348 Eric #include <inet/proto_set.h> 70 0 stevel #include <inet/mib2.h> 71 0 stevel #include <inet/nd.h> 72 0 stevel #include <inet/optcom.h> 73 0 stevel #include <inet/snmpcom.h> 74 0 stevel #include <inet/kstatcom.h> 75 741 masputra #include <inet/ipclassifier.h> 76 8275 Eric #include <sys/squeue_impl.h> 77 8023 Phil #include <inet/ipnet.h> 78 8485 Peter #include <sys/ethernet.h> 79 741 masputra 80 1676 jpk #include <sys/tsol/label.h> 81 1676 jpk #include <sys/tsol/tnet.h> 82 1676 jpk #include <rpc/pmap_prot.h> 83 0 stevel 84 11042 Erik #include <inet/udp_impl.h> 85 11042 Erik 86 0 stevel /* 87 0 stevel * Synchronization notes: 88 0 stevel * 89 5240 nordmark * UDP is MT and uses the usual kernel synchronization primitives. There are 2 90 11042 Erik * locks, the fanout lock (uf_lock) and conn_lock. conn_lock 91 11042 Erik * protects the contents of the udp_t. uf_lock protects the address and the 92 11042 Erik * fanout information. 93 11042 Erik * The lock order is conn_lock -> uf_lock. 94 5240 nordmark * 95 5240 nordmark * The fanout lock uf_lock: 96 741 masputra * When a UDP endpoint is bound to a local port, it is inserted into 97 0 stevel * a bind hash list. The list consists of an array of udp_fanout_t buckets. 98 0 stevel * The size of the array is controlled by the udp_bind_fanout_size variable. 99 0 stevel * This variable can be changed in /etc/system if the default value is 100 741 masputra * not large enough. Each bind hash bucket is protected by a per bucket 101 741 masputra * lock. It protects the udp_bind_hash and udp_ptpbhn fields in the udp_t 102 5240 nordmark * structure and a few other fields in the udp_t. A UDP endpoint is removed 103 5240 nordmark * from the bind hash list only when it is being unbound or being closed. 104 5240 nordmark * The per bucket lock also protects a UDP endpoint's state changes. 105 5240 nordmark * 106 741 masputra * Plumbing notes: 107 5240 nordmark * UDP is always a device driver. For compatibility with mibopen() code 108 5240 nordmark * it is possible to I_PUSH "udp", but that results in pushing a passthrough 109 5240 nordmark * dummy module. 110 5240 nordmark * 111 5240 nordmark * The above implies that we don't support any intermediate module to 112 741 masputra * reside in between /dev/ip and udp -- in fact, we never supported such 113 741 masputra * scenario in the past as the inter-layer communication semantics have 114 5240 nordmark * always been private. 115 5240 nordmark */ 116 0 stevel 117 3448 dh155122 /* For /etc/system control */ 118 0 stevel uint_t udp_bind_fanout_size = UDP_BIND_FANOUT_SIZE; 119 1676 jpk 120 0 stevel static void udp_addr_req(queue_t *q, mblk_t *mp); 121 8348 Eric static void udp_tpi_bind(queue_t *q, mblk_t *mp); 122 0 stevel static void udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp); 123 0 stevel static void udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock); 124 11042 Erik static int udp_build_hdr_template(conn_t *, const in6_addr_t *, 125 11042 Erik const in6_addr_t *, in_port_t, uint32_t); 126 0 stevel static void udp_capability_req(queue_t *q, mblk_t *mp); 127 8348 Eric static int udp_tpi_close(queue_t *q, int flags); 128 11042 Erik static void udp_close_free(conn_t *); 129 8348 Eric static void udp_tpi_connect(queue_t *q, mblk_t *mp); 130 8348 Eric static void udp_tpi_disconnect(queue_t *q, mblk_t *mp); 131 0 stevel static void udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, 132 11042 Erik int sys_error); 133 11042 Erik static void udp_err_ack_prim(queue_t *q, mblk_t *mp, t_scalar_t primitive, 134 11042 Erik t_scalar_t tlierr, int sys_error); 135 0 stevel static int udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, 136 0 stevel cred_t *cr); 137 0 stevel static int udp_extra_priv_ports_add(queue_t *q, mblk_t *mp, 138 0 stevel char *value, caddr_t cp, cred_t *cr); 139 0 stevel static int udp_extra_priv_ports_del(queue_t *q, mblk_t *mp, 140 0 stevel char *value, caddr_t cp, cred_t *cr); 141 11042 Erik static void udp_icmp_input(void *, mblk_t *, void *, ip_recv_attr_t *); 142 11042 Erik static void udp_icmp_error_ipv6(conn_t *connp, mblk_t *mp, 143 11042 Erik ip_recv_attr_t *ira); 144 0 stevel static void udp_info_req(queue_t *q, mblk_t *mp); 145 11042 Erik static void udp_input(void *, mblk_t *, void *, ip_recv_attr_t *); 146 5240 nordmark static void udp_lrput(queue_t *, mblk_t *); 147 5240 nordmark static void udp_lwput(queue_t *, mblk_t *); 148 0 stevel static int udp_open(queue_t *q, dev_t *devp, int flag, int sflag, 149 5240 nordmark cred_t *credp, boolean_t isv6); 150 5240 nordmark static int udp_openv4(queue_t *q, dev_t *devp, int flag, int sflag, 151 5240 nordmark cred_t *credp); 152 5240 nordmark static int udp_openv6(queue_t *q, dev_t *devp, int flag, int sflag, 153 0 stevel cred_t *credp); 154 0 stevel static boolean_t udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name); 155 11042 Erik int udp_opt_set(conn_t *connp, uint_t optset_context, 156 11042 Erik int level, int name, uint_t inlen, 157 11042 Erik uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp, 158 11042 Erik void *thisdg_attrs, cred_t *cr); 159 11042 Erik int udp_opt_get(conn_t *connp, int level, int name, 160 11042 Erik uchar_t *ptr); 161 11042 Erik static int udp_output_connected(conn_t *connp, mblk_t *mp, cred_t *cr, 162 11042 Erik pid_t pid); 163 11042 Erik static int udp_output_lastdst(conn_t *connp, mblk_t *mp, cred_t *cr, 164 11042 Erik pid_t pid, ip_xmit_attr_t *ixa); 165 11042 Erik static int udp_output_newdst(conn_t *connp, mblk_t *data_mp, sin_t *sin, 166 11042 Erik sin6_t *sin6, ushort_t ipversion, cred_t *cr, pid_t, 167 11042 Erik ip_xmit_attr_t *ixa); 168 0 stevel static int udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr); 169 3448 dh155122 static boolean_t udp_param_register(IDP *ndp, udpparam_t *udppa, int cnt); 170 0 stevel static int udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 171 0 stevel cred_t *cr); 172 11042 Erik static mblk_t *udp_prepend_hdr(conn_t *, ip_xmit_attr_t *, const ip_pkt_t *, 173 11042 Erik const in6_addr_t *, const in6_addr_t *, in_port_t, uint32_t, mblk_t *, 174 11042 Erik int *); 175 11042 Erik static mblk_t *udp_prepend_header_template(conn_t *, ip_xmit_attr_t *, 176 11042 Erik mblk_t *, const in6_addr_t *, in_port_t, uint32_t, int *); 177 11042 Erik static void udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err); 178 11042 Erik static void udp_ud_err_connected(conn_t *, t_scalar_t); 179 8348 Eric static void udp_tpi_unbind(queue_t *q, mblk_t *mp); 180 1676 jpk static in_port_t udp_update_next_port(udp_t *udp, in_port_t port, 181 1676 jpk boolean_t random); 182 0 stevel static void udp_wput_other(queue_t *q, mblk_t *mp); 183 0 stevel static void udp_wput_iocdata(queue_t *q, mblk_t *mp); 184 8348 Eric static void udp_wput_fallback(queue_t *q, mblk_t *mp); 185 741 masputra static size_t udp_set_rcv_hiwat(udp_t *udp, size_t size); 186 0 stevel 187 3448 dh155122 static void *udp_stack_init(netstackid_t stackid, netstack_t *ns); 188 3448 dh155122 static void udp_stack_fini(netstackid_t stackid, void *arg); 189 3448 dh155122 190 3448 dh155122 static void *udp_kstat_init(netstackid_t stackid); 191 3448 dh155122 static void udp_kstat_fini(netstackid_t stackid, kstat_t *ksp); 192 3448 dh155122 static void *udp_kstat2_init(netstackid_t, udp_stat_t *); 193 3448 dh155122 static void udp_kstat2_fini(netstackid_t, kstat_t *); 194 0 stevel static int udp_kstat_update(kstat_t *kp, int rw); 195 741 masputra 196 11042 Erik 197 11042 Erik /* Common routines for TPI and socket module */ 198 11042 Erik static void udp_ulp_recv(conn_t *, mblk_t *, uint_t, ip_recv_attr_t *); 199 8348 Eric 200 8348 Eric /* Common routine for TPI and socket module */ 201 8348 Eric static conn_t *udp_do_open(cred_t *, boolean_t, int); 202 8348 Eric static void udp_do_close(conn_t *); 203 8348 Eric static int udp_do_bind(conn_t *, struct sockaddr *, socklen_t, cred_t *, 204 8348 Eric boolean_t); 205 8348 Eric static int udp_do_unbind(conn_t *); 206 8348 Eric 207 8348 Eric int udp_getsockname(sock_lower_handle_t, 208 8348 Eric struct sockaddr *, socklen_t *, cred_t *); 209 8348 Eric int udp_getpeername(sock_lower_handle_t, 210 8348 Eric struct sockaddr *, socklen_t *, cred_t *); 211 8778 Erik static int udp_do_connect(conn_t *, const struct sockaddr *, socklen_t, 212 11042 Erik cred_t *, pid_t); 213 8348 Eric 214 741 masputra #define UDP_RECV_HIWATER (56 * 1024) 215 741 masputra #define UDP_RECV_LOWATER 128 216 741 masputra #define UDP_XMIT_HIWATER (56 * 1024) 217 741 masputra #define UDP_XMIT_LOWATER 1024 218 741 masputra 219 11042 Erik #pragma inline(udp_output_connected, udp_output_newdst, udp_output_lastdst) 220 8392 Huafeng 221 8392 Huafeng /* 222 8392 Huafeng * Checks if the given destination addr/port is allowed out. 223 8392 Huafeng * If allowed, registers the (dest_addr/port, node_ID) mapping at Cluster. 224 8392 Huafeng * Called for each connect() and for sendto()/sendmsg() to a different 225 8392 Huafeng * destination. 226 8392 Huafeng * For connect(), called in udp_connect(). 227 11042 Erik * For sendto()/sendmsg(), called in udp_output_newdst(). 228 8392 Huafeng * 229 8392 Huafeng * This macro assumes that the cl_inet_connect2 hook is not NULL. 230 8392 Huafeng * Please check this before calling this macro. 231 8392 Huafeng * 232 8392 Huafeng * void 233 8392 Huafeng * CL_INET_UDP_CONNECT(conn_t cp, udp_t *udp, boolean_t is_outgoing, 234 8392 Huafeng * in6_addr_t *faddrp, in_port_t (or uint16_t) fport, int err); 235 8392 Huafeng */ 236 11042 Erik #define CL_INET_UDP_CONNECT(cp, is_outgoing, faddrp, fport, err) { \ 237 8392 Huafeng (err) = 0; \ 238 8392 Huafeng /* \ 239 8392 Huafeng * Running in cluster mode - check and register active \ 240 8392 Huafeng * "connection" information \ 241 8392 Huafeng */ \ 242 11042 Erik if ((cp)->conn_ipversion == IPV4_VERSION) \ 243 8392 Huafeng (err) = (*cl_inet_connect2)( \ 244 8392 Huafeng (cp)->conn_netstack->netstack_stackid, \ 245 8392 Huafeng IPPROTO_UDP, is_outgoing, AF_INET, \ 246 11042 Erik (uint8_t *)&((cp)->conn_laddr_v4), \ 247 11042 Erik (cp)->conn_lport, \ 248 11042 Erik (uint8_t *)&(V4_PART_OF_V6(*faddrp)), \ 249 8392 Huafeng (in_port_t)(fport), NULL); \ 250 8392 Huafeng else \ 251 8392 Huafeng (err) = (*cl_inet_connect2)( \ 252 8392 Huafeng (cp)->conn_netstack->netstack_stackid, \ 253 8392 Huafeng IPPROTO_UDP, is_outgoing, AF_INET6, \ 254 11042 Erik (uint8_t *)&((cp)->conn_laddr_v6), \ 255 11042 Erik (cp)->conn_lport, \ 256 8392 Huafeng (uint8_t *)(faddrp), (in_port_t)(fport), NULL); \ 257 8392 Huafeng } 258 8392 Huafeng 259 5240 nordmark static struct module_info udp_mod_info = { 260 741 masputra UDP_MOD_ID, UDP_MOD_NAME, 1, INFPSZ, UDP_RECV_HIWATER, UDP_RECV_LOWATER 261 741 masputra }; 262 741 masputra 263 5240 nordmark /* 264 5240 nordmark * Entry points for UDP as a device. 265 5240 nordmark * We have separate open functions for the /dev/udp and /dev/udp6 devices. 266 5240 nordmark */ 267 5240 nordmark static struct qinit udp_rinitv4 = { 268 9991 Anders NULL, NULL, udp_openv4, udp_tpi_close, NULL, &udp_mod_info, NULL 269 5240 nordmark }; 270 5240 nordmark 271 5240 nordmark static struct qinit udp_rinitv6 = { 272 9991 Anders NULL, NULL, udp_openv6, udp_tpi_close, NULL, &udp_mod_info, NULL 273 741 masputra }; 274 741 masputra 275 741 masputra static struct qinit udp_winit = { 276 9991 Anders (pfi_t)udp_wput, (pfi_t)ip_wsrv, NULL, NULL, NULL, &udp_mod_info 277 5240 nordmark }; 278 5240 nordmark 279 8348 Eric /* UDP entry point during fallback */ 280 8348 Eric struct qinit udp_fallback_sock_winit = { 281 8348 Eric (pfi_t)udp_wput_fallback, NULL, NULL, NULL, NULL, &udp_mod_info 282 8348 Eric }; 283 8348 Eric 284 5240 nordmark /* 285 5240 nordmark * UDP needs to handle I_LINK and I_PLINK since ifconfig 286 5240 nordmark * likes to use it as a place to hang the various streams. 287 5240 nordmark */ 288 5240 nordmark static struct qinit udp_lrinit = { 289 9991 Anders (pfi_t)udp_lrput, NULL, udp_openv4, udp_tpi_close, NULL, &udp_mod_info 290 5240 nordmark }; 291 5240 nordmark 292 5240 nordmark static struct qinit udp_lwinit = { 293 9991 Anders (pfi_t)udp_lwput, NULL, udp_openv4, udp_tpi_close, NULL, &udp_mod_info 294 5240 nordmark }; 295 5240 nordmark 296 5240 nordmark /* For AF_INET aka /dev/udp */ 297 5240 nordmark struct streamtab udpinfov4 = { 298 5240 nordmark &udp_rinitv4, &udp_winit, &udp_lrinit, &udp_lwinit 299 5240 nordmark }; 300 5240 nordmark 301 5240 nordmark /* For AF_INET6 aka /dev/udp6 */ 302 5240 nordmark struct streamtab udpinfov6 = { 303 5240 nordmark &udp_rinitv6, &udp_winit, &udp_lrinit, &udp_lwinit 304 0 stevel }; 305 0 stevel 306 0 stevel static sin_t sin_null; /* Zero address for quick clears */ 307 0 stevel static sin6_t sin6_null; /* Zero address for quick clears */ 308 0 stevel 309 741 masputra #define UDP_MAXPACKET_IPV4 (IP_MAXPACKET - UDPH_SIZE - IP_SIMPLE_HDR_LENGTH) 310 0 stevel 311 0 stevel /* Default structure copied into T_INFO_ACK messages */ 312 0 stevel static struct T_info_ack udp_g_t_info_ack_ipv4 = { 313 0 stevel T_INFO_ACK, 314 0 stevel UDP_MAXPACKET_IPV4, /* TSDU_size. Excl. headers */ 315 0 stevel T_INVALID, /* ETSU_size. udp does not support expedited data. */ 316 0 stevel T_INVALID, /* CDATA_size. udp does not support connect data. */ 317 0 stevel T_INVALID, /* DDATA_size. udp does not support disconnect data. */ 318 0 stevel sizeof (sin_t), /* ADDR_size. */ 319 0 stevel 0, /* OPT_size - not initialized here */ 320 0 stevel UDP_MAXPACKET_IPV4, /* TIDU_size. Excl. headers */ 321 0 stevel T_CLTS, /* SERV_type. udp supports connection-less. */ 322 0 stevel TS_UNBND, /* CURRENT_state. This is set from udp_state. */ 323 0 stevel (XPG4_1|SENDZERO) /* PROVIDER_flag */ 324 0 stevel }; 325 0 stevel 326 741 masputra #define UDP_MAXPACKET_IPV6 (IP_MAXPACKET - UDPH_SIZE - IPV6_HDR_LEN) 327 741 masputra 328 0 stevel static struct T_info_ack udp_g_t_info_ack_ipv6 = { 329 0 stevel T_INFO_ACK, 330 0 stevel UDP_MAXPACKET_IPV6, /* TSDU_size. Excl. headers */ 331 0 stevel T_INVALID, /* ETSU_size. udp does not support expedited data. */ 332 0 stevel T_INVALID, /* CDATA_size. udp does not support connect data. */ 333 0 stevel T_INVALID, /* DDATA_size. udp does not support disconnect data. */ 334 0 stevel sizeof (sin6_t), /* ADDR_size. */ 335 0 stevel 0, /* OPT_size - not initialized here */ 336 0 stevel UDP_MAXPACKET_IPV6, /* TIDU_size. Excl. headers */ 337 0 stevel T_CLTS, /* SERV_type. udp supports connection-less. */ 338 0 stevel TS_UNBND, /* CURRENT_state. This is set from udp_state. */ 339 0 stevel (XPG4_1|SENDZERO) /* PROVIDER_flag */ 340 0 stevel }; 341 0 stevel 342 0 stevel /* largest UDP port number */ 343 0 stevel #define UDP_MAX_PORT 65535 344 0 stevel 345 0 stevel /* 346 3448 dh155122 * Table of ND variables supported by udp. These are loaded into us_nd 347 0 stevel * in udp_open. 348 0 stevel * All of these are alterable, within the min/max values given, at run time. 349 0 stevel */ 350 741 masputra /* BEGIN CSTYLED */ 351 741 masputra udpparam_t udp_param_arr[] = { 352 741 masputra /*min max value name */ 353 741 masputra { 0L, 256, 32, "udp_wroff_extra" }, 354 741 masputra { 1L, 255, 255, "udp_ipv4_ttl" }, 355 741 masputra { 0, IPV6_MAX_HOPS, IPV6_DEFAULT_HOPS, "udp_ipv6_hoplimit"}, 356 741 masputra { 1024, (32 * 1024), 1024, "udp_smallest_nonpriv_port" }, 357 741 masputra { 0, 1, 1, "udp_do_checksum" }, 358 741 masputra { 1024, UDP_MAX_PORT, (32 * 1024), "udp_smallest_anon_port" }, 359 741 masputra { 1024, UDP_MAX_PORT, UDP_MAX_PORT, "udp_largest_anon_port" }, 360 741 masputra { UDP_XMIT_LOWATER, (1<<30), UDP_XMIT_HIWATER, "udp_xmit_hiwat"}, 361 741 masputra { 0, (1<<30), UDP_XMIT_LOWATER, "udp_xmit_lowat"}, 362 741 masputra { UDP_RECV_LOWATER, (1<<30), UDP_RECV_HIWATER, "udp_recv_hiwat"}, 363 741 masputra { 65536, (1<<30), 2*1024*1024, "udp_max_buf"}, 364 11042 Erik { 0, 1, 0, "udp_pmtu_discovery" }, 365 11042 Erik { 0, 1, 0, "udp_sendto_ignerr" }, 366 741 masputra }; 367 741 masputra /* END CSTYLED */ 368 0 stevel 369 3448 dh155122 /* Setable in /etc/system */ 370 0 stevel /* If set to 0, pick ephemeral port sequentially; otherwise randomly. */ 371 0 stevel uint32_t udp_random_anon_port = 1; 372 0 stevel 373 0 stevel /* 374 0 stevel * Hook functions to enable cluster networking. 375 0 stevel * On non-clustered systems these vectors must always be NULL 376 0 stevel */ 377 0 stevel 378 8392 Huafeng void (*cl_inet_bind)(netstackid_t stack_id, uchar_t protocol, 379 8392 Huafeng sa_family_t addr_family, uint8_t *laddrp, in_port_t lport, 380 8392 Huafeng void *args) = NULL; 381 8392 Huafeng void (*cl_inet_unbind)(netstackid_t stack_id, uint8_t protocol, 382 8392 Huafeng sa_family_t addr_family, uint8_t *laddrp, in_port_t lport, 383 8392 Huafeng void *args) = NULL; 384 741 masputra 385 741 masputra typedef union T_primitives *t_primp_t; 386 741 masputra 387 0 stevel /* 388 1676 jpk * Return the next anonymous port in the privileged port range for 389 0 stevel * bind checking. 390 1676 jpk * 391 1676 jpk * Trusted Extension (TX) notes: TX allows administrator to mark or 392 1676 jpk * reserve ports as Multilevel ports (MLP). MLP has special function 393 1676 jpk * on TX systems. Once a port is made MLP, it's not available as 394 1676 jpk * ordinary port. This creates "holes" in the port name space. It 395 1676 jpk * may be necessary to skip the "holes" find a suitable anon port. 396 0 stevel */ 397 0 stevel static in_port_t 398 1676 jpk udp_get_next_priv_port(udp_t *udp) 399 0 stevel { 400 0 stevel static in_port_t next_priv_port = IPPORT_RESERVED - 1; 401 1676 jpk in_port_t nextport; 402 1676 jpk boolean_t restart = B_FALSE; 403 3448 dh155122 udp_stack_t *us = udp->udp_us; 404 1676 jpk 405 1676 jpk retry: 406 3448 dh155122 if (next_priv_port < us->us_min_anonpriv_port || 407 1676 jpk next_priv_port >= IPPORT_RESERVED) { 408 0 stevel next_priv_port = IPPORT_RESERVED - 1; 409 1676 jpk if (restart) 410 1676 jpk return (0); 411 1676 jpk restart = B_TRUE; 412 1676 jpk } 413 1676 jpk 414 1676 jpk if (is_system_labeled() && 415 1676 jpk (nextport = tsol_next_port(crgetzone(udp->udp_connp->conn_cred), 416 1676 jpk next_priv_port, IPPROTO_UDP, B_FALSE)) != 0) { 417 1676 jpk next_priv_port = nextport; 418 1676 jpk goto retry; 419 1676 jpk } 420 1676 jpk 421 0 stevel return (next_priv_port--); 422 0 stevel } 423 0 stevel 424 0 stevel /* 425 0 stevel * Hash list removal routine for udp_t structures. 426 0 stevel */ 427 0 stevel static void 428 0 stevel udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock) 429 0 stevel { 430 11042 Erik udp_t *udpnext; 431 11042 Erik kmutex_t *lockp; 432 11042 Erik udp_stack_t *us = udp->udp_us; 433 11042 Erik conn_t *connp = udp->udp_connp; 434 0 stevel 435 0 stevel if (udp->udp_ptpbhn == NULL) 436 0 stevel return; 437 0 stevel 438 0 stevel /* 439 0 stevel * Extract the lock pointer in case there are concurrent 440 0 stevel * hash_remove's for this instance. 441 0 stevel */ 442 11042 Erik ASSERT(connp->conn_lport != 0); 443 0 stevel if (!caller_holds_lock) { 444 11042 Erik lockp = &us->us_bind_fanout[UDP_BIND_HASH(connp->conn_lport, 445 4987 danmcd us->us_bind_fanout_size)].uf_lock; 446 0 stevel ASSERT(lockp != NULL); 447 0 stevel mutex_enter(lockp); 448 0 stevel } 449 0 stevel if (udp->udp_ptpbhn != NULL) { 450 0 stevel udpnext = udp->udp_bind_hash; 451 0 stevel if (udpnext != NULL) { 452 0 stevel udpnext->udp_ptpbhn = udp->udp_ptpbhn; 453 0 stevel udp->udp_bind_hash = NULL; 454 0 stevel } 455 0 stevel *udp->udp_ptpbhn = udpnext; 456 0 stevel udp->udp_ptpbhn = NULL; 457 0 stevel } 458 0 stevel if (!caller_holds_lock) { 459 0 stevel mutex_exit(lockp); 460 0 stevel } 461 0 stevel } 462 0 stevel 463 0 stevel static void 464 0 stevel udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp) 465 0 stevel { 466 11042 Erik conn_t *connp = udp->udp_connp; 467 0 stevel udp_t **udpp; 468 0 stevel udp_t *udpnext; 469 11042 Erik conn_t *connext; 470 0 stevel 471 0 stevel ASSERT(MUTEX_HELD(&uf->uf_lock)); 472 5240 nordmark ASSERT(udp->udp_ptpbhn == NULL); 473 0 stevel udpp = &uf->uf_udp; 474 0 stevel udpnext = udpp[0]; 475 0 stevel if (udpnext != NULL) { 476 0 stevel /* 477 0 stevel * If the new udp bound to the INADDR_ANY address 478 0 stevel * and the first one in the list is not bound to 479 0 stevel * INADDR_ANY we skip all entries until we find the 480 0 stevel * first one bound to INADDR_ANY. 481 0 stevel * This makes sure that applications binding to a 482 0 stevel * specific address get preference over those binding to 483 0 stevel * INADDR_ANY. 484 0 stevel */ 485 11042 Erik connext = udpnext->udp_connp; 486 11042 Erik if (V6_OR_V4_INADDR_ANY(connp->conn_bound_addr_v6) && 487 11042 Erik !V6_OR_V4_INADDR_ANY(connext->conn_bound_addr_v6)) { 488 0 stevel while ((udpnext = udpp[0]) != NULL && 489 11042 Erik !V6_OR_V4_INADDR_ANY(connext->conn_bound_addr_v6)) { 490 0 stevel udpp = &(udpnext->udp_bind_hash); 491 0 stevel } 492 0 stevel if (udpnext != NULL) 493 0 stevel udpnext->udp_ptpbhn = &udp->udp_bind_hash; 494 0 stevel } else { 495 0 stevel udpnext->udp_ptpbhn = &udp->udp_bind_hash; 496 0 stevel } 497 0 stevel } 498 0 stevel udp->udp_bind_hash = udpnext; 499 0 stevel udp->udp_ptpbhn = udpp; 500 0 stevel udpp[0] = udp; 501 0 stevel } 502 0 stevel 503 0 stevel /* 504 0 stevel * This routine is called to handle each O_T_BIND_REQ/T_BIND_REQ message 505 0 stevel * passed to udp_wput. 506 0 stevel * It associates a port number and local address with the stream. 507 11042 Erik * It calls IP to verify the local IP address, and calls IP to insert 508 11042 Erik * the conn_t in the fanout table. 509 11042 Erik * If everything is ok it then sends the T_BIND_ACK back up. 510 0 stevel * 511 0 stevel * Note that UDP over IPv4 and IPv6 sockets can use the same port number 512 0 stevel * without setting SO_REUSEADDR. This is needed so that they 513 0 stevel * can be viewed as two independent transport protocols. 514 0 stevel * However, anonymouns ports are allocated from the same range to avoid 515 3448 dh155122 * duplicating the us->us_next_port_to_try. 516 0 stevel */ 517 0 stevel static void 518 8348 Eric udp_tpi_bind(queue_t *q, mblk_t *mp) 519 0 stevel { 520 0 stevel sin_t *sin; 521 0 stevel sin6_t *sin6; 522 0 stevel mblk_t *mp1; 523 0 stevel struct T_bind_req *tbr; 524 741 masputra conn_t *connp; 525 741 masputra udp_t *udp; 526 8348 Eric int error; 527 8348 Eric struct sockaddr *sa; 528 8778 Erik cred_t *cr; 529 8778 Erik 530 8778 Erik /* 531 8778 Erik * All Solaris components should pass a db_credp 532 8778 Erik * for this TPI message, hence we ASSERT. 533 8778 Erik * But in case there is some other M_PROTO that looks 534 8778 Erik * like a TPI message sent by some other kernel 535 8778 Erik * component, we check and return an error. 536 8778 Erik */ 537 8778 Erik cr = msg_getcred(mp, NULL); 538 8778 Erik ASSERT(cr != NULL); 539 8778 Erik if (cr == NULL) { 540 8778 Erik udp_err_ack(q, mp, TSYSERR, EINVAL); 541 8778 Erik return; 542 8778 Erik } 543 741 masputra 544 741 masputra connp = Q_TO_CONN(q); 545 741 masputra udp = connp->conn_udp; 546 0 stevel if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) { 547 0 stevel (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 548 0 stevel "udp_bind: bad req, len %u", 549 0 stevel (uint_t)(mp->b_wptr - mp->b_rptr)); 550 0 stevel udp_err_ack(q, mp, TPROTO, 0); 551 0 stevel return; 552 0 stevel } 553 0 stevel if (udp->udp_state != TS_UNBND) { 554 0 stevel (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 555 0 stevel "udp_bind: bad state, %u", udp->udp_state); 556 0 stevel udp_err_ack(q, mp, TOUTSTATE, 0); 557 0 stevel return; 558 0 stevel } 559 0 stevel /* 560 0 stevel * Reallocate the message to make sure we have enough room for an 561 11042 Erik * address. 562 11042 Erik */ 563 11042 Erik mp1 = reallocb(mp, sizeof (struct T_bind_ack) + sizeof (sin6_t), 1); 564 11042 Erik if (mp1 == NULL) { 565 0 stevel udp_err_ack(q, mp, TSYSERR, ENOMEM); 566 0 stevel return; 567 0 stevel } 568 0 stevel 569 0 stevel mp = mp1; 570 8348 Eric 571 8348 Eric /* Reset the message type in preparation for shipping it back. */ 572 8348 Eric DB_TYPE(mp) = M_PCPROTO; 573 8348 Eric 574 0 stevel tbr = (struct T_bind_req *)mp->b_rptr; 575 0 stevel switch (tbr->ADDR_length) { 576 0 stevel case 0: /* Request for a generic port */ 577 0 stevel tbr->ADDR_offset = sizeof (struct T_bind_req); 578 11042 Erik if (connp->conn_family == AF_INET) { 579 0 stevel tbr->ADDR_length = sizeof (sin_t); 580 0 stevel sin = (sin_t *)&tbr[1]; 581 0 stevel *sin = sin_null; 582 0 stevel sin->sin_family = AF_INET; 583 0 stevel mp->b_wptr = (uchar_t *)&sin[1]; 584 8348 Eric sa = (struct sockaddr *)sin; 585 0 stevel } else { 586 11042 Erik ASSERT(connp->conn_family == AF_INET6); 587 0 stevel tbr->ADDR_length = sizeof (sin6_t); 588 0 stevel sin6 = (sin6_t *)&tbr[1]; 589 0 stevel *sin6 = sin6_null; 590 0 stevel sin6->sin6_family = AF_INET6; 591 0 stevel mp->b_wptr = (uchar_t *)&sin6[1]; 592 8348 Eric sa = (struct sockaddr *)sin6; 593 8348 Eric } 594 0 stevel break; 595 0 stevel 596 0 stevel case sizeof (sin_t): /* Complete IPv4 address */ 597 8348 Eric sa = (struct sockaddr *)mi_offset_param(mp, tbr->ADDR_offset, 598 0 stevel sizeof (sin_t)); 599 8348 Eric if (sa == NULL || !OK_32PTR((char *)sa)) { 600 0 stevel udp_err_ack(q, mp, TSYSERR, EINVAL); 601 0 stevel return; 602 0 stevel } 603 11042 Erik if (connp->conn_family != AF_INET || 604 8348 Eric sa->sa_family != AF_INET) { 605 0 stevel udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 606 0 stevel return; 607 0 stevel } 608 0 stevel break; 609 0 stevel 610 0 stevel case sizeof (sin6_t): /* complete IPv6 address */ 611 8348 Eric sa = (struct sockaddr *)mi_offset_param(mp, tbr->ADDR_offset, 612 0 stevel sizeof (sin6_t)); 613 8348 Eric if (sa == NULL || !OK_32PTR((char *)sa)) { 614 0 stevel udp_err_ack(q, mp, TSYSERR, EINVAL); 615 0 stevel return; 616 0 stevel } 617 11042 Erik if (connp->conn_family != AF_INET6 || 618 8348 Eric sa->sa_family != AF_INET6) { 619 0 stevel udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 620 0 stevel return; 621 0 stevel } 622 0 stevel break; 623 0 stevel 624 0 stevel default: /* Invalid request */ 625 0 stevel (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 626 0 stevel "udp_bind: bad ADDR_length length %u", tbr->ADDR_length); 627 0 stevel udp_err_ack(q, mp, TBADADDR, 0); 628 0 stevel return; 629 0 stevel } 630 0 stevel 631 8348 Eric error = udp_do_bind(connp, sa, tbr->ADDR_length, cr, 632 8348 Eric tbr->PRIM_type != O_T_BIND_REQ); 633 8348 Eric 634 8348 Eric if (error != 0) { 635 8348 Eric if (error > 0) { 636 0 stevel udp_err_ack(q, mp, TSYSERR, error); 637 8348 Eric } else { 638 8348 Eric udp_err_ack(q, mp, -error, 0); 639 8348 Eric } 640 8348 Eric } else { 641 8348 Eric tbr->PRIM_type = T_BIND_ACK; 642 8348 Eric qreply(q, mp); 643 8348 Eric } 644 0 stevel } 645 0 stevel 646 0 stevel /* 647 0 stevel * This routine handles each T_CONN_REQ message passed to udp. It 648 0 stevel * associates a default destination address with the stream. 649 0 stevel * 650 11042 Erik * After various error checks are completed, udp_connect() lays 651 11042 Erik * the target address and port into the composite header template. 652 11042 Erik * Then we ask IP for information, including a source address if we didn't 653 11042 Erik * already have one. Finally we send up the T_OK_ACK reply message. 654 0 stevel */ 655 0 stevel static void 656 8348 Eric udp_tpi_connect(queue_t *q, mblk_t *mp) 657 8348 Eric { 658 8348 Eric conn_t *connp = Q_TO_CONN(q); 659 8348 Eric int error; 660 8348 Eric socklen_t len; 661 8348 Eric struct sockaddr *sa; 662 0 stevel struct T_conn_req *tcr; 663 8778 Erik cred_t *cr; 664 11042 Erik pid_t pid; 665 8778 Erik /* 666 8778 Erik * All Solaris components should pass a db_credp 667 8778 Erik * for this TPI message, hence we ASSERT. 668 8778 Erik * But in case there is some other M_PROTO that looks 669 8778 Erik * like a TPI message sent by some other kernel 670 8778 Erik * component, we check and return an error. 671 8778 Erik */ 672 11042 Erik cr = msg_getcred(mp, &pid); 673 8778 Erik ASSERT(cr != NULL); 674 8778 Erik if (cr == NULL) { 675 8778 Erik udp_err_ack(q, mp, TSYSERR, EINVAL); 676 8778 Erik return; 677 8778 Erik } 678 5240 nordmark 679 0 stevel tcr = (struct T_conn_req *)mp->b_rptr; 680 0 stevel 681 0 stevel /* A bit of sanity checking */ 682 0 stevel if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_req)) { 683 0 stevel udp_err_ack(q, mp, TPROTO, 0); 684 0 stevel return; 685 0 stevel } 686 0 stevel 687 0 stevel if (tcr->OPT_length != 0) { 688 0 stevel udp_err_ack(q, mp, TBADOPT, 0); 689 0 stevel return; 690 0 stevel } 691 0 stevel 692 0 stevel /* 693 0 stevel * Determine packet type based on type of address passed in 694 0 stevel * the request should contain an IPv4 or IPv6 address. 695 0 stevel * Make sure that address family matches the type of 696 11042 Erik * family of the address passed down. 697 0 stevel */ 698 8348 Eric len = tcr->DEST_length; 699 0 stevel switch (tcr->DEST_length) { 700 0 stevel default: 701 0 stevel udp_err_ack(q, mp, TBADADDR, 0); 702 0 stevel return; 703 0 stevel 704 0 stevel case sizeof (sin_t): 705 8348 Eric sa = (struct sockaddr *)mi_offset_param(mp, tcr->DEST_offset, 706 0 stevel sizeof (sin_t)); 707 0 stevel break; 708 0 stevel 709 0 stevel case sizeof (sin6_t): 710 8348 Eric sa = (struct sockaddr *)mi_offset_param(mp, tcr->DEST_offset, 711 0 stevel sizeof (sin6_t)); 712 8348 Eric break; 713 8348 Eric } 714 8348 Eric 715 11042 Erik error = proto_verify_ip_addr(connp->conn_family, sa, len); 716 8348 Eric if (error != 0) { 717 8348 Eric udp_err_ack(q, mp, TSYSERR, error); 718 8348 Eric return; 719 8348 Eric } 720 8348 Eric 721 11042 Erik error = udp_do_connect(connp, sa, len, cr, pid); 722 8348 Eric if (error != 0) { 723 8348 Eric if (error < 0) 724 8348 Eric udp_err_ack(q, mp, -error, 0); 725 8348 Eric else 726 8348 Eric udp_err_ack(q, mp, TSYSERR, error); 727 8348 Eric } else { 728 9142 Rao mblk_t *mp1; 729 9142 Rao /* 730 9142 Rao * We have to send a connection confirmation to 731 9142 Rao * keep TLI happy. 732 9142 Rao */ 733 11042 Erik if (connp->conn_family == AF_INET) { 734 9142 Rao mp1 = mi_tpi_conn_con(NULL, (char *)sa, 735 9142 Rao sizeof (sin_t), NULL, 0); 736 9142 Rao } else { 737 9142 Rao mp1 = mi_tpi_conn_con(NULL, (char *)sa, 738 9142 Rao sizeof (sin6_t), NULL, 0); 739 9142 Rao } 740 9142 Rao if (mp1 == NULL) { 741 9142 Rao udp_err_ack(q, mp, TSYSERR, ENOMEM); 742 9142 Rao return; 743 9142 Rao } 744 9142 Rao 745 9142 Rao /* 746 9142 Rao * Send ok_ack for T_CONN_REQ 747 9142 Rao */ 748 8873 Rao mp = mi_tpi_ok_ack_alloc(mp); 749 9142 Rao if (mp == NULL) { 750 9142 Rao /* Unable to reuse the T_CONN_REQ for the ack. */ 751 9142 Rao udp_err_ack_prim(q, mp1, T_CONN_REQ, TSYSERR, ENOMEM); 752 9142 Rao return; 753 9142 Rao } 754 9142 Rao 755 8348 Eric putnext(connp->conn_rq, mp); 756 8348 Eric putnext(connp->conn_rq, mp1); 757 8348 Eric } 758 8348 Eric } 759 8348 Eric 760 8348 Eric static int 761 8348 Eric udp_tpi_close(queue_t *q, int flags) 762 8348 Eric { 763 8348 Eric conn_t *connp; 764 8348 Eric 765 8348 Eric if (flags & SO_FALLBACK) { 766 8348 Eric /* 767 8348 Eric * stream is being closed while in fallback 768 8348 Eric * simply free the resources that were allocated 769 8348 Eric */ 770 8348 Eric inet_minor_free(WR(q)->q_ptr, (dev_t)(RD(q)->q_ptr)); 771 8348 Eric qprocsoff(q); 772 8348 Eric goto done; 773 8348 Eric } 774 8348 Eric 775 8348 Eric connp = Q_TO_CONN(q); 776 8348 Eric udp_do_close(connp); 777 8348 Eric done: 778 5240 nordmark q->q_ptr = WR(q)->q_ptr = NULL; 779 5240 nordmark return (0); 780 5240 nordmark } 781 5240 nordmark 782 11042 Erik static void 783 741 masputra udp_close_free(conn_t *connp) 784 741 masputra { 785 741 masputra udp_t *udp = connp->conn_udp; 786 741 masputra 787 0 stevel /* If there are any options associated with the stream, free them. */ 788 11042 Erik if (udp->udp_recv_ipp.ipp_fields != 0) 789 11042 Erik ip_pkt_free(&udp->udp_recv_ipp); 790 5330 nordmark 791 5330 nordmark /* 792 5330 nordmark * Clear any fields which the kmem_cache constructor clears. 793 5330 nordmark * Only udp_connp needs to be preserved. 794 5330 nordmark * TBD: We should make this more efficient to avoid clearing 795 5330 nordmark * everything. 796 5330 nordmark */ 797 5330 nordmark ASSERT(udp->udp_connp == connp); 798 5330 nordmark bzero(udp, sizeof (udp_t)); 799 5330 nordmark udp->udp_connp = connp; 800 0 stevel } 801 0 stevel 802 8348 Eric static int 803 8348 Eric udp_do_disconnect(conn_t *connp) 804 0 stevel { 805 5240 nordmark udp_t *udp; 806 0 stevel udp_fanout_t *udpf; 807 3448 dh155122 udp_stack_t *us; 808 8348 Eric int error; 809 5240 nordmark 810 5240 nordmark udp = connp->conn_udp; 811 3448 dh155122 us = udp->udp_us; 812 11042 Erik mutex_enter(&connp->conn_lock); 813 11042 Erik if (udp->udp_state != TS_DATA_XFER) { 814 11042 Erik mutex_exit(&connp->conn_lock); 815 8348 Eric return (-TOUTSTATE); 816 0 stevel } 817 11042 Erik udpf = &us->us_bind_fanout[UDP_BIND_HASH(connp->conn_lport, 818 3448 dh155122 us->us_bind_fanout_size)]; 819 0 stevel mutex_enter(&udpf->uf_lock); 820 11042 Erik if (connp->conn_mcbc_bind) 821 11042 Erik connp->conn_saddr_v6 = ipv6_all_zeros; 822 11042 Erik else 823 11042 Erik connp->conn_saddr_v6 = connp->conn_bound_addr_v6; 824 11042 Erik connp->conn_laddr_v6 = connp->conn_bound_addr_v6; 825 11042 Erik connp->conn_faddr_v6 = ipv6_all_zeros; 826 11042 Erik connp->conn_fport = 0; 827 0 stevel udp->udp_state = TS_IDLE; 828 0 stevel mutex_exit(&udpf->uf_lock); 829 0 stevel 830 11042 Erik /* Remove any remnants of mapped address binding */ 831 11042 Erik if (connp->conn_family == AF_INET6) 832 11042 Erik connp->conn_ipversion = IPV6_VERSION; 833 11042 Erik 834 11042 Erik connp->conn_v6lastdst = ipv6_all_zeros; 835 11042 Erik error = udp_build_hdr_template(connp, &connp->conn_saddr_v6, 836 11042 Erik &connp->conn_faddr_v6, connp->conn_fport, connp->conn_flowinfo); 837 11042 Erik mutex_exit(&connp->conn_lock); 838 11042 Erik if (error != 0) 839 11042 Erik return (error); 840 11042 Erik 841 11042 Erik /* 842 11042 Erik * Tell IP to remove the full binding and revert 843 11042 Erik * to the local address binding. 844 11042 Erik */ 845 11042 Erik return (ip_laddr_fanout_insert(connp)); 846 11042 Erik } 847 8348 Eric 848 8348 Eric static void 849 8348 Eric udp_tpi_disconnect(queue_t *q, mblk_t *mp) 850 8348 Eric { 851 8348 Eric conn_t *connp = Q_TO_CONN(q); 852 8348 Eric int error; 853 8348 Eric 854 8348 Eric /* 855 8348 Eric * Allocate the largest primitive we need to send back 856 8348 Eric * T_error_ack is > than T_ok_ack 857 8348 Eric */ 858 8348 Eric mp = reallocb(mp, sizeof (struct T_error_ack), 1); 859 8348 Eric if (mp == NULL) { 860 8348 Eric /* Unable to reuse the T_DISCON_REQ for the ack. */ 861 8348 Eric udp_err_ack_prim(q, mp, T_DISCON_REQ, TSYSERR, ENOMEM); 862 8348 Eric return; 863 8348 Eric } 864 8348 Eric 865 8348 Eric error = udp_do_disconnect(connp); 866 8348 Eric 867 8348 Eric if (error != 0) { 868 8348 Eric if (error < 0) { 869 8348 Eric udp_err_ack(q, mp, -error, 0); 870 8348 Eric } else { 871 8348 Eric udp_err_ack(q, mp, TSYSERR, error); 872 8348 Eric } 873 8348 Eric } else { 874 8348 Eric mp = mi_tpi_ok_ack_alloc(mp); 875 8348 Eric ASSERT(mp != NULL); 876 8348 Eric qreply(q, mp); 877 8348 Eric } 878 8348 Eric } 879 8348 Eric 880 8348 Eric int 881 8348 Eric udp_disconnect(conn_t *connp) 882 8348 Eric { 883 8348 Eric int error; 884 11042 Erik 885 11042 Erik connp->conn_dgram_errind = B_FALSE; 886 8348 Eric error = udp_do_disconnect(connp); 887 8348 Eric if (error < 0) 888 8348 Eric error = proto_tlitosyserr(-error); 889 8348 Eric 890 8348 Eric return (error); 891 0 stevel } 892 0 stevel 893 0 stevel /* This routine creates a T_ERROR_ACK message and passes it upstream. */ 894 0 stevel static void 895 0 stevel udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, int sys_error) 896 0 stevel { 897 0 stevel if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL) 898 5240 nordmark qreply(q, mp); 899 0 stevel } 900 0 stevel 901 0 stevel /* Shorthand to generate and send TPI error acks to our client */ 902 0 stevel static void 903 11042 Erik udp_err_ack_prim(queue_t *q, mblk_t *mp, t_scalar_t primitive, 904 11042 Erik t_scalar_t t_error, int sys_error) 905 0 stevel { 906 0 stevel struct T_error_ack *teackp; 907 0 stevel 908 0 stevel if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack), 909 0 stevel M_PCPROTO, T_ERROR_ACK)) != NULL) { 910 0 stevel teackp = (struct T_error_ack *)mp->b_rptr; 911 0 stevel teackp->ERROR_prim = primitive; 912 0 stevel teackp->TLI_error = t_error; 913 0 stevel teackp->UNIX_error = sys_error; 914 5240 nordmark qreply(q, mp); 915 0 stevel } 916 0 stevel } 917 0 stevel 918 11042 Erik /*ARGSUSED2*/ 919 0 stevel static int 920 0 stevel udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 921 0 stevel { 922 0 stevel int i; 923 3448 dh155122 udp_t *udp = Q_TO_UDP(q); 924 3448 dh155122 udp_stack_t *us = udp->udp_us; 925 3448 dh155122 926 3448 dh155122 for (i = 0; i < us->us_num_epriv_ports; i++) { 927 3448 dh155122 if (us->us_epriv_ports[i] != 0) 928 3448 dh155122 (void) mi_mpprintf(mp, "%d ", us->us_epriv_ports[i]); 929 0 stevel } 930 0 stevel return (0); 931 0 stevel } 932 0 stevel 933 11042 Erik /* ARGSUSED1 */ 934 0 stevel static int 935 0 stevel udp_extra_priv_ports_add(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 936 0 stevel cred_t *cr) 937 0 stevel { 938 0 stevel long new_value; 939 0 stevel int i; 940 3448 dh155122 udp_t *udp = Q_TO_UDP(q); 941 3448 dh155122 udp_stack_t *us = udp->udp_us; 942 0 stevel 943 0 stevel /* 944 0 stevel * Fail the request if the new value does not lie within the 945 0 stevel * port number limits. 946 0 stevel */ 947 0 stevel if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 948 0 stevel new_value <= 0 || new_value >= 65536) { 949 0 stevel return (EINVAL); 950 0 stevel } 951 0 stevel 952 0 stevel /* Check if the value is already in the list */ 953 3448 dh155122 for (i = 0; i < us->us_num_epriv_ports; i++) { 954 3448 dh155122 if (new_value == us->us_epriv_ports[i]) { 955 0 stevel return (EEXIST); 956 0 stevel } 957 0 stevel } 958 0 stevel /* Find an empty slot */ 959 3448 dh155122 for (i = 0; i < us->us_num_epriv_ports; i++) { 960 3448 dh155122 if (us->us_epriv_ports[i] == 0) 961 3448 dh155122 break; 962 3448 dh155122 } 963 3448 dh155122 if (i == us->us_num_epriv_ports) { 964 0 stevel return (EOVERFLOW); 965 0 stevel } 966 0 stevel 967 0 stevel /* Set the new value */ 968 3448 dh155122 us->us_epriv_ports[i] = (in_port_t)new_value; 969 741 masputra return (0); 970 741 masputra } 971 741 masputra 972 11042 Erik /* ARGSUSED1 */ 973 0 stevel static int 974 0 stevel udp_extra_priv_ports_del(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 975 0 stevel cred_t *cr) 976 0 stevel { 977 0 stevel long new_value; 978 0 stevel int i; 979 3448 dh155122 udp_t *udp = Q_TO_UDP(q); 980 3448 dh155122 udp_stack_t *us = udp->udp_us; 981 0 stevel 982 0 stevel /* 983 0 stevel * Fail the request if the new value does not lie within the 984 0 stevel * port number limits. 985 0 stevel */ 986 0 stevel if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 987 0 stevel new_value <= 0 || new_value >= 65536) { 988 0 stevel return (EINVAL); 989 0 stevel } 990 0 stevel 991 0 stevel /* Check that the value is already in the list */ 992 3448 dh155122 for (i = 0; i < us->us_num_epriv_ports; i++) { 993 3448 dh155122 if (us->us_epriv_ports[i] == new_value) 994 3448 dh155122 break; 995 3448 dh155122 } 996 3448 dh155122 if (i == us->us_num_epriv_ports) { 997 0 stevel return (ESRCH); 998 0 stevel } 999 0 stevel 1000 0 stevel /* Clear the value */ 1001 3448 dh155122 us->us_epriv_ports[i] = 0; 1002 0 stevel return (0); 1003 0 stevel } 1004 0 stevel 1005 0 stevel /* At minimum we need 4 bytes of UDP header */ 1006 0 stevel #define ICMP_MIN_UDP_HDR 4 1007 0 stevel 1008 0 stevel /* 1009 11042 Erik * udp_icmp_input is called as conn_recvicmp to process ICMP messages. 1010 0 stevel * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors. 1011 0 stevel * Assumes that IP has pulled up everything up to and including the ICMP header. 1012 0 stevel */ 1013 11042 Erik /* ARGSUSED2 */ 1014 11042 Erik static void 1015 11042 Erik udp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 1016 11042 Erik { 1017 11042 Erik conn_t *connp = (conn_t *)arg1; 1018 11042 Erik icmph_t *icmph; 1019 11042 Erik ipha_t *ipha; 1020 11042 Erik int iph_hdr_length; 1021 11042 Erik udpha_t *udpha; 1022 11042 Erik sin_t sin; 1023 11042 Erik sin6_t sin6; 1024 11042 Erik mblk_t *mp1; 1025 11042 Erik int error = 0; 1026 11042 Erik udp_t *udp = connp->conn_udp; 1027 11042 Erik 1028 0 stevel ipha = (ipha_t *)mp->b_rptr; 1029 5240 nordmark 1030 5240 nordmark ASSERT(OK_32PTR(mp->b_rptr)); 1031 5240 nordmark 1032 5240 nordmark if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) { 1033 5240 nordmark ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION); 1034 11042 Erik udp_icmp_error_ipv6(connp, mp, ira); 1035 0 stevel return; 1036 5240 nordmark } 1037 5240 nordmark ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 1038 0 stevel 1039 0 stevel /* Skip past the outer IP and ICMP headers */ 1040 11042 Erik ASSERT(IPH_HDR_LENGTH(ipha) == ira->ira_ip_hdr_length); 1041 11042 Erik iph_hdr_length = ira->ira_ip_hdr_length; 1042 0 stevel icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 1043 11042 Erik ipha = (ipha_t *)&icmph[1]; /* Inner IP header */ 1044 0 stevel 1045 0 stevel /* Skip past the inner IP and find the ULP header */ 1046 0 stevel iph_hdr_length = IPH_HDR_LENGTH(ipha); 1047 0 stevel udpha = (udpha_t *)((char *)ipha + iph_hdr_length); 1048 0 stevel 1049 0 stevel switch (icmph->icmph_type) { 1050 0 stevel case ICMP_DEST_UNREACHABLE: 1051 0 stevel switch (icmph->icmph_code) { 1052 11042 Erik case ICMP_FRAGMENTATION_NEEDED: { 1053 11042 Erik ipha_t *ipha; 1054 11042 Erik ip_xmit_attr_t *ixa; 1055 0 stevel /* 1056 0 stevel * IP has already adjusted the path MTU. 1057 11042 Erik * But we need to adjust DF for IPv4. 1058 11042 Erik */ 1059 11042 Erik if (connp->conn_ipversion != IPV4_VERSION) 1060 11042 Erik break; 1061 11042 Erik 1062 11042 Erik ixa = conn_get_ixa(connp, B_FALSE); 1063 11042 Erik if (ixa == NULL || ixa->ixa_ire == NULL) { 1064 11042 Erik /* 1065 11042 Erik * Some other thread holds conn_ixa. We will 1066 11042 Erik * redo this on the next ICMP too big. 1067 11042 Erik */ 1068 11042 Erik if (ixa != NULL) 1069 11042 Erik ixa_refrele(ixa); 1070 11042 Erik break; 1071 11042 Erik } 1072 11042 Erik (void) ip_get_pmtu(ixa); 1073 11042 Erik 1074 11042 Erik mutex_enter(&connp->conn_lock); 1075 11042 Erik ipha = (ipha_t *)connp->conn_ht_iphc; 1076 11042 Erik if (ixa->ixa_flags & IXAF_PMTU_IPV4_DF) { 1077 11042 Erik ipha->ipha_fragment_offset_and_flags |= 1078 11042 Erik IPH_DF_HTONS; 1079 11042 Erik } else { 1080 11042 Erik ipha->ipha_fragment_offset_and_flags &= 1081 11042 Erik ~IPH_DF_HTONS; 1082 11042 Erik } 1083 11042 Erik mutex_exit(&connp->conn_lock); 1084 11042 Erik ixa_refrele(ixa); 1085 11042 Erik break; 1086 11042 Erik } 1087 0 stevel case ICMP_PORT_UNREACHABLE: 1088 0 stevel case ICMP_PROTOCOL_UNREACHABLE: 1089 0 stevel error = ECONNREFUSED; 1090 0 stevel break; 1091 0 stevel default: 1092 0 stevel /* Transient errors */ 1093 0 stevel break; 1094 0 stevel } 1095 0 stevel break; 1096 0 stevel default: 1097 0 stevel /* Transient errors */ 1098 0 stevel break; 1099 0 stevel } 1100 0 stevel if (error == 0) { 1101 5240 nordmark freemsg(mp); 1102 5240 nordmark return; 1103 5240 nordmark } 1104 5240 nordmark 1105 5240 nordmark /* 1106 5240 nordmark * Deliver T_UDERROR_IND when the application has asked for it. 1107 5240 nordmark * The socket layer enables this automatically when connected. 1108 5240 nordmark */ 1109 11042 Erik if (!connp->conn_dgram_errind) { 1110 11042 Erik freemsg(mp); 1111 11042 Erik return; 1112 11042 Erik } 1113 11042 Erik 1114 11042 Erik switch (connp->conn_family) { 1115 0 stevel case AF_INET: 1116 0 stevel sin = sin_null; 1117 0 stevel sin.sin_family = AF_INET; 1118 0 stevel sin.sin_addr.s_addr = ipha->ipha_dst; 1119 0 stevel sin.sin_port = udpha->uha_dst_port; 1120 8348 Eric if (IPCL_IS_NONSTR(connp)) { 1121 11042 Erik mutex_enter(&connp->conn_lock); 1122 8348 Eric if (udp->udp_state == TS_DATA_XFER) { 1123 11042 Erik if (sin.sin_port == connp->conn_fport && 1124 8348 Eric sin.sin_addr.s_addr == 1125 11042 Erik connp->conn_faddr_v4) { 1126 11042 Erik mutex_exit(&connp->conn_lock); 1127 8348 Eric (*connp->conn_upcalls->su_set_error) 1128 8348 Eric (connp->conn_upper_handle, error); 1129 8348 Eric goto done; 1130 8348 Eric } 1131 8348 Eric } else { 1132 8348 Eric udp->udp_delayed_error = error; 1133 8348 Eric *((sin_t *)&udp->udp_delayed_addr) = sin; 1134 8348 Eric } 1135 11042 Erik mutex_exit(&connp->conn_lock); 1136 8348 Eric } else { 1137 8348 Eric mp1 = mi_tpi_uderror_ind((char *)&sin, sizeof (sin_t), 1138 8348 Eric NULL, 0, error); 1139 11042 Erik if (mp1 != NULL) 1140 11042 Erik putnext(connp->conn_rq, mp1); 1141 8348 Eric } 1142 0 stevel break; 1143 0 stevel case AF_INET6: 1144 0 stevel sin6 = sin6_null; 1145 0 stevel sin6.sin6_family = AF_INET6; 1146 0 stevel IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &sin6.sin6_addr); 1147 0 stevel sin6.sin6_port = udpha->uha_dst_port; 1148 8348 Eric if (IPCL_IS_NONSTR(connp)) { 1149 11042 Erik mutex_enter(&connp->conn_lock); 1150 8348 Eric if (udp->udp_state == TS_DATA_XFER) { 1151 11042 Erik if (sin6.sin6_port == connp->conn_fport && 1152 8348 Eric IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, 1153 11042 Erik &connp->conn_faddr_v6)) { 1154 11042 Erik mutex_exit(&connp->conn_lock); 1155 8348 Eric (*connp->conn_upcalls->su_set_error) 1156 8348 Eric (connp->conn_upper_handle, error); 1157 8348 Eric goto done; 1158 8348 Eric } 1159 8348 Eric } else { 1160 8348 Eric udp->udp_delayed_error = error; 1161 8348 Eric *((sin6_t *)&udp->udp_delayed_addr) = sin6; 1162 8348 Eric } 1163 11042 Erik mutex_exit(&connp->conn_lock); 1164 8348 Eric } else { 1165 8348 Eric mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t), 1166 8348 Eric NULL, 0, error); 1167 11042 Erik if (mp1 != NULL) 1168 11042 Erik putnext(connp->conn_rq, mp1); 1169 11042 Erik } 1170 11042 Erik break; 1171 11042 Erik } 1172 8348 Eric done: 1173 0 stevel freemsg(mp); 1174 0 stevel } 1175 0 stevel 1176 0 stevel /* 1177 0 stevel * udp_icmp_error_ipv6 is called by udp_icmp_error to process ICMP for IPv6. 1178 0 stevel * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors. 1179 0 stevel * Assumes that IP has pulled up all the extension headers as well as the 1180 0 stevel * ICMPv6 header. 1181 0 stevel */ 1182 0 stevel static void 1183 11042 Erik udp_icmp_error_ipv6(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira) 1184 0 stevel { 1185 0 stevel icmp6_t *icmp6; 1186 0 stevel ip6_t *ip6h, *outer_ip6h; 1187 5240 nordmark uint16_t iph_hdr_length; 1188 0 stevel uint8_t *nexthdrp; 1189 0 stevel udpha_t *udpha; 1190 0 stevel sin6_t sin6; 1191 0 stevel mblk_t *mp1; 1192 0 stevel int error = 0; 1193 8348 Eric udp_t *udp = connp->conn_udp; 1194 5240 nordmark udp_stack_t *us = udp->udp_us; 1195 0 stevel 1196 0 stevel outer_ip6h = (ip6_t *)mp->b_rptr; 1197 11042 Erik #ifdef DEBUG 1198 5240 nordmark if (outer_ip6h->ip6_nxt != IPPROTO_ICMPV6) 1199 5240 nordmark iph_hdr_length = ip_hdr_length_v6(mp, outer_ip6h); 1200 5240 nordmark else 1201 5240 nordmark iph_hdr_length = IPV6_HDR_LEN; 1202 11042 Erik ASSERT(iph_hdr_length == ira->ira_ip_hdr_length); 1203 11042 Erik #endif 1204 11042 Erik /* Skip past the outer IP and ICMP headers */ 1205 11042 Erik iph_hdr_length = ira->ira_ip_hdr_length; 1206 5240 nordmark icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length]; 1207 11042 Erik 1208 11042 Erik /* Skip past the inner IP and find the ULP header */ 1209 11042 Erik ip6h = (ip6_t *)&icmp6[1]; /* Inner IP header */ 1210 5240 nordmark if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length, &nexthdrp)) { 1211 5240 nordmark freemsg(mp); 1212 5240 nordmark return; 1213 5240 nordmark } 1214 5240 nordmark udpha = (udpha_t *)((char *)ip6h + iph_hdr_length); 1215 0 stevel 1216 0 stevel switch (icmp6->icmp6_type) { 1217 0 stevel case ICMP6_DST_UNREACH: 1218 0 stevel switch (icmp6->icmp6_code) { 1219 0 stevel case ICMP6_DST_UNREACH_NOPORT: 1220 0 stevel error = ECONNREFUSED; 1221 0 stevel break; 1222 0 stevel case ICMP6_DST_UNREACH_ADMIN: 1223 0 stevel case ICMP6_DST_UNREACH_NOROUTE: 1224 0 stevel case ICMP6_DST_UNREACH_BEYONDSCOPE: 1225 0 stevel case ICMP6_DST_UNREACH_ADDR: 1226 0 stevel /* Transient errors */ 1227 0 stevel break; 1228 0 stevel default: 1229 0 stevel break; 1230 0 stevel } 1231 0 stevel break; 1232 0 stevel case ICMP6_PACKET_TOO_BIG: { 1233 0 stevel struct T_unitdata_ind *tudi; 1234 0 stevel struct T_opthdr *toh; 1235 0 stevel size_t udi_size; 1236 0 stevel mblk_t *newmp; 1237 0 stevel t_scalar_t opt_length = sizeof (struct T_opthdr) + 1238 0 stevel sizeof (struct ip6_mtuinfo); 1239 0 stevel sin6_t *sin6; 1240 0 stevel struct ip6_mtuinfo *mtuinfo; 1241 0 stevel 1242 0 stevel /* 1243 0 stevel * If the application has requested to receive path mtu 1244 0 stevel * information, send up an empty message containing an 1245 0 stevel * IPV6_PATHMTU ancillary data item. 1246 0 stevel */ 1247 11042 Erik if (!connp->conn_ipv6_recvpathmtu) 1248 0 stevel break; 1249 0 stevel 1250 0 stevel udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t) + 1251 0 stevel opt_length; 1252 0 stevel if ((newmp = allocb(udi_size, BPRI_MED)) == NULL) { 1253 5240 nordmark BUMP_MIB(&us->us_udp_mib, udpInErrors); 1254 0 stevel break; 1255 0 stevel } 1256 0 stevel 1257 0 stevel /* 1258 0 stevel * newmp->b_cont is left to NULL on purpose. This is an 1259 0 stevel * empty message containing only ancillary data. 1260 0 stevel */ 1261 0 stevel newmp->b_datap->db_type = M_PROTO; 1262 0 stevel tudi = (struct T_unitdata_ind *)newmp->b_rptr; 1263 0 stevel newmp->b_wptr = (uchar_t *)tudi + udi_size; 1264 0 stevel tudi->PRIM_type = T_UNITDATA_IND; 1265 0 stevel tudi->SRC_length = sizeof (sin6_t); 1266 0 stevel tudi->SRC_offset = sizeof (struct T_unitdata_ind); 1267 0 stevel tudi->OPT_offset = tudi->SRC_offset + sizeof (sin6_t); 1268 0 stevel tudi->OPT_length = opt_length; 1269 0 stevel 1270 0 stevel sin6 = (sin6_t *)&tudi[1]; 1271 0 stevel bzero(sin6, sizeof (sin6_t)); 1272 0 stevel sin6->sin6_family = AF_INET6; 1273 11042 Erik sin6->sin6_addr = connp->conn_faddr_v6; 1274 0 stevel 1275 0 stevel toh = (struct T_opthdr *)&sin6[1]; 1276 0 stevel toh->level = IPPROTO_IPV6; 1277 0 stevel toh->name = IPV6_PATHMTU; 1278 0 stevel toh->len = opt_length; 1279 0 stevel toh->status = 0; 1280 0 stevel 1281 0 stevel mtuinfo = (struct ip6_mtuinfo *)&toh[1]; 1282 0 stevel bzero(mtuinfo, sizeof (struct ip6_mtuinfo)); 1283 0 stevel mtuinfo->ip6m_addr.sin6_family = AF_INET6; 1284 0 stevel mtuinfo->ip6m_addr.sin6_addr = ip6h->ip6_dst; 1285 0 stevel mtuinfo->ip6m_mtu = icmp6->icmp6_mtu; 1286 0 stevel /* 1287 0 stevel * We've consumed everything we need from the original 1288 0 stevel * message. Free it, then send our empty message. 1289 0 stevel */ 1290 0 stevel freemsg(mp); 1291 11042 Erik udp_ulp_recv(connp, newmp, msgdsize(newmp), ira); 1292 0 stevel return; 1293 0 stevel } 1294 0 stevel case ICMP6_TIME_EXCEEDED: 1295 0 stevel /* Transient errors */ 1296 0 stevel break; 1297 0 stevel case ICMP6_PARAM_PROB: 1298 0 stevel /* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */ 1299 0 stevel if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER && 1300 0 stevel (uchar_t *)ip6h + icmp6->icmp6_pptr == 1301 0 stevel (uchar_t *)nexthdrp) { 1302 0 stevel error = ECONNREFUSED; 1303 0 stevel break; 1304 0 stevel } 1305 0 stevel break; 1306 0 stevel } 1307 0 stevel if (error == 0) { 1308 0 stevel freemsg(mp); 1309 0 stevel return; 1310 0 stevel } 1311 0 stevel 1312 5240 nordmark /* 1313 5240 nordmark * Deliver T_UDERROR_IND when the application has asked for it. 1314 5240 nordmark * The socket layer enables this automatically when connected. 1315 5240 nordmark */ 1316 11042 Erik if (!connp->conn_dgram_errind) { 1317 5240 nordmark freemsg(mp); 1318 5240 nordmark return; 1319 5240 nordmark } 1320 5240 nordmark 1321 0 stevel sin6 = sin6_null; 1322 0 stevel sin6.sin6_family = AF_INET6; 1323 0 stevel sin6.sin6_addr = ip6h->ip6_dst; 1324 0 stevel sin6.sin6_port = udpha->uha_dst_port; 1325 0 stevel sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK; 1326 0 stevel 1327 8348 Eric if (IPCL_IS_NONSTR(connp)) { 1328 11042 Erik mutex_enter(&connp->conn_lock); 1329 8348 Eric if (udp->udp_state == TS_DATA_XFER) { 1330 11042 Erik if (sin6.sin6_port == connp->conn_fport && 1331 8348 Eric IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, 1332 11042 Erik &connp->conn_faddr_v6)) { 1333 11042 Erik mutex_exit(&connp->conn_lock); 1334 8348 Eric (*connp->conn_upcalls->su_set_error) 1335 8348 Eric (connp->conn_upper_handle, error); 1336 8348 Eric goto done; 1337 8348 Eric } 1338 8348 Eric } else { 1339 8348 Eric udp->udp_delayed_error = error; 1340 8348 Eric *((sin6_t *)&udp->udp_delayed_addr) = sin6; 1341 8348 Eric } 1342 11042 Erik mutex_exit(&connp->conn_lock); 1343 8348 Eric } else { 1344 8348 Eric mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t), 1345 8348 Eric NULL, 0, error); 1346 8348 Eric if (mp1 != NULL) 1347 8348 Eric putnext(connp->conn_rq, mp1); 1348 8348 Eric } 1349 8348 Eric done: 1350 0 stevel freemsg(mp); 1351 0 stevel } 1352 0 stevel 1353 0 stevel /* 1354 0 stevel * This routine responds to T_ADDR_REQ messages. It is called by udp_wput. 1355 0 stevel * The local address is filled in if endpoint is bound. The remote address 1356 0 stevel * is filled in if remote address has been precified ("connected endpoint") 1357 0 stevel * (The concept of connected CLTS sockets is alien to published TPI 1358 0 stevel * but we support it anyway). 1359 0 stevel */ 1360 0 stevel static void 1361 0 stevel udp_addr_req(queue_t *q, mblk_t *mp) 1362 0 stevel { 1363 11042 Erik struct sockaddr *sa; 1364 0 stevel mblk_t *ackmp; 1365 0 stevel struct T_addr_ack *taa; 1366 741 masputra udp_t *udp = Q_TO_UDP(q); 1367 11042 Erik conn_t *connp = udp->udp_connp; 1368 11042 Erik uint_t addrlen; 1369 0 stevel 1370 0 stevel /* Make it large enough for worst case */ 1371 0 stevel ackmp = reallocb(mp, sizeof (struct T_addr_ack) + 1372 0 stevel 2 * sizeof (sin6_t), 1); 1373 0 stevel if (ackmp == NULL) { 1374 0 stevel udp_err_ack(q, mp, TSYSERR, ENOMEM); 1375 0 stevel return; 1376 0 stevel } 1377 0 stevel taa = (struct T_addr_ack *)ackmp->b_rptr; 1378 0 stevel 1379 0 stevel bzero(taa, sizeof (struct T_addr_ack)); 1380 0 stevel ackmp->b_wptr = (uchar_t *)&taa[1]; 1381 0 stevel 1382 0 stevel taa->PRIM_type = T_ADDR_ACK; 1383 0 stevel ackmp->b_datap->db_type = M_PCPROTO; 1384 11042 Erik 1385 11042 Erik if (connp->conn_family == AF_INET) 1386 11042 Erik addrlen = sizeof (sin_t); 1387 11042 Erik else 1388 11042 Erik addrlen = sizeof (sin6_t); 1389 11042 Erik 1390 11042 Erik mutex_enter(&connp->conn_lock); 1391 0 stevel /* 1392 0 stevel * Note: Following code assumes 32 bit alignment of basic 1393 0 stevel * data structures like sin_t and struct T_addr_ack. 1394 0 stevel */ 1395 0 stevel if (udp->udp_state != TS_UNBND) { 1396 0 stevel /* 1397 0 stevel * Fill in local address first 1398 0 stevel */ 1399 0 stevel taa->LOCADDR_offset = sizeof (*taa); 1400 11042 Erik taa->LOCADDR_length = addrlen; 1401 11042 Erik sa = (struct sockaddr *)&taa[1]; 1402 11042 Erik (void) conn_getsockname(connp, sa, &addrlen); 1403 11042 Erik ackmp->b_wptr += addrlen; 1404 11042 Erik } 1405 11042 Erik if (udp->udp_state == TS_DATA_XFER) { 1406 11042 Erik /* 1407 11042 Erik * connected, fill remote address too 1408 11042 Erik */ 1409 11042 Erik taa->REMADDR_length = addrlen; 1410 11042 Erik /* assumed 32-bit alignment */ 1411 11042 Erik taa->REMADDR_offset = taa->LOCADDR_offset + taa->LOCADDR_length; 1412 11042 Erik sa = (struct sockaddr *)(ackmp->b_rptr + taa->REMADDR_offset); 1413 11042 Erik (void) conn_getpeername(connp, sa, &addrlen); 1414 11042 Erik ackmp->b_wptr += addrlen; 1415 11042 Erik } 1416 11042 Erik mutex_exit(&connp->conn_lock); 1417 0 stevel ASSERT(ackmp->b_wptr <= ackmp->b_datap->db_lim); 1418 5240 nordmark qreply(q, ackmp); 1419 0 stevel } 1420 0 stevel 1421 0 stevel static void 1422 0 stevel udp_copy_info(struct T_info_ack *tap, udp_t *udp) 1423 0 stevel { 1424 11042 Erik conn_t *connp = udp->udp_connp; 1425 11042 Erik 1426 11042 Erik if (connp->conn_family == AF_INET) { 1427 0 stevel *tap = udp_g_t_info_ack_ipv4; 1428 0 stevel } else { 1429 0 stevel *tap = udp_g_t_info_ack_ipv6; 1430 0 stevel } 1431 0 stevel tap->CURRENT_state = udp->udp_state; 1432 0 stevel tap->OPT_size = udp_max_optsize; 1433 0 stevel } 1434 0 stevel 1435 8348 Eric static void 1436 8348 Eric udp_do_capability_ack(udp_t *udp, struct T_capability_ack *tcap, 1437 8348 Eric t_uscalar_t cap_bits1) 1438 8348 Eric { 1439 8348 Eric tcap->CAP_bits1 = 0; 1440 8348 Eric 1441 8348 Eric if (cap_bits1 & TC1_INFO) { 1442 8348 Eric udp_copy_info(&tcap->INFO_ack, udp); 1443 8348 Eric tcap->CAP_bits1 |= TC1_INFO; 1444 8348 Eric } 1445 8348 Eric } 1446 8348 Eric 1447 0 stevel /* 1448 0 stevel * This routine responds to T_CAPABILITY_REQ messages. It is called by 1449 0 stevel * udp_wput. Much of the T_CAPABILITY_ACK information is copied from 1450 0 stevel * udp_g_t_info_ack. The current state of the stream is copied from 1451 0 stevel * udp_state. 1452 0 stevel */ 1453 0 stevel static void 1454 0 stevel udp_capability_req(queue_t *q, mblk_t *mp) 1455 0 stevel { 1456 0 stevel t_uscalar_t cap_bits1; 1457 0 stevel struct T_capability_ack *tcap; 1458 741 masputra udp_t *udp = Q_TO_UDP(q); 1459 0 stevel 1460 0 stevel cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1; 1461 0 stevel 1462 0 stevel mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack), 1463 0 stevel mp->b_datap->db_type, T_CAPABILITY_ACK); 1464 0 stevel if (!mp) 1465 0 stevel return; 1466 0 stevel 1467 0 stevel tcap = (struct T_capability_ack *)mp->b_rptr; 1468 8348 Eric udp_do_capability_ack(udp, tcap, cap_bits1); 1469 0 stevel 1470 5240 nordmark qreply(q, mp); 1471 0 stevel } 1472 0 stevel 1473 0 stevel /* 1474 0 stevel * This routine responds to T_INFO_REQ messages. It is called by udp_wput. 1475 0 stevel * Most of the T_INFO_ACK information is copied from udp_g_t_info_ack. 1476 0 stevel * The current state of the stream is copied from udp_state. 1477 0 stevel */ 1478 0 stevel static void 1479 0 stevel udp_info_req(queue_t *q, mblk_t *mp) 1480 0 stevel { 1481 741 masputra udp_t *udp = Q_TO_UDP(q); 1482 0 stevel 1483 0 stevel /* Create a T_INFO_ACK message. */ 1484 0 stevel mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO, 1485 0 stevel T_INFO_ACK); 1486 0 stevel if (!mp) 1487 0 stevel return; 1488 0 stevel udp_copy_info((struct T_info_ack *)mp->b_rptr, udp); 1489 5240 nordmark qreply(q, mp); 1490 0 stevel } 1491 0 stevel 1492 5240 nordmark /* For /dev/udp aka AF_INET open */ 1493 5240 nordmark static int 1494 5240 nordmark udp_openv4(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 1495 5240 nordmark { 1496 5240 nordmark return (udp_open(q, devp, flag, sflag, credp, B_FALSE)); 1497 5240 nordmark } 1498 5240 nordmark 1499 5240 nordmark /* For /dev/udp6 aka AF_INET6 open */ 1500 5240 nordmark static int 1501 5240 nordmark udp_openv6(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 1502 5240 nordmark { 1503 5240 nordmark return (udp_open(q, devp, flag, sflag, credp, B_TRUE)); 1504 5240 nordmark } 1505 5240 nordmark 1506 0 stevel /* 1507 0 stevel * This is the open routine for udp. It allocates a udp_t structure for 1508 0 stevel * the stream and, on the first open of the module, creates an ND table. 1509 0 stevel */ 1510 5240 nordmark static int 1511 5240 nordmark udp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp, 1512 5240 nordmark boolean_t isv6) 1513 0 stevel { 1514 5815 gt145670 udp_t *udp; 1515 5815 gt145670 conn_t *connp; 1516 5815 gt145670 dev_t conn_dev; 1517 5815 gt145670 vmem_t *minor_arena; 1518 0 stevel 1519 0 stevel /* If the stream is already open, return immediately. */ 1520 0 stevel if (q->q_ptr != NULL) 1521 0 stevel return (0); 1522 0 stevel 1523 5240 nordmark if (sflag == MODOPEN) 1524 0 stevel return (EINVAL); 1525 3448 dh155122 1526 5815 gt145670 if ((ip_minor_arena_la != NULL) && (flag & SO_SOCKSTR) && 1527 5815 gt145670 ((conn_dev = inet_minor_alloc(ip_minor_arena_la)) != 0)) { 1528 5815 gt145670 minor_arena = ip_minor_arena_la; 1529 5815 gt145670 } else { 1530 5815 gt145670 /* 1531 5815 gt145670 * Either minor numbers in the large arena were exhausted 1532 5815 gt145670 * or a non socket application is doing the open. 1533 5815 gt145670 * Try to allocate from the small arena. 1534 5815 gt145670 */ 1535 8348 Eric if ((conn_dev = inet_minor_alloc(ip_minor_arena_sa)) == 0) 1536 5815 gt145670 return (EBUSY); 1537 8348 Eric 1538 5815 gt145670 minor_arena = ip_minor_arena_sa; 1539 5815 gt145670 } 1540 5815 gt145670 1541 8348 Eric if (flag & SO_FALLBACK) { 1542 8348 Eric /* 1543 8348 Eric * Non streams socket needs a stream to fallback to 1544 8348 Eric */ 1545 8348 Eric RD(q)->q_ptr = (void *)conn_dev; 1546 8348 Eric WR(q)->q_qinfo = &udp_fallback_sock_winit; 1547 8348 Eric WR(q)->q_ptr = (void *)minor_arena; 1548 8348 Eric qprocson(q); 1549 8348 Eric return (0); 1550 8348 Eric } 1551 8348 Eric 1552 8348 Eric connp = udp_do_open(credp, isv6, KM_SLEEP); 1553 8348 Eric if (connp == NULL) { 1554 8348 Eric inet_minor_free(minor_arena, conn_dev); 1555 8348 Eric return (ENOMEM); 1556 8348 Eric } 1557 8348 Eric udp = connp->conn_udp; 1558 8348 Eric 1559 5240 nordmark *devp = makedevice(getemajor(*devp), (minor_t)conn_dev); 1560 5240 nordmark connp->conn_dev = conn_dev; 1561 5815 gt145670 connp->conn_minor_arena = minor_arena; 1562 741 masputra 1563 741 masputra /* 1564 741 masputra * Initialize the udp_t structure for this stream. 1565 741 masputra */ 1566 5240 nordmark q->q_ptr = connp; 1567 5240 nordmark WR(q)->q_ptr = connp; 1568 5240 nordmark connp->conn_rq = q; 1569 5240 nordmark connp->conn_wq = WR(q); 1570 5240 nordmark 1571 11042 Erik /* 1572 11042 Erik * Since this conn_t/udp_t is not yet visible to anybody else we don't 1573 11042 Erik * need to lock anything. 1574 11042 Erik */ 1575 11042 Erik ASSERT(connp->conn_proto == IPPROTO_UDP); 1576 5240 nordmark ASSERT(connp->conn_udp == udp); 1577 5240 nordmark ASSERT(udp->udp_connp == connp); 1578 0 stevel 1579 5240 nordmark if (flag & SO_SOCKSTR) { 1580 741 masputra udp->udp_issocket = B_TRUE; 1581 741 masputra } 1582 1676 jpk 1583 11042 Erik WR(q)->q_hiwat = connp->conn_sndbuf; 1584 11042 Erik WR(q)->q_lowat = connp->conn_sndlowat; 1585 0 stevel 1586 8348 Eric qprocson(q); 1587 8348 Eric 1588 8348 Eric /* Set the Stream head write offset and high watermark. */ 1589 11042 Erik (void) proto_set_tx_wroff(q, connp, connp->conn_wroff); 1590 11042 Erik (void) proto_set_rx_hiwat(q, connp, 1591 11042 Erik udp_set_rcv_hiwat(udp, connp->conn_rcvbuf)); 1592 5240 nordmark 1593 5240 nordmark mutex_enter(&connp->conn_lock); 1594 5240 nordmark connp->conn_state_flags &= ~CONN_INCIPIENT; 1595 5240 nordmark mutex_exit(&connp->conn_lock); 1596 741 masputra return (0); 1597 0 stevel } 1598 0 stevel 1599 0 stevel /* 1600 0 stevel * Which UDP options OK to set through T_UNITDATA_REQ... 1601 0 stevel */ 1602 0 stevel /* ARGSUSED */ 1603 0 stevel static boolean_t 1604 0 stevel udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name) 1605 0 stevel { 1606 0 stevel return (B_TRUE); 1607 0 stevel } 1608 0 stevel 1609 0 stevel /* 1610 0 stevel * This routine gets default values of certain options whose default 1611 0 stevel * values are maintained by protcol specific code 1612 0 stevel */ 1613 0 stevel int 1614 5240 nordmark udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 1615 0 stevel { 1616 3448 dh155122 udp_t *udp = Q_TO_UDP(q); 1617 3448 dh155122 udp_stack_t *us = udp->udp_us; 1618 0 stevel int *i1 = (int *)ptr; 1619 0 stevel 1620 0 stevel switch (level) { 1621 0 stevel case IPPROTO_IP: 1622 0 stevel switch (name) { 1623 0 stevel case IP_MULTICAST_TTL: 1624 0 stevel *ptr = (uchar_t)IP_DEFAULT_MULTICAST_TTL; 1625 0 stevel return (sizeof (uchar_t)); 1626 0 stevel case IP_MULTICAST_LOOP: 1627 0 stevel *ptr = (uchar_t)IP_DEFAULT_MULTICAST_LOOP; 1628 0 stevel return (sizeof (uchar_t)); 1629 0 stevel } 1630 0 stevel break; 1631 0 stevel case IPPROTO_IPV6: 1632 0 stevel switch (name) { 1633 0 stevel case IPV6_MULTICAST_HOPS: 1634 0 stevel *i1 = IP_DEFAULT_MULTICAST_TTL; 1635 0 stevel return (sizeof (int)); 1636 0 stevel case IPV6_MULTICAST_LOOP: 1637 0 stevel *i1 = IP_DEFAULT_MULTICAST_LOOP; 1638 0 stevel return (sizeof (int)); 1639 0 stevel case IPV6_UNICAST_HOPS: 1640 3448 dh155122 *i1 = us->us_ipv6_hoplimit; 1641 0 stevel return (sizeof (int)); 1642 0 stevel } 1643 0 stevel break; 1644 0 stevel } 1645 0 stevel return (-1); 1646 0 stevel } 1647 0 stevel 1648 0 stevel /* 1649 5240 nordmark * This routine retrieves the current status of socket options. 1650 11042 Erik * It returns the size of the option retrieved, or -1. 1651 11042 Erik */ 1652 11042 Erik int 1653 11042 Erik udp_opt_get(conn_t *connp, t_scalar_t level, t_scalar_t name, 1654 11042 Erik uchar_t *ptr) 1655 11042 Erik { 1656 8348 Eric int *i1 = (int *)ptr; 1657 11042 Erik udp_t *udp = connp->conn_udp; 1658 8348 Eric int len; 1659 11042 Erik conn_opt_arg_t coas; 1660 11042 Erik int retval; 1661 11042 Erik 1662 11042 Erik coas.coa_connp = connp; 1663 11042 Erik coas.coa_ixa = connp->conn_ixa; 1664 11042 Erik coas.coa_ipp = &connp->conn_xmit_ipp; 1665 11042 Erik coas.coa_ancillary = B_FALSE; 1666 11042 Erik coas.coa_changed = 0; 1667 11042 Erik 1668 11042 Erik /* 1669 11042 Erik * We assume that the optcom framework has checked for the set 1670 11042 Erik * of levels and names that are supported, hence we don't worry 1671 11042 Erik * about rejecting based on that. 1672 11042 Erik * First check for UDP specific handling, then pass to common routine. 1673 11042 Erik */ 1674 11042 Erik switch (level) { 1675 11042 Erik case IPPROTO_IP: 1676 11042 Erik /* 1677 11042 Erik * Only allow IPv4 option processing on IPv4 sockets. 1678 11042 Erik */ 1679 11042 Erik if (connp->conn_family != AF_INET) 1680 11042 Erik return (-1); 1681 11042 Erik 1682 11042 Erik switch (name) { 1683 11042 Erik case IP_OPTIONS: 1684 11042 Erik case T_IP_OPTIONS: 1685 11042 Erik mutex_enter(&connp->conn_lock); 1686 11042 Erik if (!(udp->udp_recv_ipp.ipp_fields & 1687 11042 Erik IPPF_IPV4_OPTIONS)) { 1688 11042 Erik mutex_exit(&connp->conn_lock); 1689 11042 Erik return (0); 1690 11042 Erik } 1691 11042 Erik 1692 11042 Erik len = udp->udp_recv_ipp.ipp_ipv4_options_len; 1693 11042 Erik ASSERT(len != 0); 1694 11042 Erik bcopy(udp->udp_recv_ipp.ipp_ipv4_options, ptr, len); 1695 11042 Erik mutex_exit(&connp->conn_lock); 1696 11042 Erik return (len); 1697 11042 Erik } 1698 11042 Erik break; 1699 11042 Erik case IPPROTO_UDP: 1700 11042 Erik switch (name) { 1701 11042 Erik case UDP_NAT_T_ENDPOINT: 1702 11042 Erik mutex_enter(&connp->conn_lock); 1703 11042 Erik *i1 = udp->udp_nat_t_endpoint; 1704 11042 Erik mutex_exit(&connp->conn_lock); 1705 11042 Erik return (sizeof (int)); 1706 11042 Erik case UDP_RCVHDR: 1707 11042 Erik mutex_enter(&connp->conn_lock); 1708 11042 Erik *i1 = udp->udp_rcvhdr ? 1 : 0; 1709 11042 Erik mutex_exit(&connp->conn_lock); 1710 11042 Erik return (sizeof (int)); 1711 11042 Erik } 1712 11042 Erik } 1713 11042 Erik mutex_enter(&connp->conn_lock); 1714 11042 Erik retval = conn_opt_get(&coas, level, name, ptr); 1715 11042 Erik mutex_exit(&connp->conn_lock); 1716 11042 Erik return (retval); 1717 11042 Erik } 1718 11042 Erik 1719 11042 Erik /* 1720 11042 Erik * This routine retrieves the current status of socket options. 1721 11042 Erik * It returns the size of the option retrieved, or -1. 1722 11042 Erik */ 1723 11042 Erik int 1724 11042 Erik udp_tpi_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 1725 11042 Erik { 1726 11042 Erik conn_t *connp = Q_TO_CONN(q); 1727 11042 Erik int err; 1728 11042 Erik 1729 11042 Erik err = udp_opt_get(connp, level, name, ptr); 1730 11042 Erik return (err); 1731 11042 Erik } 1732 11042 Erik 1733 11042 Erik /* 1734 11042 Erik * This routine sets socket options. 1735 11042 Erik */ 1736 11042 Erik int 1737 11042 Erik udp_do_opt_set(conn_opt_arg_t *coa, int level, int name, 1738 11042 Erik uint_t inlen, uchar_t *invalp, cred_t *cr, boolean_t checkonly) 1739 11042 Erik { 1740 11042 Erik conn_t *connp = coa->coa_connp; 1741 11042 Erik ip_xmit_attr_t *ixa = coa->coa_ixa; 1742 11042 Erik udp_t *udp = connp->conn_udp; 1743 11042 Erik udp_stack_t *us = udp->udp_us; 1744 11042 Erik int *i1 = (int *)invalp; 1745 11042 Erik boolean_t onoff = (*i1 == 0) ? 0 : 1; 1746 11042 Erik int error; 1747 11042 Erik 1748 11042 Erik ASSERT(MUTEX_NOT_HELD(&coa->coa_connp->conn_lock)); 1749 11042 Erik /* 1750 11042 Erik * First do UDP specific sanity checks and handle UDP specific 1751 11042 Erik * options. Note that some IPPROTO_UDP options are handled 1752 11042 Erik * by conn_opt_set. 1753 11042 Erik */ 1754 0 stevel switch (level) { 1755 0 stevel case SOL_SOCKET: 1756 0 stevel switch (name) { 1757 0 stevel case SO_SNDBUF: 1758 3448 dh155122 if (*i1 > us->us_max_buf) { 1759 0 stevel return (ENOBUFS); 1760 0 stevel } 1761 0 stevel break; 1762 0 stevel case SO_RCVBUF: 1763 3448 dh155122 if (*i1 > us->us_max_buf) { 1764 0 stevel return (ENOBUFS); 1765 0 stevel } 1766 11042 Erik break; 1767 11042 Erik 1768 1676 jpk case SCM_UCRED: { 1769 1676 jpk struct ucred_s *ucr; 1770 11042 Erik cred_t *newcr; 1771 1676 jpk ts_label_t *tsl; 1772 1676 jpk 1773 1676 jpk /* 1774 1676 jpk * Only sockets that have proper privileges and are 1775 1676 jpk * bound to MLPs will have any other value here, so 1776 1676 jpk * this implicitly tests for privilege to set label. 1777 1676 jpk */ 1778 1676 jpk if (connp->conn_mlp_type == mlptSingle) 1779 1676 jpk break; 1780 11042 Erik 1781 1676 jpk ucr = (struct ucred_s *)invalp; 1782 11134 Casper if (inlen < sizeof (*ucr) + sizeof (bslabel_t) || 1783 1676 jpk ucr->uc_labeloff < sizeof (*ucr) || 1784 1676 jpk ucr->uc_labeloff + sizeof (bslabel_t) > inlen) 1785 1676 jpk return (EINVAL); 1786 1676 jpk if (!checkonly) { 1787 11042 Erik /* 1788 11042 Erik * Set ixa_tsl to the new label. 1789 11042 Erik * We assume that crgetzoneid doesn't change 1790 11042 Erik * as part of the SCM_UCRED. 1791 11042 Erik */ 1792 1676 jpk ASSERT(cr != NULL); 1793 1676 jpk if ((tsl = crgetlabel(cr)) == NULL) 1794 1676 jpk return (EINVAL); 1795 1676 jpk newcr = copycred_from_bslabel(cr, UCLABEL(ucr), 1796 1676 jpk tsl->tsl_doi, KM_NOSLEEP); 1797 1676 jpk if (newcr == NULL) 1798 1676 jpk return (ENOSR); 1799 11042 Erik ASSERT(newcr->cr_label != NULL); 1800 11042 Erik /* 1801 11042 Erik * Move the hold on the cr_label to ixa_tsl by 1802 11042 Erik * setting cr_label to NULL. Then release newcr. 1803 11042 Erik */ 1804 11042 Erik ip_xmit_attr_replace_tsl(ixa, newcr->cr_label); 1805 11042 Erik ixa->ixa_flags |= IXAF_UCRED_TSL; 1806 11042 Erik newcr->cr_label = NULL; 1807 1676 jpk crfree(newcr); 1808 11042 Erik coa->coa_changed |= COA_HEADER_CHANGED; 1809 11042 Erik coa->coa_changed |= COA_WROFF_CHANGED; 1810 11042 Erik } 1811 11042 Erik /* Fully handled this option. */ 1812 11042 Erik return (0); 1813 11042 Erik } 1814 11042 Erik } 1815 11042 Erik break; 1816 0 stevel case IPPROTO_UDP: 1817 0 stevel switch (name) { 1818 4987 danmcd case UDP_NAT_T_ENDPOINT: 1819 4987 danmcd if ((error = secpolicy_ip_config(cr, B_FALSE)) != 0) { 1820 4987 danmcd return (error); 1821 4987 danmcd } 1822 4987 danmcd 1823 4987 danmcd /* 1824 11042 Erik * Use conn_family instead so we can avoid ambiguitites 1825 4987 danmcd * with AF_INET6 sockets that may switch from IPv4 1826 4987 danmcd * to IPv6. 1827 4987 danmcd */ 1828 11042 Erik if (connp->conn_family != AF_INET) { 1829 4987 danmcd return (EAFNOSUPPORT); 1830 4987 danmcd } 1831 4987 danmcd 1832 4987 danmcd if (!checkonly) { 1833 11042 Erik mutex_enter(&connp->conn_lock); 1834 4987 danmcd udp->udp_nat_t_endpoint = onoff; 1835 11042 Erik mutex_exit(&connp->conn_lock); 1836 11042 Erik coa->coa_changed |= COA_HEADER_CHANGED; 1837 11042 Erik coa->coa_changed |= COA_WROFF_CHANGED; 1838 11042 Erik } 1839 11042 Erik /* Fully handled this option. */ 1840 11042 Erik return (0); 1841 11042 Erik case UDP_RCVHDR: 1842 11042 Erik mutex_enter(&connp->conn_lock); 1843 11042 Erik udp->udp_rcvhdr = onoff; 1844 11042 Erik mutex_exit(&connp->conn_lock); 1845 11042 Erik return (0); 1846 11042 Erik } 1847 11042 Erik break; 1848 11042 Erik } 1849 11042 Erik error = conn_opt_set(coa, level, name, inlen, invalp, 1850 11042 Erik checkonly, cr); 1851 11042 Erik return (error); 1852 11042 Erik } 1853 11042 Erik 1854 11042 Erik /* 1855 11042 Erik * This routine sets socket options. 1856 11042 Erik */ 1857 11042 Erik int 1858 11042 Erik udp_opt_set(conn_t *connp, uint_t optset_context, int level, 1859 11042 Erik int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 1860 11042 Erik uchar_t *outvalp, void *thisdg_attrs, cred_t *cr) 1861 11042 Erik { 1862 11042 Erik udp_t *udp = connp->conn_udp; 1863 11042 Erik int err; 1864 11042 Erik conn_opt_arg_t coas, *coa; 1865 8348 Eric boolean_t checkonly; 1866 11042 Erik udp_stack_t *us = udp->udp_us; 1867 11042 Erik 1868 8348 Eric switch (optset_context) { 1869 8348 Eric case SETFN_OPTCOM_CHECKONLY: 1870 8348 Eric checkonly = B_TRUE; 1871 8348 Eric /* 1872 8348 Eric * Note: Implies T_CHECK semantics for T_OPTCOM_REQ 1873 8348 Eric * inlen != 0 implies value supplied and 1874 8348 Eric * we have to "pretend" to set it. 1875 8348 Eric * inlen == 0 implies that there is no 1876 8348 Eric * value part in T_CHECK request and just validation 1877 8348 Eric * done elsewhere should be enough, we just return here. 1878 8348 Eric */ 1879 8348 Eric if (inlen == 0) { 1880 8348 Eric *outlenp = 0; 1881 11042 Erik return (0); 1882 8348 Eric } 1883 8348 Eric break; 1884 8348 Eric case SETFN_OPTCOM_NEGOTIATE: 1885 8348 Eric checkonly = B_FALSE; 1886 8348 Eric break; 1887 8348 Eric case SETFN_UD_NEGOTIATE: 1888 8348 Eric case SETFN_CONN_NEGOTIATE: 1889 8348 Eric checkonly = B_FALSE; 1890 8348 Eric /* 1891 8348 Eric * Negotiating local and "association-related" options 1892 8348 Eric * through T_UNITDATA_REQ. 1893 8348 Eric * 1894 8348 Eric * Following routine can filter out ones we do not 1895 8348 Eric * want to be "set" this way. 1896 8348 Eric */ 1897 8348 Eric if (!udp_opt_allow_udr_set(level, name)) { 1898 8348 Eric *outlenp = 0; 1899 11042 Erik return (EINVAL); 1900 8348 Eric } 1901 8348 Eric break; 1902 8348 Eric default: 1903 8348 Eric /* 1904 8348 Eric * We should never get here 1905 8348 Eric */ 1906 8348 Eric *outlenp = 0; 1907 11042 Erik return (EINVAL); 1908 8348 Eric } 1909 8348 Eric 1910 8348 Eric ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) || 1911 8348 Eric (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0)); 1912 8348 Eric 1913 11042 Erik if (thisdg_attrs != NULL) { 1914 11042 Erik /* Options from T_UNITDATA_REQ */ 1915 11042 Erik coa = (conn_opt_arg_t *)thisdg_attrs; 1916 11042 Erik ASSERT(coa->coa_connp == connp); 1917 11042 Erik ASSERT(coa->coa_ixa != NULL); 1918 11042 Erik ASSERT(coa->coa_ipp != NULL); 1919 11042 Erik ASSERT(coa->coa_ancillary); 1920 11042 Erik } else { 1921 11042 Erik coa = &coas; 1922 11042 Erik coas.coa_connp = connp; 1923 11042 Erik /* Get a reference on conn_ixa to prevent concurrent mods */ 1924 11042 Erik coas.coa_ixa = conn_get_ixa(connp, B_TRUE); 1925 11042 Erik if (coas.coa_ixa == NULL) { 1926 11042 Erik *outlenp = 0; 1927 11042 Erik return (ENOMEM); 1928 11042 Erik } 1929 11042 Erik coas.coa_ipp = &connp->conn_xmit_ipp; 1930 11042 Erik coas.coa_ancillary = B_FALSE; 1931 11042 Erik coas.coa_changed = 0; 1932 11042 Erik } 1933 11042 Erik 1934 11042 Erik err = udp_do_opt_set(coa, level, name, inlen, invalp, 1935 11042 Erik cr, checkonly); 1936 11042 Erik if (err != 0) { 1937 11042 Erik errout: 1938 11042 Erik if (!coa->coa_ancillary) 1939 11042 Erik ixa_refrele(coa->coa_ixa); 1940 11042 Erik *outlenp = 0; 1941 11042 Erik return (err); 1942 11042 Erik } 1943 11042 Erik /* Handle DHCPINIT here outside of lock */ 1944 11042 Erik if (level == IPPROTO_IP && name == IP_DHCPINIT_IF) { 1945 11042 Erik uint_t ifindex; 1946 11042 Erik ill_t *ill; 1947 11042 Erik 1948 11042 Erik ifindex = *(uint_t *)invalp; 1949 11042 Erik if (ifindex == 0) { 1950 11042 Erik ill = NULL; 1951 11042 Erik } else { 1952 11042 Erik ill = ill_lookup_on_ifindex(ifindex, B_FALSE, 1953 11042 Erik coa->coa_ixa->ixa_ipst); 1954 11042 Erik if (ill == NULL) { 1955 11042 Erik err = ENXIO; 1956 11042 Erik goto errout; 1957 11042 Erik } 1958 11042 Erik 1959 11042 Erik mutex_enter(&ill->ill_lock); 1960 11042 Erik if (ill->ill_state_flags & ILL_CONDEMNED) { 1961 11042 Erik mutex_exit(&ill->ill_lock); 1962 11042 Erik ill_refrele(ill); 1963 11042 Erik err = ENXIO; 1964 11042 Erik goto errout; 1965 11042 Erik } 1966 11042 Erik if (IS_VNI(ill)) { 1967 11042 Erik mutex_exit(&ill->ill_lock); 1968 11042 Erik ill_refrele(ill); 1969 11042 Erik err = EINVAL; 1970 11042 Erik goto errout; 1971 11042 Erik } 1972 11042 Erik } 1973 11042 Erik mutex_enter(&connp->conn_lock); 1974 11042 Erik 1975 11042 Erik if (connp->conn_dhcpinit_ill != NULL) { 1976 11042 Erik /* 1977 11042 Erik * We've locked the conn so conn_cleanup_ill() 1978 11042 Erik * cannot clear conn_dhcpinit_ill -- so it's 1979 11042 Erik * safe to access the ill. 1980 11042 Erik */ 1981 11042 Erik ill_t *oill = connp->conn_dhcpinit_ill; 1982 11042 Erik 1983 11042 Erik ASSERT(oill->ill_dhcpinit != 0); 1984 11042 Erik atomic_dec_32(&oill->ill_dhcpinit); 1985 11042 Erik ill_set_inputfn(connp->conn_dhcpinit_ill); 1986 11042 Erik connp->conn_dhcpinit_ill = NULL; 1987 11042 Erik } 1988 11042 Erik 1989 11042 Erik if (ill != NULL) { 1990 11042 Erik connp->conn_dhcpinit_ill = ill; 1991 11042 Erik atomic_inc_32(&ill->ill_dhcpinit); 1992 11042 Erik ill_set_inputfn(ill); 1993 11042 Erik mutex_exit(&connp->conn_lock); 1994 11042 Erik mutex_exit(&ill->ill_lock); 1995 11042 Erik ill_refrele(ill); 1996 11042 Erik } else { 1997 11042 Erik mutex_exit(&connp->conn_lock); 1998 11042 Erik } 1999 11042 Erik } 2000 11042 Erik 2001 11042 Erik /* 2002 11042 Erik * Common case of OK return with outval same as inval. 2003 11042 Erik */ 2004 11042 Erik if (invalp != outvalp) { 2005 11042 Erik /* don't trust bcopy for identical src/dst */ 2006 11042 Erik (void) bcopy(invalp, outvalp, inlen); 2007 11042 Erik } 2008 11042 Erik *outlenp = inlen; 2009 11042 Erik 2010 11042 Erik /* 2011 11042 Erik * If this was not ancillary data, then we rebuild the headers, 2012 11042 Erik * update the IRE/NCE, and IPsec as needed. 2013 11042 Erik * Since the label depends on the destination we go through 2014 11042 Erik * ip_set_destination first. 2015 11042 Erik */ 2016 11042 Erik if (coa->coa_ancillary) { 2017 11042 Erik return (0); 2018 11042 Erik } 2019 11042 Erik 2020 11042 Erik if (coa->coa_changed & COA_ROUTE_CHANGED) { 2021 11042 Erik in6_addr_t saddr, faddr, nexthop; 2022 11042 Erik in_port_t fport; 2023 11042 Erik 2024 11042 Erik /* 2025 11042 Erik * We clear lastdst to make sure we pick up the change 2026 11042 Erik * next time sending. 2027 11042 Erik * If we are connected we re-cache the information. 2028 11042 Erik * We ignore errors to preserve BSD behavior. 2029 11042 Erik * Note that we don't redo IPsec policy lookup here 2030 11042 Erik * since the final destination (or source) didn't change. 2031 11042 Erik */ 2032 11042 Erik mutex_enter(&connp->conn_lock); 2033 11042 Erik connp->conn_v6lastdst = ipv6_all_zeros; 2034 11042 Erik 2035 11042 Erik ip_attr_nexthop(coa->coa_ipp, coa->coa_ixa, 2036 11042 Erik &connp->conn_faddr_v6, &nexthop); 2037 11042 Erik saddr = connp->conn_saddr_v6; 2038 11042 Erik faddr = connp->conn_faddr_v6; 2039 11042 Erik fport = connp->conn_fport; 2040 11042 Erik mutex_exit(&connp->conn_lock); 2041 11042 Erik 2042 11042 Erik if (!IN6_IS_ADDR_UNSPECIFIED(&faddr) && 2043 11042 Erik !IN6_IS_ADDR_V4MAPPED_ANY(&faddr)) { 2044 11042 Erik (void) ip_attr_connect(connp, coa->coa_ixa, 2045 11042 Erik &saddr, &faddr, &nexthop, fport, NULL, NULL, 2046 11042 Erik IPDF_ALLOW_MCBC | IPDF_VERIFY_DST); 2047 11042 Erik } 2048 11042 Erik } 2049 11042 Erik 2050 11042 Erik ixa_refrele(coa->coa_ixa); 2051 11042 Erik 2052 11042 Erik if (coa->coa_changed & COA_HEADER_CHANGED) { 2053 11042 Erik /* 2054 11042 Erik * Rebuild the header template if we are connected. 2055 11042 Erik * Otherwise clear conn_v6lastdst so we rebuild the header 2056 11042 Erik * in the data path. 2057 11042 Erik */ 2058 11042 Erik mutex_enter(&connp->conn_lock); 2059 11042 Erik if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) && 2060 11042 Erik !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) { 2061 11042 Erik err = udp_build_hdr_template(connp, 2062 11042 Erik &connp->conn_saddr_v6, &connp->conn_faddr_v6, 2063 11042 Erik connp->conn_fport, connp->conn_flowinfo); 2064 11042 Erik if (err != 0) { 2065 11042 Erik mutex_exit(&connp->conn_lock); 2066 11042 Erik return (err); 2067 11042 Erik } 2068 11042 Erik } else { 2069 11042 Erik connp->conn_v6lastdst = ipv6_all_zeros; 2070 11042 Erik } 2071 11042 Erik mutex_exit(&connp->conn_lock); 2072 11042 Erik } 2073 11042 Erik if (coa->coa_changed & COA_RCVBUF_CHANGED) { 2074 11042 Erik (void) proto_set_rx_hiwat(connp->conn_rq, connp, 2075 11042 Erik connp->conn_rcvbuf); 2076 11042 Erik } 2077 11042 Erik if ((coa->coa_changed & COA_SNDBUF_CHANGED) && !IPCL_IS_NONSTR(connp)) { 2078 11042 Erik connp->conn_wq->q_hiwat = connp->conn_sndbuf; 2079 11042 Erik } 2080 11042 Erik if (coa->coa_changed & COA_WROFF_CHANGED) { 2081 11042 Erik /* Increase wroff if needed */ 2082 11042 Erik uint_t wroff; 2083 11042 Erik 2084 11042 Erik mutex_enter(&connp->conn_lock); 2085 11042 Erik wroff = connp->conn_ht_iphc_allocated + us->us_wroff_extra; 2086 11042 Erik if (udp->udp_nat_t_endpoint) 2087 11042 Erik wroff += sizeof (uint32_t); 2088 11042 Erik if (wroff > connp->conn_wroff) { 2089 11042 Erik connp->conn_wroff = wroff; 2090 11042 Erik mutex_exit(&connp->conn_lock); 2091 11042 Erik (void) proto_set_tx_wroff(connp->conn_rq, connp, wroff); 2092 11042 Erik } else { 2093 11042 Erik mutex_exit(&connp->conn_lock); 2094 11042 Erik } 2095 11042 Erik } 2096 11042 Erik return (err); 2097 11042 Erik } 2098 11042 Erik 2099 11042 Erik /* This routine sets socket options. */ 2100 8348 Eric int 2101 8348 Eric udp_tpi_opt_set(queue_t *q, uint_t optset_context, int level, int name, 2102 8348 Eric uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp, 2103 11042 Erik void *thisdg_attrs, cred_t *cr) 2104 11042 Erik { 2105 11042 Erik conn_t *connp = Q_TO_CONN(q); 2106 8348 Eric int error; 2107 11042 Erik 2108 8348 Eric error = udp_opt_set(connp, optset_context, level, name, inlen, invalp, 2109 8348 Eric outlenp, outvalp, thisdg_attrs, cr); 2110 11042 Erik return (error); 2111 11042 Erik } 2112 11042 Erik 2113 11042 Erik /* 2114 11042 Erik * Setup IP and UDP headers. 2115 11042 Erik * Returns NULL on allocation failure, in which case data_mp is freed. 2116 11042 Erik */ 2117 11042 Erik mblk_t * 2118 11042 Erik udp_prepend_hdr(conn_t *connp, ip_xmit_attr_t *ixa, const ip_pkt_t *ipp, 2119 11042 Erik const in6_addr_t *v6src, const in6_addr_t *v6dst, in_port_t dstport, 2120 11042 Erik uint32_t flowinfo, mblk_t *data_mp, int *errorp) 2121 11042 Erik { 2122 11042 Erik mblk_t *mp; 2123 11042 Erik udpha_t *udpha; 2124 11042 Erik udp_stack_t *us = connp->conn_netstack->netstack_udp; 2125 11042 Erik uint_t data_len; 2126 11042 Erik uint32_t cksum; 2127 11042 Erik udp_t *udp = connp->conn_udp; 2128 11042 Erik boolean_t insert_spi = udp->udp_nat_t_endpoint; 2129 11042 Erik uint_t ulp_hdr_len; 2130 11042 Erik 2131 11042 Erik data_len = msgdsize(data_mp); 2132 11042 Erik ulp_hdr_len = UDPH_SIZE; 2133 11042 Erik if (insert_spi) 2134 11042 Erik ulp_hdr_len += sizeof (uint32_t); 2135 11042 Erik 2136 11042 Erik mp = conn_prepend_hdr(ixa, ipp, v6src, v6dst, IPPROTO_UDP, flowinfo, 2137 11042 Erik ulp_hdr_len, data_mp, data_len, us->us_wroff_extra, &cksum, errorp); 2138 11042 Erik if (mp == NULL) { 2139 11042 Erik ASSERT(*errorp != 0); 2140 11042 Erik return (NULL); 2141 11042 Erik } 2142 11042 Erik 2143 11042 Erik data_len += ulp_hdr_len; 2144 11042 Erik ixa->ixa_pktlen = data_len + ixa->ixa_ip_hdr_length; 2145 11042 Erik 2146 11042 Erik udpha = (udpha_t *)(mp->b_rptr + ixa->ixa_ip_hdr_length); 2147 11042 Erik udpha->uha_src_port = connp->conn_lport; 2148 11042 Erik udpha->uha_dst_port = dstport; 2149 11042 Erik udpha->uha_checksum = 0; 2150 11042 Erik udpha->uha_length = htons(data_len); 2151 11042 Erik 2152 11042 Erik /* 2153 11042 Erik * If there was a routing option/header then conn_prepend_hdr 2154 11042 Erik * has massaged it and placed the pseudo-header checksum difference 2155 11042 Erik * in the cksum argument. 2156 11042 Erik * 2157 11042 Erik * Setup header length and prepare for ULP checksum done in IP. 2158 11042 Erik * 2159 11042 Erik * We make it easy for IP to include our pseudo header 2160 11042 Erik * by putting our length in uha_checksum. 2161 11042 Erik * The IP source, destination, and length have already been set by 2162 11042 Erik * conn_prepend_hdr. 2163 11042 Erik */ 2164 11042 Erik cksum += data_len; 2165 11042 Erik cksum = (cksum >> 16) + (cksum & 0xFFFF); 2166 11042 Erik ASSERT(cksum < 0x10000); 2167 11042 Erik 2168 11042 Erik if (ixa->ixa_flags & IXAF_IS_IPV4) { 2169 11042 Erik ipha_t *ipha = (ipha_t *)mp->b_rptr; 2170 11042 Erik 2171 11042 Erik ASSERT(ntohs(ipha->ipha_length) == ixa->ixa_pktlen); 2172 11042 Erik 2173 11042 Erik /* IP does the checksum if uha_checksum is non-zero */ 2174 11042 Erik if (us->us_do_checksum) { 2175 11042 Erik if (cksum == 0) 2176 11042 Erik udpha->uha_checksum = 0xffff; 2177 11042 Erik else 2178 11042 Erik udpha->uha_checksum = htons(cksum); 2179 11042 Erik } else { 2180 11042 Erik udpha->uha_checksum = 0; 2181 11042 Erik } 2182 11042 Erik } else { 2183 11042 Erik ip6_t *ip6h = (ip6_t *)mp->b_rptr; 2184 11042 Erik 2185 11042 Erik ASSERT(ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN == ixa->ixa_pktlen); 2186 11042 Erik if (cksum == 0) 2187 11042 Erik udpha->uha_checksum = 0xffff; 2188 11042 Erik else 2189 11042 Erik udpha->uha_checksum = htons(cksum); 2190 11042 Erik } 2191 11042 Erik 2192 11042 Erik /* Insert all-0s SPI now. */ 2193 11042 Erik if (insert_spi) 2194 11042 Erik *((uint32_t *)(udpha + 1)) = 0; 2195 11042 Erik 2196 11042 Erik return (mp); 2197 11042 Erik } 2198 11042 Erik 2199 11042 Erik static int 2200 11042 Erik udp_build_hdr_template(conn_t *connp, const in6_addr_t *v6src, 2201 11042 Erik const in6_addr_t *v6dst, in_port_t dstport, uint32_t flowinfo) 2202 11042 Erik { 2203 11042 Erik udpha_t *udpha; 2204 11042 Erik int error; 2205 11042 Erik 2206 11042 Erik ASSERT(MUTEX_HELD(&connp->conn_lock)); 2207 11042 Erik /* 2208 11042 Erik * We clear lastdst to make sure we don't use the lastdst path 2209 11042 Erik * next time sending since we might not have set v6dst yet. 2210 11042 Erik */ 2211 11042 Erik connp->conn_v6lastdst = ipv6_all_zeros; 2212 11042 Erik 2213 11042 Erik error = conn_build_hdr_template(connp, UDPH_SIZE, 0, v6src, v6dst, 2214 11042 Erik flowinfo); 2215 11042 Erik if (error != 0) 2216 11042 Erik return (error); 2217 11042 Erik 2218 11042 Erik /* 2219 11042 Erik * Any routing header/option has been massaged. The checksum difference 2220 11042 Erik * is stored in conn_sum. 2221 11042 Erik */ 2222 11042 Erik udpha = (udpha_t *)connp->conn_ht_ulp; 2223 11042 Erik udpha->uha_src_port = connp->conn_lport; 2224 11042 Erik udpha->uha_dst_port = dstport; 2225 11042 Erik udpha->uha_checksum = 0; 2226 11042 Erik udpha->uha_length = htons(UDPH_SIZE); /* Filled in later */ 2227 0 stevel return (0); 2228 0 stevel } 2229 0 stevel 2230 0 stevel /* 2231 0 stevel * This routine retrieves the value of an ND variable in a udpparam_t 2232 0 stevel * structure. It is called through nd_getset when a user reads the 2233 0 stevel * variable. 2234 0 stevel */ 2235 0 stevel /* ARGSUSED */ 2236 0 stevel static int 2237 0 stevel udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 2238 0 stevel { 2239 0 stevel udpparam_t *udppa = (udpparam_t *)cp; 2240 0 stevel 2241 0 stevel (void) mi_mpprintf(mp, "%d", udppa->udp_param_value); 2242 0 stevel return (0); 2243 0 stevel } 2244 0 stevel 2245 0 stevel /* 2246 0 stevel * Walk through the param array specified registering each element with the 2247 0 stevel * named dispatch (ND) handler. 2248 0 stevel */ 2249 0 stevel static boolean_t 2250 3448 dh155122 udp_param_register(IDP *ndp, udpparam_t *udppa, int cnt) 2251 0 stevel { 2252 0 stevel for (; cnt-- > 0; udppa++) { 2253 0 stevel if (udppa->udp_param_name && udppa->udp_param_name[0]) { 2254 3448 dh155122 if (!nd_load(ndp, udppa->udp_param_name, 2255 0 stevel udp_param_get, udp_param_set, 2256 0 stevel (caddr_t)udppa)) { 2257 3448 dh155122 nd_free(ndp); 2258 0 stevel return (B_FALSE); 2259 0 stevel } 2260 0 stevel } 2261 0 stevel } 2262 3448 dh155122 if (!nd_load(ndp, "udp_extra_priv_ports", 2263 0 stevel udp_extra_priv_ports_get, NULL, NULL)) { 2264 3448 dh155122 nd_free(ndp); 2265 0 stevel return (B_FALSE); 2266 0 stevel } 2267 3448 dh155122 if (!nd_load(ndp, "udp_extra_priv_ports_add", 2268 0 stevel NULL, udp_extra_priv_ports_add, NULL)) { 2269 3448 dh155122 nd_free(ndp); 2270 0 stevel return (B_FALSE); 2271 0 stevel } 2272 3448 dh155122 if (!nd_load(ndp, "udp_extra_priv_ports_del", 2273 0 stevel NULL, udp_extra_priv_ports_del, NULL)) { 2274 3448 dh155122 nd_free(ndp); 2275 0 stevel return (B_FALSE); 2276 0 stevel } 2277 0 stevel return (B_TRUE); 2278 0 stevel } 2279 0 stevel 2280 0 stevel /* This routine sets an ND variable in a udpparam_t structure. */ 2281 0 stevel /* ARGSUSED */ 2282 0 stevel static int 2283 0 stevel udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) 2284 0 stevel { 2285 0 stevel long new_value; 2286 0 stevel udpparam_t *udppa = (udpparam_t *)cp; 2287 0 stevel 2288 0 stevel /* 2289 0 stevel * Fail the request if the new value does not lie within the 2290 0 stevel * required bounds. 2291 0 stevel */ 2292 0 stevel if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 2293 0 stevel new_value < udppa->udp_param_min || 2294 0 stevel new_value > udppa->udp_param_max) { 2295 0 stevel return (EINVAL); 2296 0 stevel } 2297 0 stevel 2298 0 stevel /* Set the new value */ 2299 0 stevel udppa->udp_param_value = new_value; 2300 0 stevel return (0); 2301 1676 jpk } 2302 1676 jpk 2303 8963 Anders static mblk_t * 2304 8348 Eric udp_queue_fallback(udp_t *udp, mblk_t *mp) 2305 8348 Eric { 2306 8348 Eric ASSERT(MUTEX_HELD(&udp->udp_recv_lock)); 2307 8348 Eric if (IPCL_IS_NONSTR(udp->udp_connp)) { 2308 8348 Eric /* 2309 8348 Eric * fallback has started but messages have not been moved yet 2310 8348 Eric */ 2311 8348 Eric if (udp->udp_fallback_queue_head == NULL) { 2312 8348 Eric ASSERT(udp->udp_fallback_queue_tail == NULL); 2313 8348 Eric udp->udp_fallback_queue_head = mp; 2314 8348 Eric udp->udp_fallback_queue_tail = mp; 2315 8348 Eric } else { 2316 8348 Eric ASSERT(udp->udp_fallback_queue_tail != NULL); 2317 8348 Eric udp->udp_fallback_queue_tail->b_next = mp; 2318 8348 Eric udp->udp_fallback_queue_tail = mp; 2319 8348 Eric } 2320 8963 Anders return (NULL); 2321 8963 Anders } else { 2322 8963 Anders /* 2323 8963 Anders * Fallback completed, let the caller putnext() the mblk. 2324 8963 Anders */ 2325 8963 Anders return (mp); 2326 8963 Anders } 2327 8963 Anders } 2328 8963 Anders 2329 8963 Anders /* 2330 8963 Anders * Deliver data to ULP. In case we have a socket, and it's falling back to 2331 8963 Anders * TPI, then we'll queue the mp for later processing. 2332 8963 Anders */ 2333 8963 Anders static void 2334 11042 Erik udp_ulp_recv(conn_t *connp, mblk_t *mp, uint_t len, ip_recv_attr_t *ira) 2335 8963 Anders { 2336 8963 Anders if (IPCL_IS_NONSTR(connp)) { 2337 8963 Anders udp_t *udp = connp->conn_udp; 2338 8963 Anders int error; 2339 8963 Anders 2340 11042 Erik ASSERT(len == msgdsize(mp)); 2341 8963 Anders if ((*connp->conn_upcalls->su_recv) 2342 11042 Erik (connp->conn_upper_handle, mp, len, 0, &error, NULL) < 0) { 2343 8963 Anders mutex_enter(&udp->udp_recv_lock); 2344 8963 Anders if (error == ENOSPC) { 2345 8963 Anders /* 2346 8963 Anders * let's confirm while holding the lock 2347 8963 Anders */ 2348 8963 Anders if ((*connp->conn_upcalls->su_recv) 2349 8963 Anders (connp->conn_upper_handle, NULL, 0, 0, 2350 8963 Anders &error, NULL) < 0) { 2351 8963 Anders ASSERT(error == ENOSPC); 2352 8963 Anders if (error == ENOSPC) { 2353 8963 Anders connp->conn_flow_cntrld = 2354 8963 Anders B_TRUE; 2355 8963 Anders } 2356 8963 Anders } 2357 8963 Anders mutex_exit(&udp->udp_recv_lock); 2358 8963 Anders } else { 2359 8963 Anders ASSERT(error == EOPNOTSUPP); 2360 8963 Anders mp = udp_queue_fallback(udp, mp); 2361 8963 Anders mutex_exit(&udp->udp_recv_lock); 2362 8963 Anders if (mp != NULL) 2363 8963 Anders putnext(connp->conn_rq, mp); 2364 8963 Anders } 2365 8963 Anders } 2366 8963 Anders ASSERT(MUTEX_NOT_HELD(&udp->udp_recv_lock)); 2367 8963 Anders } else { 2368 11042 Erik if (is_system_labeled()) { 2369 11042 Erik ASSERT(ira->ira_cred != NULL); 2370 11042 Erik /* 2371 11042 Erik * Provide for protocols above UDP such as RPC 2372 11042 Erik * NOPID leaves db_cpid unchanged. 2373 11042 Erik */ 2374 11042 Erik mblk_setcred(mp, ira->ira_cred, NOPID); 2375 11042 Erik } 2376 11042 Erik 2377 8963 Anders putnext(connp->conn_rq, mp); 2378 5240 nordmark } 2379 5240 nordmark } 2380 5240 nordmark 2381 11042 Erik /* 2382 11042 Erik * This is the inbound data path. 2383 11042 Erik * IP has already pulled up the IP plus UDP headers and verified alignment 2384 11042 Erik * etc. 2385 11042 Erik */ 2386 5240 nordmark /* ARGSUSED2 */ 2387 5240 nordmark static void 2388 11042 Erik udp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 2389 11042 Erik { 2390 11042 Erik conn_t *connp = (conn_t *)arg1; 2391 0 stevel struct T_unitdata_ind *tudi; 2392 741 masputra uchar_t *rptr; /* Pointer to IP header */ 2393 741 masputra int hdr_length; /* Length of IP+UDP headers */ 2394 0 stevel int udi_size; /* Size of T_unitdata_ind */ 2395 11042 Erik int pkt_len; 2396 0 stevel udp_t *udp; 2397 0 stevel udpha_t *udpha; 2398 11042 Erik ip_pkt_t ipps; 2399 0 stevel ip6_t *ip6h; 2400 0 stevel mblk_t *mp1; 2401 11042 Erik uint32_t udp_ipv4_options_len; 2402 11042 Erik crb_t recv_ancillary; 2403 11042 Erik udp_stack_t *us; 2404 0 stevel 2405 5240 nordmark ASSERT(connp->conn_flags & IPCL_UDPCONN); 2406 0 stevel 2407 741 masputra udp = connp->conn_udp; 2408 3448 dh155122 us = udp->udp_us; 2409 0 stevel rptr = mp->b_rptr; 2410 11042 Erik 2411 11042 Erik ASSERT(DB_TYPE(mp) == M_DATA); 2412 741 masputra ASSERT(OK_32PTR(rptr)); 2413 11042 Erik ASSERT(ira->ira_pktlen == msgdsize(mp)); 2414 11042 Erik pkt_len = ira->ira_pktlen; 2415 11042 Erik 2416 11042 Erik /* 2417 11042 Erik * Get a snapshot of these and allow other threads to change 2418 11042 Erik * them after that. We need the same recv_ancillary when determining 2419 11042 Erik * the size as when adding the ancillary data items. 2420 11042 Erik */ 2421 11042 Erik mutex_enter(&connp->conn_lock); 2422 11042 Erik udp_ipv4_options_len = udp->udp_recv_ipp.ipp_ipv4_options_len; 2423 11042 Erik recv_ancillary = connp->conn_recv_ancillary; 2424 11042 Erik mutex_exit(&connp->conn_lock); 2425 11042 Erik 2426 11042 Erik hdr_length = ira->ira_ip_hdr_length; 2427 0 stevel 2428 0 stevel /* 2429 0 stevel * IP inspected the UDP header thus all of it must be in the mblk. 2430 0 stevel * UDP length check is performed for IPv6 packets and IPv4 packets 2431 5240 nordmark * to check if the size of the packet as specified 2432 11042 Erik * by the UDP header is the same as the length derived from the IP 2433 11042 Erik * header. 2434 11042 Erik */ 2435 11042 Erik udpha = (udpha_t *)(rptr + hdr_length); 2436 11042 Erik if (pkt_len != ntohs(udpha->uha_length) + hdr_length) 2437 0 stevel goto tossit; 2438 11042 Erik 2439 11042 Erik hdr_length += UDPH_SIZE; 2440 11042 Erik ASSERT(MBLKL(mp) >= hdr_length); /* IP did a pullup */ 2441 11042 Erik 2442 11042 Erik /* Initialize regardless of IP version */ 2443 11042 Erik ipps.ipp_fields = 0; 2444 11042 Erik 2445 11042 Erik if (((ira->ira_flags & IRAF_IPV4_OPTIONS) || 2446 11042 Erik udp_ipv4_options_len > 0) && 2447 11042 Erik connp->conn_family == AF_INET) { 2448 11042 Erik int err; 2449 11042 Erik 2450 11042 Erik /* 2451 11042 Erik * Record/update udp_recv_ipp with the lock 2452 11042 Erik * held. Not needed for AF_INET6 sockets 2453 11042 Erik * since they don't support a getsockopt of IP_OPTIONS. 2454 11042 Erik */ 2455 11042 Erik mutex_enter(&connp->conn_lock); 2456 11042 Erik err = ip_find_hdr_v4((ipha_t *)rptr, &udp->udp_recv_ipp, 2457 11042 Erik B_TRUE); 2458 11042 Erik if (err != 0) { 2459 11042 Erik /* Allocation failed. Drop packet */ 2460 11042 Erik mutex_exit(&connp->conn_lock); 2461 11042 Erik freemsg(mp); 2462 11042 Erik BUMP_MIB(&us->us_udp_mib, udpInErrors); 2463 11042 Erik return; 2464 11042 Erik } 2465 11042 Erik mutex_exit(&connp->conn_lock); 2466 11042 Erik } 2467 11042 Erik 2468 11042 Erik if (recv_ancillary.crb_all != 0) { 2469 11042 Erik /* 2470 11042 Erik * Record packet information in the ip_pkt_t 2471 11042 Erik */ 2472 11042 Erik if (ira->ira_flags & IRAF_IS_IPV4) { 2473 11042 Erik ASSERT(IPH_HDR_VERSION(rptr) == IPV4_VERSION); 2474 11042 Erik ASSERT(MBLKL(mp) >= sizeof (ipha_t)); 2475 11042 Erik ASSERT(((ipha_t *)rptr)->ipha_protocol == IPPROTO_UDP); 2476 11042 Erik ASSERT(ira->ira_ip_hdr_length == IPH_HDR_LENGTH(rptr)); 2477 11042 Erik 2478 11042 Erik (void) ip_find_hdr_v4((ipha_t *)rptr, &ipps, B_FALSE); 2479 11042 Erik } else { 2480 11042 Erik uint8_t nexthdrp; 2481 11042 Erik 2482 11042 Erik ASSERT(IPH_HDR_VERSION(rptr) == IPV6_VERSION); 2483 11042 Erik /* 2484 11042 Erik * IPv6 packets can only be received by applications 2485 11042 Erik * that are prepared to receive IPv6 addresses. 2486 11042 Erik * The IP fanout must ensure this. 2487 11042 Erik */ 2488 11042 Erik ASSERT(connp->conn_family == AF_INET6); 2489 11042 Erik 2490 11042 Erik ip6h = (ip6_t *)rptr; 2491 11042 Erik 2492 11042 Erik /* We don't care about the length, but need the ipp */ 2493 11042 Erik hdr_length = ip_find_hdr_v6(mp, ip6h, B_TRUE, &ipps, 2494 11042 Erik &nexthdrp); 2495 11042 Erik ASSERT(hdr_length == ira->ira_ip_hdr_length); 2496 11042 Erik /* Restore */ 2497 11042 Erik hdr_length = ira->ira_ip_hdr_length + UDPH_SIZE; 2498 11042 Erik ASSERT(nexthdrp == IPPROTO_UDP); 2499 11042 Erik } 2500 741 masputra } 2501 0 stevel 2502 0 stevel /* 2503 0 stevel * This is the inbound data path. Packets are passed upstream as 2504 11042 Erik * T_UNITDATA_IND messages. 2505 11042 Erik */ 2506 11042 Erik if (connp->conn_family == AF_INET) { 2507 0 stevel sin_t *sin; 2508 0 stevel 2509 0 stevel ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION); 2510 0 stevel 2511 0 stevel /* 2512 5240 nordmark * Normally only send up the source address. 2513 11042 Erik * If any ancillary data items are wanted we add those. 2514 0 stevel */ 2515 0 stevel udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 2516 11042 Erik if (recv_ancillary.crb_all != 0) { 2517 11042 Erik udi_size += conn_recvancillary_size(connp, 2518 11042 Erik recv_ancillary, ira, mp, &ipps); 2519 1673 gt145670 } 2520 0 stevel 2521 0 stevel /* Allocate a message block for the T_UNITDATA_IND structure. */ 2522 0 stevel mp1 = allocb(udi_size, BPRI_MED); 2523 0 stevel if (mp1 == NULL) { 2524 0 stevel freemsg(mp); 2525 5240 nordmark BUMP_MIB(&us->us_udp_mib, udpInErrors); 2526 0 stevel return; 2527 0 stevel } 2528 0 stevel mp1->b_cont = mp; 2529 11042 Erik mp1->b_datap->db_type = M_PROTO; 2530 11042 Erik tudi = (struct T_unitdata_ind *)mp1->b_rptr; 2531 11042 Erik mp1->b_wptr = (uchar_t *)tudi + udi_size; 2532 0 stevel tudi->PRIM_type = T_UNITDATA_IND; 2533 0 stevel tudi->SRC_length = sizeof (sin_t); 2534 0 stevel tudi->SRC_offset = sizeof (struct T_unitdata_ind); 2535 0 stevel tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 2536 0 stevel sizeof (sin_t); 2537 0 stevel udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t)); 2538 0 stevel tudi->OPT_length = udi_size; 2539 0 stevel sin = (sin_t *)&tudi[1]; 2540 0 stevel sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src; 2541 0 stevel sin->sin_port = udpha->uha_src_port; 2542 11042 Erik sin->sin_family = connp->conn_family; 2543 0 stevel *(uint32_t *)&sin->sin_zero[0] = 0; 2544 0 stevel *(uint32_t *)&sin->sin_zero[4] = 0; 2545 0 stevel 2546 0 stevel /* 2547 0 stevel * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or 2548 0 stevel * IP_RECVTTL has been set. 2549 0 stevel */ 2550 0 stevel if (udi_size != 0) { 2551 11042 Erik conn_recvancillary_add(connp, recv_ancillary, ira, 2552 11042 Erik &ipps, (uchar_t *)&sin[1], udi_size); 2553 0 stevel } 2554 0 stevel } else { 2555 0 stevel sin6_t *sin6; 2556 0 stevel 2557 0 stevel /* 2558 0 stevel * Handle both IPv4 and IPv6 packets for IPv6 sockets. 2559 0 stevel * 2560 0 stevel * Normally we only send up the address. If receiving of any 2561 0 stevel * optional receive side information is enabled, we also send 2562 0 stevel * that up as options. 2563 0 stevel */ 2564 0 stevel udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t); 2565 0 stevel 2566 11042 Erik if (recv_ancillary.crb_all != 0) { 2567 11042 Erik udi_size += conn_recvancillary_size(connp, 2568 11042 Erik recv_ancillary, ira, mp, &ipps); 2569 741 masputra } 2570 0 stevel 2571 0 stevel mp1 = allocb(udi_size, BPRI_MED); 2572 0 stevel if (mp1 == NULL) { 2573 0 stevel freemsg(mp); 2574 5240 nordmark BUMP_MIB(&us->us_udp_mib, udpInErrors); 2575 0 stevel return; 2576 0 stevel } 2577 0 stevel mp1->b_cont = mp; 2578 11042 Erik mp1->b_datap->db_type = M_PROTO; 2579 11042 Erik tudi = (struct T_unitdata_ind *)mp1->b_rptr; 2580 11042 Erik mp1->b_wptr = (uchar_t *)tudi + udi_size; 2581 0 stevel tudi->PRIM_type = T_UNITDATA_IND; 2582 0 stevel tudi->SRC_length = sizeof (sin6_t); 2583 0 stevel tudi->SRC_offset = sizeof (struct T_unitdata_ind); 2584 0 stevel tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 2585 0 stevel sizeof (sin6_t); 2586 0 stevel udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin6_t)); 2587 0 stevel tudi->OPT_length = udi_size; 2588 0 stevel sin6 = (sin6_t *)&tudi[1]; 2589 11042 Erik if (ira->ira_flags & IRAF_IS_IPV4) { 2590 0 stevel in6_addr_t v6dst; 2591 0 stevel 2592 0 stevel IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_src, 2593 0 stevel &sin6->sin6_addr); 2594 0 stevel IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_dst, 2595 0 stevel &v6dst); 2596 0 stevel sin6->sin6_flowinfo = 0; 2597 0 stevel sin6->sin6_scope_id = 0; 2598 0 stevel sin6->__sin6_src_id = ip_srcid_find_addr(&v6dst, 2599 11042 Erik IPCL_ZONEID(connp), us->us_netstack); 2600 11042 Erik } else { 2601 11042 Erik ip6h = (ip6_t *)rptr; 2602 11042 Erik 2603 0 stevel sin6->sin6_addr = ip6h->ip6_src; 2604 0 stevel /* No sin6_flowinfo per API */ 2605 0 stevel sin6->sin6_flowinfo = 0; 2606 11042 Erik /* For link-scope pass up scope id */ 2607 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) 2608 11042 Erik sin6->sin6_scope_id = ira->ira_ruifindex; 2609 0 stevel else 2610 0 stevel sin6->sin6_scope_id = 0; 2611 741 masputra sin6->__sin6_src_id = ip_srcid_find_addr( 2612 11042 Erik &ip6h->ip6_dst, IPCL_ZONEID(connp), 2613 3448 dh155122 us->us_netstack); 2614 0 stevel } 2615 0 stevel sin6->sin6_port = udpha->uha_src_port; 2616 11042 Erik sin6->sin6_family = connp->conn_family; 2617 0 stevel 2618 0 stevel if (udi_size != 0) { 2619 11042 Erik conn_recvancillary_add(connp, recv_ancillary, ira, 2620 11042 Erik &ipps, (uchar_t *)&sin6[1], udi_size); 2621 11042 Erik } 2622 11042 Erik } 2623 11042 Erik 2624 11042 Erik /* Walk past the headers unless IP_RECVHDR was set. */ 2625 11042 Erik if (!udp->udp_rcvhdr) { 2626 11042 Erik mp->b_rptr = rptr + hdr_length; 2627 11042 Erik pkt_len -= hdr_length; 2628 0 stevel } 2629 0 stevel 2630 5240 nordmark BUMP_MIB(&us->us_udp_mib, udpHCInDatagrams); 2631 11042 Erik udp_ulp_recv(connp, mp1, pkt_len, ira); 2632 741 masputra return; 2633 741 masputra 2634 741 masputra tossit: 2635 741 masputra freemsg(mp); 2636 5240 nordmark BUMP_MIB(&us->us_udp_mib, udpInErrors); 2637 5240 nordmark } 2638 5240 nordmark 2639 5240 nordmark /* 2640 5240 nordmark * return SNMP stuff in buffer in mpdata. We don't hold any lock and report 2641 5240 nordmark * information that can be changing beneath us. 2642 5240 nordmark */ 2643 5240 nordmark mblk_t * 2644 0 stevel udp_snmp_get(queue_t *q, mblk_t *mpctl) 2645 0 stevel { 2646 0 stevel mblk_t *mpdata; 2647 0 stevel mblk_t *mp_conn_ctl; 2648 1676 jpk mblk_t *mp_attr_ctl; 2649 0 stevel mblk_t *mp6_conn_ctl; 2650 1676 jpk mblk_t *mp6_attr_ctl; 2651 1676 jpk mblk_t *mp_conn_tail; 2652 1676 jpk mblk_t *mp_attr_tail; 2653 1676 jpk mblk_t *mp6_conn_tail; 2654 1676 jpk mblk_t *mp6_attr_tail; 2655 0 stevel struct opthdr *optp; 2656 0 stevel mib2_udpEntry_t ude; 2657 0 stevel mib2_udp6Entry_t ude6; 2658 1676 jpk mib2_transportMLPEntry_t mlp; 2659 0 stevel int state; 2660 0 stevel zoneid_t zoneid; 2661 741 masputra int i; 2662 741 masputra connf_t *connfp; 2663 741 masputra conn_t *connp = Q_TO_CONN(q); 2664 1676 jpk int v4_conn_idx; 2665 1676 jpk int v6_conn_idx; 2666 1676 jpk boolean_t needattr; 2667 5240 nordmark udp_t *udp; 2668 3448 dh155122 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 2669 5240 nordmark udp_stack_t *us = connp->conn_netstack->netstack_udp; 2670 5240 nordmark mblk_t *mp2ctl; 2671 5240 nordmark 2672 5240 nordmark /* 2673 5240 nordmark * make a copy of the original message 2674 5240 nordmark */ 2675 5240 nordmark mp2ctl = copymsg(mpctl); 2676 1676 jpk 2677 1676 jpk mp_conn_ctl = mp_attr_ctl = mp6_conn_ctl = NULL; 2678 0 stevel if (mpctl == NULL || 2679 0 stevel (mpdata = mpctl->b_cont) == NULL || 2680 0 stevel (mp_conn_ctl = copymsg(mpctl)) == NULL || 2681 1676 jpk (mp_attr_ctl = copymsg(mpctl)) == NULL || 2682 1676 jpk (mp6_conn_ctl = copymsg(mpctl)) == NULL || 2683 1676 jpk (mp6_attr_ctl = copymsg(mpctl)) == NULL) { 2684 0 stevel freemsg(mp_conn_ctl); 2685 1676 jpk freemsg(mp_attr_ctl); 2686 1676 jpk freemsg(mp6_conn_ctl); 2687 5240 nordmark freemsg(mpctl); 2688 5240 nordmark freemsg(mp2ctl); 2689 0 stevel return (0); 2690 0 stevel } 2691 0 stevel 2692 741 masputra zoneid = connp->conn_zoneid; 2693 0 stevel 2694 0 stevel /* fixed length structure for IPv4 and IPv6 counters */ 2695 5240 nordmark SET_MIB(us->us_udp_mib.udpEntrySize, sizeof (mib2_udpEntry_t)); 2696 5240 nordmark SET_MIB(us->us_udp_mib.udp6EntrySize, sizeof (mib2_udp6Entry_t)); 2697 3284 apersson /* synchronize 64- and 32-bit counters */ 2698 5240 nordmark SYNC32_MIB(&us->us_udp_mib, udpInDatagrams, udpHCInDatagrams); 2699 5240 nordmark SYNC32_MIB(&us->us_udp_mib, udpOutDatagrams, udpHCOutDatagrams); 2700 3284 apersson 2701 0 stevel optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 2702 0 stevel optp->level = MIB2_UDP; 2703 0 stevel optp->name = 0; 2704 5240 nordmark (void) snmp_append_data(mpdata, (char *)&us->us_udp_mib, 2705 5240 nordmark sizeof (us->us_udp_mib)); 2706 0 stevel optp->len = msgdsize(mpdata); 2707 0 stevel qreply(q, mpctl); 2708 0 stevel 2709 1676 jpk mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL; 2710 1676 jpk v4_conn_idx = v6_conn_idx = 0; 2711 1676 jpk 2712 741 masputra for (i = 0; i < CONN_G_HASH_SIZE; i++) { 2713 3448 dh155122 connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 2714 741 masputra connp = NULL; 2715 741 masputra 2716 741 masputra while ((connp = ipcl_get_next_conn(connfp, connp, 2717 5240 nordmark IPCL_UDPCONN))) { 2718 741 masputra udp = connp->conn_udp; 2719 741 masputra if (zoneid != connp->conn_zoneid) 2720 741 masputra continue; 2721 741 masputra 2722 741 masputra /* 2723 741 masputra * Note that the port numbers are sent in 2724 741 masputra * host byte order 2725 741 masputra */ 2726 741 masputra 2727 741 masputra if (udp->udp_state == TS_UNBND) 2728 741 masputra state = MIB2_UDP_unbound; 2729 741 masputra else if (udp->udp_state == TS_IDLE) 2730 741 masputra state = MIB2_UDP_idle; 2731 741 masputra else if (udp->udp_state == TS_DATA_XFER) 2732 741 masputra state = MIB2_UDP_connected; 2733 741 masputra else 2734 741 masputra state = MIB2_UDP_unknown; 2735 1676 jpk 2736 1676 jpk needattr = B_FALSE; 2737 1676 jpk bzero(&mlp, sizeof (mlp)); 2738 1676 jpk if (connp->conn_mlp_type != mlptSingle) { 2739 1676 jpk if (connp->conn_mlp_type == mlptShared || 2740 1676 jpk connp->conn_mlp_type == mlptBoth) 2741 1676 jpk mlp.tme_flags |= MIB2_TMEF_SHARED; 2742 1676 jpk if (connp->conn_mlp_type == mlptPrivate || 2743 1676 jpk connp->conn_mlp_type == mlptBoth) 2744 1676 jpk mlp.tme_flags |= MIB2_TMEF_PRIVATE; 2745 1676 jpk needattr = B_TRUE; 2746 1676 jpk } 2747 9710 Ken if (connp->conn_anon_mlp) { 2748 9710 Ken mlp.tme_flags |= MIB2_TMEF_ANONMLP; 2749 9710 Ken needattr = B_TRUE; 2750 9710 Ken } 2751 10934 sommerfeld switch (connp->conn_mac_mode) { 2752 10934 sommerfeld case CONN_MAC_DEFAULT: 2753 10934 sommerfeld break; 2754 10934 sommerfeld case CONN_MAC_AWARE: 2755 9710 Ken mlp.tme_flags |= MIB2_TMEF_MACEXEMPT; 2756 9710 Ken needattr = B_TRUE; 2757 10934 sommerfeld break; 2758 10934 sommerfeld case CONN_MAC_IMPLICIT: 2759 10934 sommerfeld mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT; 2760 10934 sommerfeld needattr = B_TRUE; 2761 10934 sommerfeld break; 2762 9710 Ken } 2763 11042 Erik mutex_enter(&connp->conn_lock); 2764 11042 Erik if (udp->udp_state == TS_DATA_XFER && 2765 11042 Erik connp->conn_ixa->ixa_tsl != NULL) { 2766 11042 Erik ts_label_t *tsl; 2767 11042 Erik 2768 11042 Erik tsl = connp->conn_ixa->ixa_tsl; 2769 11042 Erik mlp.tme_flags |= MIB2_TMEF_IS_LABELED; 2770 11042 Erik mlp.tme_doi = label2doi(tsl); 2771 11042 Erik mlp.tme_label = *label2bslabel(tsl); 2772 11042 Erik needattr = B_TRUE; 2773 11042 Erik } 2774 11042 Erik mutex_exit(&connp->conn_lock); 2775 741 masputra 2776 741 masputra /* 2777 741 masputra * Create an IPv4 table entry for IPv4 entries and also 2778 741 masputra * any IPv6 entries which are bound to in6addr_any 2779 741 masputra * (i.e. anything a IPv4 peer could connect/send to). 2780 741 masputra */ 2781 11042 Erik if (connp->conn_ipversion == IPV4_VERSION || 2782 741 masputra (udp->udp_state <= TS_IDLE && 2783 11042 Erik IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) { 2784 741 masputra ude.udpEntryInfo.ue_state = state; 2785 741 masputra /* 2786 741 masputra * If in6addr_any this will set it to 2787 741 masputra * INADDR_ANY 2788 741 masputra */ 2789 11042 Erik ude.udpLocalAddress = connp->conn_laddr_v4; 2790 11042 Erik ude.udpLocalPort = ntohs(connp->conn_lport); 2791 741 masputra if (udp->udp_state == TS_DATA_XFER) { 2792 741 masputra /* 2793 741 masputra * Can potentially get here for 2794 741 masputra * v6 socket if another process 2795 741 masputra * (say, ping) has just done a 2796 741 masputra * sendto(), changing the state 2797 741 masputra * from the TS_IDLE above to 2798 741 masputra * TS_DATA_XFER by the time we hit 2799 741 masputra * this part of the code. 2800 741 masputra */ 2801 741 masputra ude.udpEntryInfo.ue_RemoteAddress = 2802 11042 Erik connp->conn_faddr_v4; 2803 741 masputra ude.udpEntryInfo.ue_RemotePort = 2804 11042 Erik ntohs(connp->conn_fport); 2805 741 masputra } else { 2806 741 masputra ude.udpEntryInfo.ue_RemoteAddress = 0; 2807 741 masputra ude.udpEntryInfo.ue_RemotePort = 0; 2808 741 masputra } 2809 3284 apersson 2810 3284 apersson /* 2811 3284 apersson * We make the assumption that all udp_t 2812 3284 apersson * structs will be created within an address 2813 3284 apersson * region no larger than 32-bits. 2814 3284 apersson */ 2815 3284 apersson ude.udpInstance = (uint32_t)(uintptr_t)udp; 2816 3284 apersson ude.udpCreationProcess = 2817 11042 Erik (connp->conn_cpid < 0) ? 2818 3284 apersson MIB2_UNKNOWN_PROCESS : 2819 11042 Erik connp->conn_cpid; 2820 11042 Erik ude.udpCreationTime = connp->conn_open_time; 2821 3284 apersson 2822 1676 jpk (void) snmp_append_data2(mp_conn_ctl->b_cont, 2823 741 masputra &mp_conn_tail, (char *)&ude, sizeof (ude)); 2824 1676 jpk mlp.tme_connidx = v4_conn_idx++; 2825 1676 jpk if (needattr) 2826 1676 jpk (void) snmp_append_data2( 2827 1676 jpk mp_attr_ctl->b_cont, &mp_attr_tail, 2828 1676 jpk (char *)&mlp, sizeof (mlp)); 2829 741 masputra } 2830 11042 Erik if (connp->conn_ipversion == IPV6_VERSION) { 2831 741 masputra ude6.udp6EntryInfo.ue_state = state; 2832 11042 Erik ude6.udp6LocalAddress = connp->conn_laddr_v6; 2833 11042 Erik ude6.udp6LocalPort = ntohs(connp->conn_lport); 2834 11042 Erik mutex_enter(&connp->conn_lock); 2835 11042 Erik if (connp->conn_ixa->ixa_flags & 2836 11042 Erik IXAF_SCOPEID_SET) { 2837 11042 Erik ude6.udp6IfIndex = 2838 11042 Erik connp->conn_ixa->ixa_scopeid; 2839 11042 Erik } else { 2840 11042 Erik ude6.udp6IfIndex = connp->conn_bound_if; 2841 11042 Erik } 2842 11042 Erik mutex_exit(&connp->conn_lock); 2843 741 masputra if (udp->udp_state == TS_DATA_XFER) { 2844 741 masputra ude6.udp6EntryInfo.ue_RemoteAddress = 2845 11042 Erik connp->conn_faddr_v6; 2846 741 masputra ude6.udp6EntryInfo.ue_RemotePort = 2847 11042 Erik ntohs(connp->conn_fport); 2848 741 masputra } else { 2849 741 masputra ude6.udp6EntryInfo.ue_RemoteAddress = 2850 741 masputra sin6_null.sin6_addr; 2851 741 masputra ude6.udp6EntryInfo.ue_RemotePort = 0; 2852 741 masputra } 2853 3284 apersson /* 2854 3284 apersson * We make the assumption that all udp_t 2855 3284 apersson * structs will be created within an address 2856 3284 apersson * region no larger than 32-bits. 2857 3284 apersson */ 2858 3284 apersson ude6.udp6Instance = (uint32_t)(uintptr_t)udp; 2859 3284 apersson ude6.udp6CreationProcess = 2860 11042 Erik (connp->conn_cpid < 0) ? 2861 3284 apersson MIB2_UNKNOWN_PROCESS : 2862 11042 Erik connp->conn_cpid; 2863 11042 Erik ude6.udp6CreationTime = connp->conn_open_time; 2864 3284 apersson 2865 1676 jpk (void) snmp_append_data2(mp6_conn_ctl->b_cont, 2866 741 masputra &mp6_conn_tail, (char *)&ude6, 2867 741 masputra sizeof (ude6)); 2868 1676 jpk mlp.tme_connidx = v6_conn_idx++; 2869 1676 jpk if (needattr) 2870 1676 jpk (void) snmp_append_data2( 2871 1676 jpk mp6_attr_ctl->b_cont, 2872 1676 jpk &mp6_attr_tail, (char *)&mlp, 2873 1676 jpk sizeof (mlp)); 2874 741 masputra } 2875 741 masputra } 2876 741 masputra } 2877 0 stevel 2878 0 stevel /* IPv4 UDP endpoints */ 2879 0 stevel optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 2880 0 stevel sizeof (struct T_optmgmt_ack)]; 2881 0 stevel optp->level = MIB2_UDP; 2882 0 stevel optp->name = MIB2_UDP_ENTRY; 2883 1676 jpk optp->len = msgdsize(mp_conn_ctl->b_cont); 2884 0 stevel qreply(q, mp_conn_ctl); 2885 1676 jpk 2886 1676 jpk /* table of MLP attributes... */ 2887 1676 jpk optp = (struct opthdr *)&mp_attr_ctl->b_rptr[ 2888 1676 jpk sizeof (struct T_optmgmt_ack)]; 2889 1676 jpk optp->level = MIB2_UDP; 2890 1676 jpk optp->name = EXPER_XPORT_MLP; 2891 1676 jpk optp->len = msgdsize(mp_attr_ctl->b_cont); 2892 1676 jpk if (optp->len == 0) 2893 1676 jpk freemsg(mp_attr_ctl); 2894 1676 jpk else 2895 1676 jpk qreply(q, mp_attr_ctl); 2896 0 stevel 2897 0 stevel /* IPv6 UDP endpoints */ 2898 0 stevel optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 2899 0 stevel sizeof (struct T_optmgmt_ack)]; 2900 0 stevel optp->level = MIB2_UDP6; 2901 0 stevel optp->name = MIB2_UDP6_ENTRY; 2902 1676 jpk optp->len = msgdsize(mp6_conn_ctl->b_cont); 2903 0 stevel qreply(q, mp6_conn_ctl); 2904 1676 jpk 2905 1676 jpk /* table of MLP attributes... */ 2906 1676 jpk optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[ 2907 1676 jpk sizeof (struct T_optmgmt_ack)]; 2908 1676 jpk optp->level = MIB2_UDP6; 2909 1676 jpk optp->name = EXPER_XPORT_MLP; 2910 1676 jpk optp->len = msgdsize(mp6_attr_ctl->b_cont); 2911 1676 jpk if (optp->len == 0) 2912 1676 jpk freemsg(mp6_attr_ctl); 2913 1676 jpk else 2914 1676 jpk qreply(q, mp6_attr_ctl); 2915 0 stevel 2916 5240 nordmark return (mp2ctl); 2917 0 stevel } 2918 0 stevel 2919 0 stevel /* 2920 0 stevel * Return 0 if invalid set request, 1 otherwise, including non-udp requests. 2921 0 stevel * NOTE: Per MIB-II, UDP has no writable data. 2922 0 stevel * TODO: If this ever actually tries to set anything, it needs to be 2923 0 stevel * to do the appropriate locking. 2924 0 stevel */ 2925 0 stevel /* ARGSUSED */ 2926 741 masputra int 2927 0 stevel udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name, 2928 0 stevel uchar_t *ptr, int len) 2929 0 stevel { 2930 0 stevel switch (level) { 2931 0 stevel case MIB2_UDP: 2932 0 stevel return (0); 2933 0 stevel default: 2934 0 stevel return (1); 2935 0 stevel } 2936 0 stevel } 2937 0 stevel 2938 0 stevel /* 2939 0 stevel * This routine creates a T_UDERROR_IND message and passes it upstream. 2940 0 stevel * The address and options are copied from the T_UNITDATA_REQ message 2941 0 stevel * passed in mp. This message is freed. 2942 0 stevel */ 2943 0 stevel static void 2944 11042 Erik udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err) 2945 741 masputra { 2946 741 masputra struct T_unitdata_req *tudr; 2947 0 stevel mblk_t *mp1; 2948 11042 Erik uchar_t *destaddr; 2949 11042 Erik t_scalar_t destlen; 2950 741 masputra uchar_t *optaddr; 2951 741 masputra t_scalar_t optlen; 2952 741 masputra 2953 11042 Erik if ((mp->b_wptr < mp->b_rptr) || 2954 11042 Erik (MBLKL(mp)) < sizeof (struct T_unitdata_req)) { 2955 11042 Erik goto done; 2956 11042 Erik } 2957 11042 Erik tudr = (struct T_unitdata_req *)mp->b_rptr; 2958 11042 Erik destaddr = mp->b_rptr + tudr->DEST_offset; 2959 11042 Erik if (destaddr < mp->b_rptr || destaddr >= mp->b_wptr || 2960 11042 Erik destaddr + tudr->DEST_length < mp->b_rptr || 2961 11042 Erik destaddr + tudr->DEST_length > mp->b_wptr) { 2962 11042 Erik goto done; 2963 11042 Erik } 2964 11042 Erik optaddr = mp->b_rptr + tudr->OPT_offset; 2965 11042 Erik if (optaddr < mp->b_rptr || optaddr >= mp->b_wptr || 2966 11042 Erik optaddr + tudr->OPT_length < mp->b_rptr || 2967 11042 Erik optaddr + tudr->OPT_length > mp->b_wptr) { 2968 11042 Erik goto done; 2969 11042 Erik } 2970 11042 Erik destlen = tudr->DEST_length; 2971 11042 Erik optlen = tudr->OPT_length; 2972 741 masputra 2973 741 masputra mp1 = mi_tpi_uderror_ind((char *)destaddr, destlen, 2974 741 masputra (char *)optaddr, optlen, err); 2975 741 masputra if (mp1 != NULL) 2976 5240 nordmark qreply(q, mp1); 2977 0 stevel 2978 0 stevel done: 2979 0 stevel freemsg(mp); 2980 0 stevel