1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* Copyright (c) 1990 Mentat Inc. */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 const char udp_version[] = "%Z%%M% %I% %E% SMI"; 31 32 #include <sys/types.h> 33 #include <sys/stream.h> 34 #include <sys/stropts.h> 35 #include <sys/strlog.h> 36 #include <sys/strsun.h> 37 #define _SUN_TPI_VERSION 2 38 #include <sys/tihdr.h> 39 #include <sys/timod.h> 40 #include <sys/tiuser.h> 41 #include <sys/ddi.h> 42 #include <sys/sunddi.h> 43 #include <sys/strsubr.h> 44 #include <sys/suntpi.h> 45 #include <sys/xti_inet.h> 46 #include <sys/cmn_err.h> 47 #include <sys/kmem.h> 48 #include <sys/policy.h> 49 #include <sys/ucred.h> 50 #include <sys/zone.h> 51 52 #include <sys/socket.h> 53 #include <sys/vtrace.h> 54 #include <sys/debug.h> 55 #include <sys/isa_defs.h> 56 #include <sys/random.h> 57 #include <netinet/in.h> 58 #include <netinet/ip6.h> 59 #include <netinet/icmp6.h> 60 #include <netinet/udp.h> 61 #include <net/if.h> 62 63 #include <inet/common.h> 64 #include <inet/ip.h> 65 #include <inet/ip6.h> 66 #include <inet/ip_ire.h> 67 #include <inet/mi.h> 68 #include <inet/mib2.h> 69 #include <inet/nd.h> 70 #include <inet/optcom.h> 71 #include <inet/snmpcom.h> 72 #include <inet/kstatcom.h> 73 #include <inet/udp_impl.h> 74 75 /* 76 * The ipsec_info.h header file is here since it has the defination for the 77 * M_CTL message types used by IP to convey information to the ULP. The 78 * ipsec_info.h needs the pfkeyv2.h, hence the latters presence. 79 */ 80 #include <net/pfkeyv2.h> 81 #include <inet/ipsec_info.h> 82 83 /* 84 * Object to represent database of options to search passed to 85 * {sock,tpi}optcom_req() interface routine to take care of option 86 * management and associated methods. 87 * XXX. These and other externs should really move to a udp header file. 88 */ 89 extern optdb_obj_t udp_opt_obj; 90 extern uint_t udp_max_optsize; 91 92 93 /* 94 * Synchronization notes: 95 * 96 * UDP uses a combination of the queue-pair STREAMS perimeter, a global 97 * lock and a set of bind hash locks to protect its data structures. 98 * 99 * The queue-pair perimeter is not acquired exclusively in the put 100 * procedures thus when udp_rput or udp_wput needs exclusive access to 101 * the udp_t instance structure it will use qwriter(..., PERIM_INNER) to 102 * asynchronously acquire exclusive access to the udp_t instance. 103 * 104 * When UDP global data needs to be modified the udp_g_lock mutex is acquired. 105 * Currently, udp_g_head and udp_g_epriv_ports[] are protected by it. 106 * 107 * When an UDP endpoint is bound to a local port, it is inserted into 108 * a bind hash list. The list consists of an array of udp_fanout_t buckets. 109 * The size of the array is controlled by the udp_bind_fanout_size variable. 110 * This variable can be changed in /etc/system if the default value is 111 * not large enough. Each bind hash bucket is protected by a per bucket lock. 112 * It protects the udp_bind_hash and udp_ptpbhn fields in the udp_t 113 * structure. An UDP endpoint is removed from the bind hash list only 114 * when it is being unbound or being closed. The per bucket lock also 115 * protects an UDP endpoint's state changes. 116 */ 117 118 /* 119 * Bind hash list size and hash function. It has to be a power of 2 for 120 * hashing. 121 */ 122 #define UDP_BIND_FANOUT_SIZE 512 123 #define UDP_BIND_HASH(lport) \ 124 ((ntohs((uint16_t)lport)) & (udp_bind_fanout_size - 1)) 125 126 /* UDP bind fanout hash structure. */ 127 typedef struct udp_fanout_s { 128 udp_t *uf_udp; 129 kmutex_t uf_lock; 130 #if defined(_LP64) || defined(_I32LPx) 131 char uf_pad[48]; 132 #else 133 char uf_pad[56]; 134 #endif 135 } udp_fanout_t; 136 137 uint_t udp_bind_fanout_size = UDP_BIND_FANOUT_SIZE; 138 /* udp_fanout_t *udp_bind_fanout. */ 139 static udp_fanout_t *udp_bind_fanout; 140 141 /* 142 * This controls the rate some ndd info report functions can be used 143 * by non-priviledged users. It stores the last time such info is 144 * requested. When those report functions are called again, this 145 * is checked with the current time and compare with the ndd param 146 * udp_ndd_get_info_interval. 147 */ 148 static clock_t udp_last_ndd_get_info_time; 149 #define NDD_TOO_QUICK_MSG \ 150 "ndd get info rate too high for non-priviledged users, try again " \ 151 "later.\n" 152 #define NDD_OUT_OF_BUF_MSG "<< Out of buffer >>\n" 153 154 /* Named Dispatch Parameter Management Structure */ 155 typedef struct udpparam_s { 156 uint32_t udp_param_min; 157 uint32_t udp_param_max; 158 uint32_t udp_param_value; 159 char *udp_param_name; 160 } udpparam_t; 161 162 static void udp_addr_req(queue_t *q, mblk_t *mp); 163 static void udp_bind(queue_t *q, mblk_t *mp); 164 static void udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp); 165 static void udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock); 166 static int udp_build_hdrs(queue_t *q, udp_t *udp); 167 static void udp_capability_req(queue_t *q, mblk_t *mp); 168 static int udp_close(queue_t *q); 169 static void udp_connect(queue_t *q, mblk_t *mp); 170 static void udp_disconnect(queue_t *q, mblk_t *mp); 171 static void udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, 172 int sys_error); 173 static void udp_err_ack_prim(queue_t *q, mblk_t *mp, int primitive, 174 t_scalar_t tlierr, int unixerr); 175 static int udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, 176 cred_t *cr); 177 static int udp_extra_priv_ports_add(queue_t *q, mblk_t *mp, 178 char *value, caddr_t cp, cred_t *cr); 179 static int udp_extra_priv_ports_del(queue_t *q, mblk_t *mp, 180 char *value, caddr_t cp, cred_t *cr); 181 static void udp_icmp_error(queue_t *q, mblk_t *mp); 182 static void udp_icmp_error_ipv6(queue_t *q, mblk_t *mp); 183 static void udp_info_req(queue_t *q, mblk_t *mp); 184 static mblk_t *udp_ip_bind_mp(udp_t *udp, t_scalar_t bind_prim, 185 t_scalar_t addr_length); 186 static int udp_open(queue_t *q, dev_t *devp, int flag, int sflag, 187 cred_t *credp); 188 static int udp_unitdata_opt_process(queue_t *q, mblk_t *mp, 189 int *errorp, void *thisdg_attrs); 190 static boolean_t udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name); 191 int udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, 192 uchar_t *ptr); 193 int udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, 194 uchar_t *ptr); 195 int udp_opt_set(queue_t *q, uint_t optset_context, 196 int level, int name, 197 uint_t inlen, uchar_t *invalp, 198 uint_t *outlenp, uchar_t *outvalp, 199 void *thisdg_attrs, cred_t *cr, mblk_t *mblk); 200 static int udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr); 201 static boolean_t udp_param_register(udpparam_t *udppa, int cnt); 202 static int udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 203 cred_t *cr); 204 static int udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky, 205 uchar_t **optbufp, uint_t *optlenp); 206 static void udp_report_item(mblk_t *mp, udp_t *udp); 207 static void udp_rput(queue_t *q, mblk_t *mp); 208 static void udp_rput_bind_ack(queue_t *q, mblk_t *mp); 209 static void udp_rput_other(queue_t *q, mblk_t *mp); 210 static int udp_snmp_get(queue_t *q, mblk_t *mpctl); 211 static int udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name, 212 uchar_t *ptr, int len); 213 static int udp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, 214 cred_t *cr); 215 static void udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err); 216 static void udp_unbind(queue_t *q, mblk_t *mp); 217 static in_port_t udp_update_next_port(in_port_t port, boolean_t random); 218 static void udp_wput(queue_t *q, mblk_t *mp); 219 static void udp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6, 220 t_scalar_t tudr_optlen); 221 static void udp_wput_other(queue_t *q, mblk_t *mp); 222 static void udp_wput_iocdata(queue_t *q, mblk_t *mp); 223 224 static void udp_kstat_init(void); 225 static void udp_kstat_fini(void); 226 static int udp_kstat_update(kstat_t *kp, int rw); 227 228 major_t UDP6_MAJ; 229 #define UDP6 "udp6" 230 231 #define UDP_MAXPACKET_IPV4 \ 232 (IP_MAXPACKET - UDPH_SIZE - IP_SIMPLE_HDR_LENGTH) 233 #define UDP_MAXPACKET_IPV6 \ 234 (IP_MAXPACKET - UDPH_SIZE - IPV6_HDR_LEN) 235 236 static struct module_info info = { 237 5607, "udp", 1, INFPSZ, 512, 128 238 }; 239 240 static struct qinit rinit = { 241 (pfi_t)udp_rput, NULL, udp_open, udp_close, NULL, &info 242 }; 243 244 static struct qinit winit = { 245 (pfi_t)udp_wput, NULL, NULL, NULL, NULL, &info 246 }; 247 248 struct streamtab udpinfo = { 249 &rinit, &winit 250 }; 251 252 static sin_t sin_null; /* Zero address for quick clears */ 253 static sin6_t sin6_null; /* Zero address for quick clears */ 254 255 /* Protected by udp_g_lock */ 256 static void *udp_g_head; /* Head for list of open udp streams. */ 257 kmutex_t udp_g_lock; /* Protects the above variable */ 258 259 /* Hint not protected by any lock */ 260 static in_port_t udp_g_next_port_to_try; 261 262 /* 263 * Extra privileged ports. In host byte order. Protected by udp_g_lock. 264 */ 265 #define UDP_NUM_EPRIV_PORTS 64 266 static int udp_g_num_epriv_ports = UDP_NUM_EPRIV_PORTS; 267 static in_port_t udp_g_epriv_ports[UDP_NUM_EPRIV_PORTS] = { 2049, 4045 }; 268 269 /* Only modified during _init and _fini thus no locking is needed. */ 270 static IDP udp_g_nd; /* Points to table of UDP ND variables. */ 271 272 /* MIB-2 stuff for SNMP */ 273 static mib2_udp_t udp_mib; /* SNMP fixed size info */ 274 static kstat_t *udp_mibkp; /* kstat exporting udp_mib data */ 275 276 277 /* Default structure copied into T_INFO_ACK messages */ 278 static struct T_info_ack udp_g_t_info_ack_ipv4 = { 279 T_INFO_ACK, 280 UDP_MAXPACKET_IPV4, /* TSDU_size. Excl. headers */ 281 T_INVALID, /* ETSU_size. udp does not support expedited data. */ 282 T_INVALID, /* CDATA_size. udp does not support connect data. */ 283 T_INVALID, /* DDATA_size. udp does not support disconnect data. */ 284 sizeof (sin_t), /* ADDR_size. */ 285 0, /* OPT_size - not initialized here */ 286 UDP_MAXPACKET_IPV4, /* TIDU_size. Excl. headers */ 287 T_CLTS, /* SERV_type. udp supports connection-less. */ 288 TS_UNBND, /* CURRENT_state. This is set from udp_state. */ 289 (XPG4_1|SENDZERO) /* PROVIDER_flag */ 290 }; 291 292 static struct T_info_ack udp_g_t_info_ack_ipv6 = { 293 T_INFO_ACK, 294 UDP_MAXPACKET_IPV6, /* TSDU_size. Excl. headers */ 295 T_INVALID, /* ETSU_size. udp does not support expedited data. */ 296 T_INVALID, /* CDATA_size. udp does not support connect data. */ 297 T_INVALID, /* DDATA_size. udp does not support disconnect data. */ 298 sizeof (sin6_t), /* ADDR_size. */ 299 0, /* OPT_size - not initialized here */ 300 UDP_MAXPACKET_IPV6, /* TIDU_size. Excl. headers */ 301 T_CLTS, /* SERV_type. udp supports connection-less. */ 302 TS_UNBND, /* CURRENT_state. This is set from udp_state. */ 303 (XPG4_1|SENDZERO) /* PROVIDER_flag */ 304 }; 305 306 /* largest UDP port number */ 307 #define UDP_MAX_PORT 65535 308 309 /* 310 * Table of ND variables supported by udp. These are loaded into udp_g_nd 311 * in udp_open. 312 * All of these are alterable, within the min/max values given, at run time. 313 */ 314 static udpparam_t udp_param_arr[] = { 315 /* min max value name */ 316 { 0L, 256, 32, "udp_wroff_extra" }, 317 { 1L, 255, 255, "udp_ipv4_ttl" }, 318 { 0, IPV6_MAX_HOPS, IPV6_DEFAULT_HOPS, "udp_ipv6_hoplimit"}, 319 { 1024, (32 * 1024), 1024, "udp_smallest_nonpriv_port" }, 320 { 0, 1, 1, "udp_do_checksum" }, 321 { 1024, UDP_MAX_PORT, (32 * 1024), "udp_smallest_anon_port" }, 322 { 1024, UDP_MAX_PORT, UDP_MAX_PORT, "udp_largest_anon_port" }, 323 { 4096, 1024*1024, 56*1024, "udp_xmit_hiwat"}, 324 { 0, 1024*1024, 1024, "udp_xmit_lowat"}, 325 { 4096, 1024*1024, 56*1024, "udp_recv_hiwat"}, 326 { 65536, 1024*1024*1024, 2*1024*1024, "udp_max_buf"}, 327 { 100, 60000, 1000, "udp_ndd_get_info_interval"}, 328 }; 329 #define udp_wroff_extra udp_param_arr[0].udp_param_value 330 #define udp_ipv4_ttl udp_param_arr[1].udp_param_value 331 #define udp_ipv6_hoplimit udp_param_arr[2].udp_param_value 332 #define udp_smallest_nonpriv_port udp_param_arr[3].udp_param_value 333 #define udp_do_checksum udp_param_arr[4].udp_param_value 334 #define udp_smallest_anon_port udp_param_arr[5].udp_param_value 335 #define udp_largest_anon_port udp_param_arr[6].udp_param_value 336 #define udp_xmit_hiwat udp_param_arr[7].udp_param_value 337 #define udp_xmit_lowat udp_param_arr[8].udp_param_value 338 #define udp_recv_hiwat udp_param_arr[9].udp_param_value 339 #define udp_max_buf udp_param_arr[10].udp_param_value 340 #define udp_ndd_get_info_interval udp_param_arr[11].udp_param_value 341 342 /* 343 * The smallest anonymous port in the priviledged port range which UDP 344 * looks for free port. Use in the option UDP_ANONPRIVBIND. 345 */ 346 static in_port_t udp_min_anonpriv_port = 512; 347 348 /* If set to 0, pick ephemeral port sequentially; otherwise randomly. */ 349 uint32_t udp_random_anon_port = 1; 350 351 /* 352 * Hook functions to enable cluster networking. 353 * On non-clustered systems these vectors must always be NULL 354 */ 355 356 void (*cl_inet_bind)(uchar_t protocol, sa_family_t addr_family, 357 uint8_t *laddrp, in_port_t lport) = NULL; 358 void (*cl_inet_unbind)(uint8_t protocol, sa_family_t addr_family, 359 uint8_t *laddrp, in_port_t lport) = NULL; 360 361 /* 362 * Return the next anonymous port in the priviledged port range for 363 * bind checking. 364 */ 365 static in_port_t 366 udp_get_next_priv_port(void) 367 { 368 static in_port_t next_priv_port = IPPORT_RESERVED - 1; 369 370 if (next_priv_port < udp_min_anonpriv_port) { 371 next_priv_port = IPPORT_RESERVED - 1; 372 } 373 return (next_priv_port--); 374 } 375 376 /* UDP bind hash report triggered via the Named Dispatch mechanism. */ 377 /* ARGSUSED */ 378 static int 379 udp_bind_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 380 { 381 udp_fanout_t *udpf; 382 udp_t *udp; 383 int i; 384 zoneid_t zoneid; 385 386 /* Refer to comments in udp_status_report(). */ 387 if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) { 388 if (ddi_get_lbolt() - udp_last_ndd_get_info_time < 389 drv_usectohz(udp_ndd_get_info_interval * 1000)) { 390 (void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG); 391 return (0); 392 } 393 } 394 if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) { 395 /* The following may work even if we cannot get a large buf. */ 396 (void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG); 397 return (0); 398 } 399 400 (void) mi_mpprintf(mp, 401 "UDP " MI_COL_HDRPAD_STR 402 /* 12345678[89ABCDEF] */ 403 " zone lport src addr dest addr port state"); 404 /* 1234 12345 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx 12345 UNBOUND */ 405 406 udp = (udp_t *)q->q_ptr; 407 zoneid = udp->udp_zoneid; 408 409 for (i = 0; i < udp_bind_fanout_size; i++) { 410 udpf = &udp_bind_fanout[i]; 411 mutex_enter(&udpf->uf_lock); 412 413 /* Print the hash index. */ 414 udp = udpf->uf_udp; 415 if (zoneid != GLOBAL_ZONEID) { 416 /* skip to first entry in this zone; might be none */ 417 while (udp != NULL && 418 udp->udp_zoneid != zoneid) 419 udp = udp->udp_bind_hash; 420 } 421 if (udp != NULL) { 422 uint_t print_len, buf_len; 423 424 buf_len = mp->b_cont->b_datap->db_lim - 425 mp->b_cont->b_wptr; 426 print_len = snprintf((char *)mp->b_cont->b_wptr, 427 buf_len, "%d\n", i); 428 if (print_len < buf_len) { 429 mp->b_cont->b_wptr += print_len; 430 } else { 431 mp->b_cont->b_wptr += buf_len; 432 } 433 for (; udp != NULL; udp = udp->udp_bind_hash) { 434 if (zoneid == GLOBAL_ZONEID || 435 zoneid == udp->udp_zoneid) 436 udp_report_item(mp->b_cont, udp); 437 } 438 } 439 mutex_exit(&udpf->uf_lock); 440 } 441 udp_last_ndd_get_info_time = ddi_get_lbolt(); 442 return (0); 443 } 444 445 /* 446 * Hash list removal routine for udp_t structures. 447 */ 448 static void 449 udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock) 450 { 451 udp_t *udpnext; 452 kmutex_t *lockp; 453 454 if (udp->udp_ptpbhn == NULL) 455 return; 456 457 /* 458 * Extract the lock pointer in case there are concurrent 459 * hash_remove's for this instance. 460 */ 461 ASSERT(udp->udp_port != 0); 462 if (!caller_holds_lock) { 463 lockp = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)].uf_lock; 464 ASSERT(lockp != NULL); 465 mutex_enter(lockp); 466 } 467 if (udp->udp_ptpbhn != NULL) { 468 udpnext = udp->udp_bind_hash; 469 if (udpnext != NULL) { 470 udpnext->udp_ptpbhn = udp->udp_ptpbhn; 471 udp->udp_bind_hash = NULL; 472 } 473 *udp->udp_ptpbhn = udpnext; 474 udp->udp_ptpbhn = NULL; 475 } 476 if (!caller_holds_lock) { 477 mutex_exit(lockp); 478 } 479 } 480 481 static void 482 udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp) 483 { 484 udp_t **udpp; 485 udp_t *udpnext; 486 487 ASSERT(MUTEX_HELD(&uf->uf_lock)); 488 if (udp->udp_ptpbhn != NULL) { 489 udp_bind_hash_remove(udp, B_TRUE); 490 } 491 udpp = &uf->uf_udp; 492 udpnext = udpp[0]; 493 if (udpnext != NULL) { 494 /* 495 * If the new udp bound to the INADDR_ANY address 496 * and the first one in the list is not bound to 497 * INADDR_ANY we skip all entries until we find the 498 * first one bound to INADDR_ANY. 499 * This makes sure that applications binding to a 500 * specific address get preference over those binding to 501 * INADDR_ANY. 502 */ 503 if (V6_OR_V4_INADDR_ANY(udp->udp_bound_v6src) && 504 !V6_OR_V4_INADDR_ANY(udpnext->udp_bound_v6src)) { 505 while ((udpnext = udpp[0]) != NULL && 506 !V6_OR_V4_INADDR_ANY( 507 udpnext->udp_bound_v6src)) { 508 udpp = &(udpnext->udp_bind_hash); 509 } 510 if (udpnext != NULL) 511 udpnext->udp_ptpbhn = &udp->udp_bind_hash; 512 } else { 513 udpnext->udp_ptpbhn = &udp->udp_bind_hash; 514 } 515 } 516 udp->udp_bind_hash = udpnext; 517 udp->udp_ptpbhn = udpp; 518 udpp[0] = udp; 519 } 520 521 /* 522 * This routine is called to handle each O_T_BIND_REQ/T_BIND_REQ message 523 * passed to udp_wput. 524 * It associates a port number and local address with the stream. 525 * The O_T_BIND_REQ/T_BIND_REQ is passed downstream to ip with the UDP 526 * protocol type (IPPROTO_UDP) placed in the message following the address. 527 * A T_BIND_ACK message is passed upstream when ip acknowledges the request. 528 * (Called as writer.) 529 * 530 * Note that UDP over IPv4 and IPv6 sockets can use the same port number 531 * without setting SO_REUSEADDR. This is needed so that they 532 * can be viewed as two independent transport protocols. 533 * However, anonymouns ports are allocated from the same range to avoid 534 * duplicating the udp_g_next_port_to_try. 535 */ 536 static void 537 udp_bind(queue_t *q, mblk_t *mp) 538 { 539 sin_t *sin; 540 sin6_t *sin6; 541 mblk_t *mp1; 542 in_port_t port; /* Host byte order */ 543 in_port_t requested_port; /* Host byte order */ 544 struct T_bind_req *tbr; 545 udp_t *udp; 546 int count; 547 in6_addr_t v6src; 548 boolean_t bind_to_req_port_only; 549 int loopmax; 550 udp_fanout_t *udpf; 551 in_port_t lport; /* Network byte order */ 552 zoneid_t zoneid; 553 554 udp = (udp_t *)q->q_ptr; 555 if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) { 556 (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 557 "udp_bind: bad req, len %u", 558 (uint_t)(mp->b_wptr - mp->b_rptr)); 559 udp_err_ack(q, mp, TPROTO, 0); 560 return; 561 } 562 if (udp->udp_state != TS_UNBND) { 563 (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 564 "udp_bind: bad state, %u", udp->udp_state); 565 udp_err_ack(q, mp, TOUTSTATE, 0); 566 return; 567 } 568 /* 569 * Reallocate the message to make sure we have enough room for an 570 * address and the protocol type. 571 */ 572 mp1 = reallocb(mp, sizeof (struct T_bind_ack) + sizeof (sin6_t) + 1, 1); 573 if (!mp1) { 574 udp_err_ack(q, mp, TSYSERR, ENOMEM); 575 return; 576 } 577 578 mp = mp1; 579 tbr = (struct T_bind_req *)mp->b_rptr; 580 switch (tbr->ADDR_length) { 581 case 0: /* Request for a generic port */ 582 tbr->ADDR_offset = sizeof (struct T_bind_req); 583 if (udp->udp_family == AF_INET) { 584 tbr->ADDR_length = sizeof (sin_t); 585 sin = (sin_t *)&tbr[1]; 586 *sin = sin_null; 587 sin->sin_family = AF_INET; 588 mp->b_wptr = (uchar_t *)&sin[1]; 589 } else { 590 ASSERT(udp->udp_family == AF_INET6); 591 tbr->ADDR_length = sizeof (sin6_t); 592 sin6 = (sin6_t *)&tbr[1]; 593 *sin6 = sin6_null; 594 sin6->sin6_family = AF_INET6; 595 mp->b_wptr = (uchar_t *)&sin6[1]; 596 } 597 port = 0; 598 break; 599 600 case sizeof (sin_t): /* Complete IPv4 address */ 601 sin = (sin_t *)mi_offset_param(mp, tbr->ADDR_offset, 602 sizeof (sin_t)); 603 if (sin == NULL || !OK_32PTR((char *)sin)) { 604 udp_err_ack(q, mp, TSYSERR, EINVAL); 605 return; 606 } 607 if (udp->udp_family != AF_INET || 608 sin->sin_family != AF_INET) { 609 udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 610 return; 611 } 612 port = ntohs(sin->sin_port); 613 break; 614 615 case sizeof (sin6_t): /* complete IPv6 address */ 616 sin6 = (sin6_t *)mi_offset_param(mp, tbr->ADDR_offset, 617 sizeof (sin6_t)); 618 if (sin6 == NULL || !OK_32PTR((char *)sin6)) { 619 udp_err_ack(q, mp, TSYSERR, EINVAL); 620 return; 621 } 622 if (udp->udp_family != AF_INET6 || 623 sin6->sin6_family != AF_INET6) { 624 udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 625 return; 626 } 627 port = ntohs(sin6->sin6_port); 628 break; 629 630 default: /* Invalid request */ 631 (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 632 "udp_bind: bad ADDR_length length %u", tbr->ADDR_length); 633 udp_err_ack(q, mp, TBADADDR, 0); 634 return; 635 } 636 637 requested_port = port; 638 639 if (requested_port == 0 || tbr->PRIM_type == O_T_BIND_REQ) 640 bind_to_req_port_only = B_FALSE; 641 else /* T_BIND_REQ and requested_port != 0 */ 642 bind_to_req_port_only = B_TRUE; 643 644 if (requested_port == 0) { 645 /* 646 * If the application passed in zero for the port number, it 647 * doesn't care which port number we bind to. Get one in the 648 * valid range. 649 */ 650 if (udp->udp_anon_priv_bind) { 651 port = udp_get_next_priv_port(); 652 } else { 653 port = udp_update_next_port(udp_g_next_port_to_try, 654 B_TRUE); 655 } 656 } else { 657 /* 658 * If the port is in the well-known privileged range, 659 * make sure the caller was privileged. 660 */ 661 int i; 662 boolean_t priv = B_FALSE; 663 664 if (port < udp_smallest_nonpriv_port) { 665 priv = B_TRUE; 666 } else { 667 for (i = 0; i < udp_g_num_epriv_ports; i++) { 668 if (port == udp_g_epriv_ports[i]) { 669 priv = B_TRUE; 670 break; 671 } 672 } 673 } 674 675 if (priv) { 676 cred_t *cr = DB_CREDDEF(mp, udp->udp_credp); 677 678 if (secpolicy_net_privaddr(cr, port) != 0) { 679 udp_err_ack(q, mp, TACCES, 0); 680 return; 681 } 682 } 683 } 684 685 /* 686 * Copy the source address into our udp structure. This address 687 * may still be zero; if so, IP will fill in the correct address 688 * each time an outbound packet is passed to it. 689 */ 690 if (udp->udp_family == AF_INET) { 691 ASSERT(sin != NULL); 692 ASSERT(udp->udp_ipversion == IPV4_VERSION); 693 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE + 694 udp->udp_ip_snd_options_len; 695 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6src); 696 } else { 697 ASSERT(sin6 != NULL); 698 v6src = sin6->sin6_addr; 699 if (IN6_IS_ADDR_V4MAPPED(&v6src)) { 700 udp->udp_ipversion = IPV4_VERSION; 701 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + 702 UDPH_SIZE + udp->udp_ip_snd_options_len; 703 } else { 704 udp->udp_ipversion = IPV6_VERSION; 705 udp->udp_max_hdr_len = udp->udp_sticky_hdrs_len; 706 } 707 } 708 709 /* 710 * If udp_reuseaddr is not set, then we have to make sure that 711 * the IP address and port number the application requested 712 * (or we selected for the application) is not being used by 713 * another stream. If another stream is already using the 714 * requested IP address and port, the behavior depends on 715 * "bind_to_req_port_only". If set the bind fails; otherwise we 716 * search for any an unused port to bind to the the stream. 717 * 718 * As per the BSD semantics, as modified by the Deering multicast 719 * changes, if udp_reuseaddr is set, then we allow multiple binds 720 * to the same port independent of the local IP address. 721 * 722 * This is slightly different than in SunOS 4.X which did not 723 * support IP multicast. Note that the change implemented by the 724 * Deering multicast code effects all binds - not only binding 725 * to IP multicast addresses. 726 * 727 * Note that when binding to port zero we ignore SO_REUSEADDR in 728 * order to guarantee a unique port. 729 */ 730 731 count = 0; 732 if (udp->udp_anon_priv_bind) { 733 /* loopmax = (IPPORT_RESERVED-1) - udp_min_anonpriv_port + 1 */ 734 loopmax = IPPORT_RESERVED - udp_min_anonpriv_port; 735 } else { 736 loopmax = udp_largest_anon_port - udp_smallest_anon_port + 1; 737 } 738 739 zoneid = udp->udp_zoneid; 740 for (;;) { 741 udp_t *udp1; 742 boolean_t is_inaddr_any; 743 boolean_t found_exclbind = B_FALSE; 744 745 is_inaddr_any = V6_OR_V4_INADDR_ANY(v6src); 746 /* 747 * Walk through the list of udp streams bound to 748 * requested port with the same IP address. 749 */ 750 lport = htons(port); 751 udpf = &udp_bind_fanout[UDP_BIND_HASH(lport)]; 752 mutex_enter(&udpf->uf_lock); 753 for (udp1 = udpf->uf_udp; udp1 != NULL; 754 udp1 = udp1->udp_bind_hash) { 755 if (lport != udp1->udp_port || 756 zoneid != udp1->udp_zoneid) 757 continue; 758 759 /* 760 * If UDP_EXCLBIND is set for either the bound or 761 * binding endpoint, the semantics of bind 762 * is changed according to the following chart. 763 * 764 * spec = specified address (v4 or v6) 765 * unspec = unspecified address (v4 or v6) 766 * A = specified addresses are different for endpoints 767 * 768 * bound bind to allowed? 769 * ------------------------------------- 770 * unspec unspec no 771 * unspec spec no 772 * spec unspec no 773 * spec spec yes if A 774 */ 775 if (udp1->udp_exclbind || udp->udp_exclbind) { 776 if (V6_OR_V4_INADDR_ANY( 777 udp1->udp_bound_v6src) || 778 is_inaddr_any || 779 IN6_ARE_ADDR_EQUAL(&udp1->udp_bound_v6src, 780 &v6src)) { 781 found_exclbind = B_TRUE; 782 break; 783 } 784 continue; 785 } 786 787 /* 788 * Check ipversion to allow IPv4 and IPv6 sockets to 789 * have disjoint port number spaces. 790 */ 791 if (udp->udp_ipversion != udp1->udp_ipversion) 792 continue; 793 794 /* 795 * No difference depending on SO_REUSEADDR. 796 * 797 * If existing port is bound to a 798 * non-wildcard IP address and 799 * the requesting stream is bound to 800 * a distinct different IP addresses 801 * (non-wildcard, also), keep going. 802 */ 803 if (!is_inaddr_any && 804 !V6_OR_V4_INADDR_ANY(udp1->udp_bound_v6src) && 805 !IN6_ARE_ADDR_EQUAL(&udp1->udp_bound_v6src, 806 &v6src)) { 807 continue; 808 } 809 break; 810 } 811 812 if (!found_exclbind && 813 (udp->udp_reuseaddr && requested_port != 0)) { 814 break; 815 } 816 817 if (udp1 == NULL) { 818 /* 819 * No other stream has this IP address 820 * and port number. We can use it. 821 */ 822 break; 823 } 824 mutex_exit(&udpf->uf_lock); 825 if (bind_to_req_port_only) { 826 /* 827 * We get here only when requested port 828 * is bound (and only first of the for() 829 * loop iteration). 830 * 831 * The semantics of this bind request 832 * require it to fail so we return from 833 * the routine (and exit the loop). 834 * 835 */ 836 udp_err_ack(q, mp, TADDRBUSY, 0); 837 return; 838 } 839 840 if (udp->udp_anon_priv_bind) { 841 port = udp_get_next_priv_port(); 842 } else { 843 if ((count == 0) && (requested_port != 0)) { 844 /* 845 * If the application wants us to find 846 * a port, get one to start with. Set 847 * requested_port to 0, so that we will 848 * update udp_g_next_port_to_try below. 849 */ 850 port = udp_update_next_port( 851 udp_g_next_port_to_try, B_TRUE); 852 requested_port = 0; 853 } else { 854 port = udp_update_next_port(port + 1, B_FALSE); 855 } 856 } 857 858 if (++count >= loopmax) { 859 /* 860 * We've tried every possible port number and 861 * there are none available, so send an error 862 * to the user. 863 */ 864 udp_err_ack(q, mp, TNOADDR, 0); 865 return; 866 } 867 } 868 869 /* 870 * Copy the source address into our udp structure. This address 871 * may still be zero; if so, ip will fill in the correct address 872 * each time an outbound packet is passed to it. 873 * If we are binding to a broadcast or multicast address udp_rput 874 * will clear the source address when it receives the T_BIND_ACK. 875 */ 876 udp->udp_v6src = udp->udp_bound_v6src = v6src; 877 udp->udp_port = lport; 878 /* 879 * Now reset the the next anonymous port if the application requested 880 * an anonymous port, or we handed out the next anonymous port. 881 */ 882 if ((requested_port == 0) && (!udp->udp_anon_priv_bind)) { 883 udp_g_next_port_to_try = port + 1; 884 } 885 886 /* Initialize the O_T_BIND_REQ/T_BIND_REQ for ip. */ 887 if (udp->udp_family == AF_INET) { 888 sin->sin_port = udp->udp_port; 889 } else { 890 int error; 891 892 sin6->sin6_port = udp->udp_port; 893 /* Rebuild the header template */ 894 error = udp_build_hdrs(q, udp); 895 if (error != 0) { 896 mutex_exit(&udpf->uf_lock); 897 udp_err_ack(q, mp, TSYSERR, error); 898 return; 899 } 900 } 901 udp->udp_state = TS_IDLE; 902 udp_bind_hash_insert(udpf, udp); 903 mutex_exit(&udpf->uf_lock); 904 905 if (cl_inet_bind) { 906 /* 907 * Running in cluster mode - register bind information 908 */ 909 if (udp->udp_ipversion == IPV4_VERSION) { 910 (*cl_inet_bind)(IPPROTO_UDP, AF_INET, 911 (uint8_t *)(&V4_PART_OF_V6(udp->udp_v6src)), 912 (in_port_t)udp->udp_port); 913 } else { 914 (*cl_inet_bind)(IPPROTO_UDP, AF_INET6, 915 (uint8_t *)&(udp->udp_v6src), 916 (in_port_t)udp->udp_port); 917 } 918 919 } 920 921 /* Pass the protocol number in the message following the address. */ 922 *mp->b_wptr++ = IPPROTO_UDP; 923 if (!V6_OR_V4_INADDR_ANY(udp->udp_v6src)) { 924 /* 925 * Append a request for an IRE if udp_v6src not 926 * zero (IPv4 - INADDR_ANY, or IPv6 - all-zeroes address). 927 */ 928 mp->b_cont = allocb(sizeof (ire_t), BPRI_HI); 929 if (!mp->b_cont) { 930 udp_err_ack(q, mp, TSYSERR, ENOMEM); 931 return; 932 } 933 mp->b_cont->b_wptr += sizeof (ire_t); 934 mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE; 935 } 936 putnext(q, mp); 937 } 938 939 /* 940 * This routine handles each T_CONN_REQ message passed to udp. It 941 * associates a default destination address with the stream. 942 * 943 * This routine sends down a T_BIND_REQ to IP with the following mblks: 944 * T_BIND_REQ - specifying local and remote address/port 945 * IRE_DB_REQ_TYPE - to get an IRE back containing ire_type and src 946 * T_OK_ACK - for the T_CONN_REQ 947 * T_CONN_CON - to keep the TPI user happy 948 * 949 * The connect completes in udp_rput. 950 * When a T_BIND_ACK is received information is extracted from the IRE 951 * and the two appended messages are sent to the TPI user. 952 * Should udp_rput receive T_ERROR_ACK for the T_BIND_REQ it will convert 953 * it to an error ack for the appropriate primitive. 954 */ 955 static void 956 udp_connect(queue_t *q, mblk_t *mp) 957 { 958 sin6_t *sin6; 959 sin_t *sin; 960 struct T_conn_req *tcr; 961 udp_t *udp, *udp1; 962 in6_addr_t v6dst; 963 ipaddr_t v4dst; 964 uint16_t dstport; 965 uint32_t flowinfo; 966 mblk_t *mp1, *mp2; 967 udp_fanout_t *udpf; 968 969 udp = (udp_t *)q->q_ptr; 970 tcr = (struct T_conn_req *)mp->b_rptr; 971 972 /* A bit of sanity checking */ 973 if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_req)) { 974 udp_err_ack(q, mp, TPROTO, 0); 975 return; 976 } 977 /* 978 * This UDP must have bound to a port already before doing 979 * a connect. 980 */ 981 if (udp->udp_state == TS_UNBND) { 982 (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 983 "udp_connect: bad state, %u", udp->udp_state); 984 udp_err_ack(q, mp, TOUTSTATE, 0); 985 return; 986 } 987 ASSERT(udp->udp_port != 0 && udp->udp_ptpbhn != NULL); 988 989 udpf = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)]; 990 if (udp->udp_state == TS_DATA_XFER) { 991 /* Already connected - clear out state */ 992 mutex_enter(&udpf->uf_lock); 993 udp->udp_v6src = udp->udp_bound_v6src; 994 udp->udp_state = TS_IDLE; 995 mutex_exit(&udpf->uf_lock); 996 } 997 998 if (tcr->OPT_length != 0) { 999 udp_err_ack(q, mp, TBADOPT, 0); 1000 return; 1001 } 1002 1003 /* 1004 * Determine packet type based on type of address passed in 1005 * the request should contain an IPv4 or IPv6 address. 1006 * Make sure that address family matches the type of 1007 * family of the the address passed down 1008 */ 1009 switch (tcr->DEST_length) { 1010 default: 1011 udp_err_ack(q, mp, TBADADDR, 0); 1012 return; 1013 1014 case sizeof (sin_t): 1015 sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset, 1016 sizeof (sin_t)); 1017 if (sin == NULL || !OK_32PTR((char *)sin)) { 1018 udp_err_ack(q, mp, TSYSERR, EINVAL); 1019 return; 1020 } 1021 if (udp->udp_family != AF_INET || 1022 sin->sin_family != AF_INET) { 1023 udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 1024 return; 1025 } 1026 v4dst = sin->sin_addr.s_addr; 1027 dstport = sin->sin_port; 1028 IN6_IPADDR_TO_V4MAPPED(v4dst, &v6dst); 1029 ASSERT(udp->udp_ipversion == IPV4_VERSION); 1030 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE + 1031 udp->udp_ip_snd_options_len; 1032 break; 1033 1034 case sizeof (sin6_t): 1035 sin6 = (sin6_t *)mi_offset_param(mp, tcr->DEST_offset, 1036 sizeof (sin6_t)); 1037 if (sin6 == NULL || !OK_32PTR((char *)sin6)) { 1038 udp_err_ack(q, mp, TSYSERR, EINVAL); 1039 return; 1040 } 1041 if (udp->udp_family != AF_INET6 || 1042 sin6->sin6_family != AF_INET6) { 1043 udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT); 1044 return; 1045 } 1046 v6dst = sin6->sin6_addr; 1047 if (IN6_IS_ADDR_V4MAPPED(&v6dst)) { 1048 IN6_V4MAPPED_TO_IPADDR(&v6dst, v4dst); 1049 udp->udp_ipversion = IPV4_VERSION; 1050 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + 1051 UDPH_SIZE + udp->udp_ip_snd_options_len; 1052 flowinfo = 0; 1053 } else { 1054 udp->udp_ipversion = IPV6_VERSION; 1055 udp->udp_max_hdr_len = udp->udp_sticky_hdrs_len; 1056 flowinfo = sin6->sin6_flowinfo; 1057 } 1058 dstport = sin6->sin6_port; 1059 break; 1060 } 1061 if (dstport == 0) { 1062 udp_err_ack(q, mp, TBADADDR, 0); 1063 return; 1064 } 1065 1066 /* 1067 * Create a default IP header with no IP options. 1068 */ 1069 udp->udp_dstport = dstport; 1070 if (udp->udp_ipversion == IPV4_VERSION) { 1071 /* 1072 * Interpret a zero destination to mean loopback. 1073 * Update the T_CONN_REQ (sin/sin6) since it is used to 1074 * generate the T_CONN_CON. 1075 */ 1076 if (v4dst == INADDR_ANY) { 1077 v4dst = htonl(INADDR_LOOPBACK); 1078 IN6_IPADDR_TO_V4MAPPED(v4dst, &v6dst); 1079 if (udp->udp_family == AF_INET) { 1080 sin->sin_addr.s_addr = v4dst; 1081 } else { 1082 sin6->sin6_addr = v6dst; 1083 } 1084 } 1085 udp->udp_v6dst = v6dst; 1086 udp->udp_flowinfo = 0; 1087 1088 /* 1089 * If the destination address is multicast and 1090 * an outgoing multicast interface has been set, 1091 * use the address of that interface as our 1092 * source address if no source address has been set. 1093 */ 1094 if (V4_PART_OF_V6(udp->udp_v6src) == INADDR_ANY && 1095 CLASSD(v4dst) && 1096 udp->udp_multicast_if_addr != INADDR_ANY) { 1097 IN6_IPADDR_TO_V4MAPPED(udp->udp_multicast_if_addr, 1098 &udp->udp_v6src); 1099 } 1100 } else { 1101 ASSERT(udp->udp_ipversion == IPV6_VERSION); 1102 /* 1103 * Interpret a zero destination to mean loopback. 1104 * Update the T_CONN_REQ (sin/sin6) since it is used to 1105 * generate the T_CONN_CON. 1106 */ 1107 if (IN6_IS_ADDR_UNSPECIFIED(&v6dst)) { 1108 v6dst = ipv6_loopback; 1109 sin6->sin6_addr = v6dst; 1110 } 1111 udp->udp_v6dst = v6dst; 1112 udp->udp_flowinfo = flowinfo; 1113 /* 1114 * If the destination address is multicast and 1115 * an outgoing multicast interface has been set, 1116 * then the ip bind logic will pick the correct source 1117 * address (i.e. matching the outgoing multicast interface). 1118 */ 1119 } 1120 1121 /* 1122 * Verify that the src/port/dst/port is unique for all 1123 * connections in TS_DATA_XFER 1124 */ 1125 mutex_enter(&udpf->uf_lock); 1126 for (udp1 = udpf->uf_udp; udp1 != NULL; udp1 = udp1->udp_bind_hash) { 1127 if (udp1->udp_state != TS_DATA_XFER) 1128 continue; 1129 if (udp->udp_port != udp1->udp_port || 1130 udp->udp_ipversion != udp1->udp_ipversion || 1131 dstport != udp1->udp_dstport || 1132 !IN6_ARE_ADDR_EQUAL(&udp->udp_v6src, &udp1->udp_v6src) || 1133 !IN6_ARE_ADDR_EQUAL(&v6dst, &udp1->udp_v6dst)) 1134 continue; 1135 mutex_exit(&udpf->uf_lock); 1136 udp_err_ack(q, mp, TBADADDR, 0); 1137 return; 1138 } 1139 udp->udp_state = TS_DATA_XFER; 1140 mutex_exit(&udpf->uf_lock); 1141 1142 /* 1143 * Send down bind to IP to verify that there is a route 1144 * and to determine the source address. 1145 * This will come back as T_BIND_ACK with an IRE_DB_TYPE in rput. 1146 */ 1147 if (udp->udp_family == AF_INET) 1148 mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (ipa_conn_t)); 1149 else 1150 mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (ipa6_conn_t)); 1151 if (mp1 == NULL) { 1152 udp_err_ack(q, mp, TSYSERR, ENOMEM); 1153 bind_failed: 1154 mutex_enter(&udpf->uf_lock); 1155 udp->udp_state = TS_IDLE; 1156 mutex_exit(&udpf->uf_lock); 1157 return; 1158 } 1159 1160 /* 1161 * We also have to send a connection confirmation to 1162 * keep TLI happy. Prepare it for udp_rput. 1163 */ 1164 if (udp->udp_family == AF_INET) 1165 mp2 = mi_tpi_conn_con(NULL, (char *)sin, 1166 sizeof (*sin), NULL, 0); 1167 else 1168 mp2 = mi_tpi_conn_con(NULL, (char *)sin6, 1169 sizeof (*sin6), NULL, 0); 1170 if (mp2 == NULL) { 1171 freemsg(mp1); 1172 udp_err_ack(q, mp, TSYSERR, ENOMEM); 1173 goto bind_failed; 1174 } 1175 1176 mp = mi_tpi_ok_ack_alloc(mp); 1177 if (mp == NULL) { 1178 /* Unable to reuse the T_CONN_REQ for the ack. */ 1179 freemsg(mp2); 1180 udp_err_ack_prim(q, mp1, T_CONN_REQ, TSYSERR, ENOMEM); 1181 goto bind_failed; 1182 } 1183 1184 /* Hang onto the T_OK_ACK and T_CONN_CON for later. */ 1185 linkb(mp1, mp); 1186 linkb(mp1, mp2); 1187 1188 putnext(q, mp1); 1189 } 1190 1191 /* This is the close routine for udp. It frees the per-stream data. */ 1192 static int 1193 udp_close(queue_t *q) 1194 { 1195 udp_t *udp = (udp_t *)q->q_ptr; 1196 1197 TRACE_1(TR_FAC_UDP, TR_UDP_CLOSE, 1198 "udp_close: q %p", q); 1199 1200 qprocsoff(q); 1201 1202 if (cl_inet_unbind != NULL && udp->udp_state == TS_IDLE) { 1203 /* 1204 * Running in cluster mode - register unbind information 1205 */ 1206 if (udp->udp_ipversion == IPV4_VERSION) { 1207 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET, 1208 (uint8_t *)(&(V4_PART_OF_V6(udp->udp_v6src))), 1209 (in_port_t)udp->udp_port); 1210 } else { 1211 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET6, 1212 (uint8_t *)(&(udp->udp_v6src)), 1213 (in_port_t)udp->udp_port); 1214 } 1215 } 1216 1217 udp_bind_hash_remove(udp, B_FALSE); 1218 mutex_enter(&udp_g_lock); 1219 /* Unlink the udp structure and release the minor device number. */ 1220 mi_close_unlink(&udp_g_head, (IDP)udp); 1221 mutex_exit(&udp_g_lock); 1222 /* If there are any options associated with the stream, free them. */ 1223 if (udp->udp_ip_snd_options) 1224 mi_free((char *)udp->udp_ip_snd_options); 1225 1226 if (udp->udp_ip_rcv_options) 1227 mi_free((char *)udp->udp_ip_rcv_options); 1228 1229 /* Free memory associated with sticky options */ 1230 if (udp->udp_sticky_hdrs_len != 0) { 1231 kmem_free(udp->udp_sticky_hdrs, 1232 udp->udp_sticky_hdrs_len); 1233 udp->udp_sticky_hdrs = NULL; 1234 udp->udp_sticky_hdrs_len = 0; 1235 } 1236 if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) { 1237 kmem_free(udp->udp_sticky_ipp.ipp_hopopts, 1238 udp->udp_sticky_ipp.ipp_hopoptslen); 1239 } 1240 if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) { 1241 kmem_free(udp->udp_sticky_ipp.ipp_rtdstopts, 1242 udp->udp_sticky_ipp.ipp_rtdstoptslen); 1243 } 1244 if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) { 1245 kmem_free(udp->udp_sticky_ipp.ipp_rthdr, 1246 udp->udp_sticky_ipp.ipp_rthdrlen); 1247 } 1248 if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) { 1249 kmem_free(udp->udp_sticky_ipp.ipp_dstopts, 1250 udp->udp_sticky_ipp.ipp_dstoptslen); 1251 } 1252 udp->udp_sticky_ipp.ipp_fields &= 1253 ~(IPPF_HOPOPTS|IPPF_RTDSTOPTS|IPPF_RTHDR|IPPF_DSTOPTS); 1254 1255 crfree(udp->udp_credp); 1256 /* Free the data structure */ 1257 mi_close_free((IDP)udp); 1258 q->q_ptr = WR(q)->q_ptr = NULL; 1259 return (0); 1260 } 1261 1262 /* 1263 * This routine handles each T_DISCON_REQ message passed to udp 1264 * as an indicating that UDP is no longer connected. This results 1265 * in sending a T_BIND_REQ to IP to restore the binding to just 1266 * the local address/port. 1267 * 1268 * This routine sends down a T_BIND_REQ to IP with the following mblks: 1269 * T_BIND_REQ - specifying just the local address/port 1270 * T_OK_ACK - for the T_DISCON_REQ 1271 * 1272 * The disconnect completes in udp_rput. 1273 * When a T_BIND_ACK is received the appended T_OK_ACK is sent to the TPI user. 1274 * Should udp_rput receive T_ERROR_ACK for the T_BIND_REQ it will convert 1275 * it to an error ack for the appropriate primitive. 1276 */ 1277 static void 1278 udp_disconnect(queue_t *q, mblk_t *mp) 1279 { 1280 udp_t *udp; 1281 mblk_t *mp1; 1282 udp_fanout_t *udpf; 1283 1284 udp = (udp_t *)q->q_ptr; 1285 1286 if (udp->udp_state != TS_DATA_XFER) { 1287 (void) mi_strlog(q, 1, SL_ERROR|SL_TRACE, 1288 "udp_disconnect: bad state, %u", udp->udp_state); 1289 udp_err_ack(q, mp, TOUTSTATE, 0); 1290 return; 1291 } 1292 udpf = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)]; 1293 mutex_enter(&udpf->uf_lock); 1294 udp->udp_v6src = udp->udp_bound_v6src; 1295 udp->udp_state = TS_IDLE; 1296 mutex_exit(&udpf->uf_lock); 1297 1298 /* 1299 * Send down bind to IP to remove the full binding and revert 1300 * to the local address binding. 1301 */ 1302 if (udp->udp_family == AF_INET) 1303 mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (sin_t)); 1304 else 1305 mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (sin6_t)); 1306 if (mp1 == NULL) { 1307 udp_err_ack(q, mp, TSYSERR, ENOMEM); 1308 return; 1309 } 1310 mp = mi_tpi_ok_ack_alloc(mp); 1311 if (mp == NULL) { 1312 /* Unable to reuse the T_DISCON_REQ for the ack. */ 1313 udp_err_ack_prim(q, mp1, T_DISCON_REQ, TSYSERR, ENOMEM); 1314 return; 1315 } 1316 1317 if (udp->udp_family == AF_INET6) { 1318 int error; 1319 1320 /* Rebuild the header template */ 1321 error = udp_build_hdrs(q, udp); 1322 if (error != 0) { 1323 udp_err_ack_prim(q, mp, T_DISCON_REQ, TSYSERR, error); 1324 freemsg(mp1); 1325 return; 1326 } 1327 } 1328 mutex_enter(&udpf->uf_lock); 1329 udp->udp_discon_pending = 1; 1330 mutex_exit(&udpf->uf_lock); 1331 1332 /* Append the T_OK_ACK to the T_BIND_REQ for udp_rput */ 1333 linkb(mp1, mp); 1334 putnext(q, mp1); 1335 } 1336 1337 /* This routine creates a T_ERROR_ACK message and passes it upstream. */ 1338 static void 1339 udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, int sys_error) 1340 { 1341 if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL) 1342 qreply(q, mp); 1343 } 1344 1345 /* Shorthand to generate and send TPI error acks to our client */ 1346 static void 1347 udp_err_ack_prim(queue_t *q, mblk_t *mp, int primitive, t_scalar_t t_error, 1348 int sys_error) 1349 { 1350 struct T_error_ack *teackp; 1351 1352 if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack), 1353 M_PCPROTO, T_ERROR_ACK)) != NULL) { 1354 teackp = (struct T_error_ack *)mp->b_rptr; 1355 teackp->ERROR_prim = primitive; 1356 teackp->TLI_error = t_error; 1357 teackp->UNIX_error = sys_error; 1358 qreply(q, mp); 1359 } 1360 } 1361 1362 /*ARGSUSED*/ 1363 static int 1364 udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 1365 { 1366 int i; 1367 1368 for (i = 0; i < udp_g_num_epriv_ports; i++) { 1369 if (udp_g_epriv_ports[i] != 0) 1370 (void) mi_mpprintf(mp, "%d ", udp_g_epriv_ports[i]); 1371 } 1372 return (0); 1373 } 1374 1375 /* 1376 * Hold udp_g_lock to prevent multiple threads from changing udp_g_epriv_ports 1377 * at the same time. 1378 */ 1379 /* ARGSUSED */ 1380 static int 1381 udp_extra_priv_ports_add(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 1382 cred_t *cr) 1383 { 1384 long new_value; 1385 int i; 1386 1387 /* 1388 * Fail the request if the new value does not lie within the 1389 * port number limits. 1390 */ 1391 if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 1392 new_value <= 0 || new_value >= 65536) { 1393 return (EINVAL); 1394 } 1395 1396 mutex_enter(&udp_g_lock); 1397 /* Check if the value is already in the list */ 1398 for (i = 0; i < udp_g_num_epriv_ports; i++) { 1399 if (new_value == udp_g_epriv_ports[i]) { 1400 mutex_exit(&udp_g_lock); 1401 return (EEXIST); 1402 } 1403 } 1404 /* Find an empty slot */ 1405 for (i = 0; i < udp_g_num_epriv_ports; i++) { 1406 if (udp_g_epriv_ports[i] == 0) 1407 break; 1408 } 1409 if (i == udp_g_num_epriv_ports) { 1410 mutex_exit(&udp_g_lock); 1411 return (EOVERFLOW); 1412 } 1413 1414 /* Set the new value */ 1415 udp_g_epriv_ports[i] = (in_port_t)new_value; 1416 mutex_exit(&udp_g_lock); 1417 return (0); 1418 } 1419 1420 /* 1421 * Hold udp_g_lock to prevent multiple threads from changing udp_g_epriv_ports 1422 * at the same time. 1423 */ 1424 /* ARGSUSED */ 1425 static int 1426 udp_extra_priv_ports_del(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 1427 cred_t *cr) 1428 { 1429 long new_value; 1430 int i; 1431 1432 /* 1433 * Fail the request if the new value does not lie within the 1434 * port number limits. 1435 */ 1436 if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 1437 new_value <= 0 || new_value >= 65536) { 1438 return (EINVAL); 1439 } 1440 1441 mutex_enter(&udp_g_lock); 1442 /* Check that the value is already in the list */ 1443 for (i = 0; i < udp_g_num_epriv_ports; i++) { 1444 if (udp_g_epriv_ports[i] == new_value) 1445 break; 1446 } 1447 if (i == udp_g_num_epriv_ports) { 1448 mutex_exit(&udp_g_lock); 1449 return (ESRCH); 1450 } 1451 1452 /* Clear the value */ 1453 udp_g_epriv_ports[i] = 0; 1454 mutex_exit(&udp_g_lock); 1455 return (0); 1456 } 1457 1458 /* At minimum we need 4 bytes of UDP header */ 1459 #define ICMP_MIN_UDP_HDR 4 1460 1461 /* 1462 * udp_icmp_error is called by udp_rput to process ICMP msgs. passed up by IP. 1463 * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors. 1464 * Assumes that IP has pulled up everything up to and including the ICMP header. 1465 * An M_CTL could potentially come here from some other module (i.e. if UDP 1466 * is pushed on some module other than IP). Thus, if we find that the M_CTL 1467 * does not have enough ICMP information , following STREAMS conventions, 1468 * we send it upstream assuming it is an M_CTL we don't understand. 1469 */ 1470 static void 1471 udp_icmp_error(queue_t *q, mblk_t *mp) 1472 { 1473 icmph_t *icmph; 1474 ipha_t *ipha; 1475 int iph_hdr_length; 1476 udpha_t *udpha; 1477 sin_t sin; 1478 sin6_t sin6; 1479 mblk_t *mp1; 1480 int error = 0; 1481 udp_t *udp = (udp_t *)q->q_ptr; 1482 size_t mp_size = MBLKL(mp); 1483 1484 /* 1485 * Assume IP provides aligned packets - otherwise toss 1486 */ 1487 if (!OK_32PTR(mp->b_rptr)) { 1488 freemsg(mp); 1489 return; 1490 } 1491 1492 /* 1493 * Verify that we have a complete IP header and the application has 1494 * asked for errors. If not, send it upstream. 1495 */ 1496 if (!udp->udp_dgram_errind || mp_size < sizeof (ipha_t)) { 1497 noticmpv4: 1498 putnext(q, mp); 1499 return; 1500 } 1501 1502 ipha = (ipha_t *)mp->b_rptr; 1503 /* 1504 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent 1505 * upstream. ICMPv6 is handled in udp_icmp_error_ipv6. 1506 */ 1507 switch (IPH_HDR_VERSION(ipha)) { 1508 case IPV6_VERSION: 1509 udp_icmp_error_ipv6(q, mp); 1510 return; 1511 case IPV4_VERSION: 1512 break; 1513 default: 1514 goto noticmpv4; 1515 } 1516 1517 /* Skip past the outer IP and ICMP headers */ 1518 iph_hdr_length = IPH_HDR_LENGTH(ipha); 1519 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 1520 /* 1521 * If we don't have the correct outer IP header length or if the ULP 1522 * is not IPPROTO_ICMP or if we don't have a complete inner IP header 1523 * send the packet upstream. 1524 */ 1525 if (iph_hdr_length < sizeof (ipha_t) || 1526 ipha->ipha_protocol != IPPROTO_ICMP || 1527 (ipha_t *)&icmph[1] + 1 > (ipha_t *)mp->b_wptr) { 1528 goto noticmpv4; 1529 } 1530 ipha = (ipha_t *)&icmph[1]; 1531 1532 /* Skip past the inner IP and find the ULP header */ 1533 iph_hdr_length = IPH_HDR_LENGTH(ipha); 1534 udpha = (udpha_t *)((char *)ipha + iph_hdr_length); 1535 /* 1536 * If we don't have the correct inner IP header length or if the ULP 1537 * is not IPPROTO_UDP or if we don't have at least ICMP_MIN_UDP_HDR 1538 * bytes of UDP header, send it upstream. 1539 */ 1540 if (iph_hdr_length < sizeof (ipha_t) || 1541 ipha->ipha_protocol != IPPROTO_UDP || 1542 (uchar_t *)udpha + ICMP_MIN_UDP_HDR > mp->b_wptr) { 1543 goto noticmpv4; 1544 } 1545 1546 switch (icmph->icmph_type) { 1547 case ICMP_DEST_UNREACHABLE: 1548 switch (icmph->icmph_code) { 1549 case ICMP_FRAGMENTATION_NEEDED: 1550 /* 1551 * IP has already adjusted the path MTU. 1552 * XXX Somehow pass MTU indication to application? 1553 */ 1554 break; 1555 case ICMP_PORT_UNREACHABLE: 1556 case ICMP_PROTOCOL_UNREACHABLE: 1557 error = ECONNREFUSED; 1558 break; 1559 default: 1560 /* Transient errors */ 1561 break; 1562 } 1563 break; 1564 default: 1565 /* Transient errors */ 1566 break; 1567 } 1568 if (error == 0) { 1569 freemsg(mp); 1570 return; 1571 } 1572 1573 switch (udp->udp_family) { 1574 case AF_INET: 1575 sin = sin_null; 1576 sin.sin_family = AF_INET; 1577 sin.sin_addr.s_addr = ipha->ipha_dst; 1578 sin.sin_port = udpha->uha_dst_port; 1579 mp1 = mi_tpi_uderror_ind((char *)&sin, sizeof (sin_t), NULL, 0, 1580 error); 1581 break; 1582 case AF_INET6: 1583 sin6 = sin6_null; 1584 sin6.sin6_family = AF_INET6; 1585 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &sin6.sin6_addr); 1586 sin6.sin6_port = udpha->uha_dst_port; 1587 1588 mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t), 1589 NULL, 0, error); 1590 break; 1591 } 1592 if (mp1) 1593 putnext(q, mp1); 1594 freemsg(mp); 1595 } 1596 1597 /* 1598 * udp_icmp_error_ipv6 is called by udp_icmp_error to process ICMP for IPv6. 1599 * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors. 1600 * Assumes that IP has pulled up all the extension headers as well as the 1601 * ICMPv6 header. 1602 * An M_CTL could potentially come here from some other module (i.e. if UDP 1603 * is pushed on some module other than IP). Thus, if we find that the M_CTL 1604 * does not have enough ICMP information , following STREAMS conventions, 1605 * we send it upstream assuming it is an M_CTL we don't understand. The reason 1606 * it might get here is if the non-ICMP M_CTL accidently has 6 in the version 1607 * field (when cast to ipha_t in udp_icmp_error). 1608 */ 1609 static void 1610 udp_icmp_error_ipv6(queue_t *q, mblk_t *mp) 1611 { 1612 udp_t *udp = (udp_t *)q->q_ptr; 1613 icmp6_t *icmp6; 1614 ip6_t *ip6h, *outer_ip6h; 1615 uint16_t hdr_length; 1616 uint8_t *nexthdrp; 1617 udpha_t *udpha; 1618 sin6_t sin6; 1619 mblk_t *mp1; 1620 int error = 0; 1621 size_t mp_size = MBLKL(mp); 1622 1623 /* 1624 * Verify that we have a complete IP header. If not, send it upstream. 1625 */ 1626 if (mp_size < sizeof (ip6_t)) { 1627 noticmpv6: 1628 putnext(q, mp); 1629 return; 1630 } 1631 1632 outer_ip6h = (ip6_t *)mp->b_rptr; 1633 /* 1634 * Verify this is an ICMPV6 packet, else send it upstream 1635 */ 1636 if (outer_ip6h->ip6_nxt == IPPROTO_ICMPV6) { 1637 hdr_length = IPV6_HDR_LEN; 1638 } else if (!ip_hdr_length_nexthdr_v6(mp, outer_ip6h, &hdr_length, 1639 &nexthdrp) || 1640 *nexthdrp != IPPROTO_ICMPV6) { 1641 goto noticmpv6; 1642 } 1643 icmp6 = (icmp6_t *)&mp->b_rptr[hdr_length]; 1644 ip6h = (ip6_t *)&icmp6[1]; 1645 /* 1646 * Verify we have a complete ICMP and inner IP header. 1647 */ 1648 if ((uchar_t *)&ip6h[1] > mp->b_wptr) 1649 goto noticmpv6; 1650 1651 if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) 1652 goto noticmpv6; 1653 udpha = (udpha_t *)((char *)ip6h + hdr_length); 1654 /* 1655 * Validate inner header. If the ULP is not IPPROTO_UDP or if we don't 1656 * have at least ICMP_MIN_UDP_HDR bytes of UDP header send the 1657 * packet upstream. 1658 */ 1659 if ((*nexthdrp != IPPROTO_UDP) || 1660 ((uchar_t *)udpha + ICMP_MIN_UDP_HDR) > mp->b_wptr) { 1661 goto noticmpv6; 1662 } 1663 1664 switch (icmp6->icmp6_type) { 1665 case ICMP6_DST_UNREACH: 1666 switch (icmp6->icmp6_code) { 1667 case ICMP6_DST_UNREACH_NOPORT: 1668 error = ECONNREFUSED; 1669 break; 1670 case ICMP6_DST_UNREACH_ADMIN: 1671 case ICMP6_DST_UNREACH_NOROUTE: 1672 case ICMP6_DST_UNREACH_BEYONDSCOPE: 1673 case ICMP6_DST_UNREACH_ADDR: 1674 /* Transient errors */ 1675 break; 1676 default: 1677 break; 1678 } 1679 break; 1680 case ICMP6_PACKET_TOO_BIG: { 1681 struct T_unitdata_ind *tudi; 1682 struct T_opthdr *toh; 1683 size_t udi_size; 1684 mblk_t *newmp; 1685 t_scalar_t opt_length = sizeof (struct T_opthdr) + 1686 sizeof (struct ip6_mtuinfo); 1687 sin6_t *sin6; 1688 struct ip6_mtuinfo *mtuinfo; 1689 1690 /* 1691 * If the application has requested to receive path mtu 1692 * information, send up an empty message containing an 1693 * IPV6_PATHMTU ancillary data item. 1694 */ 1695 if (!udp->udp_ipv6_recvpathmtu) 1696 break; 1697 1698 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t) + 1699 opt_length; 1700 if ((newmp = allocb(udi_size, BPRI_MED)) == NULL) { 1701 BUMP_MIB(&udp_mib, udpInErrors); 1702 break; 1703 } 1704 1705 /* 1706 * newmp->b_cont is left to NULL on purpose. This is an 1707 * empty message containing only ancillary data. 1708 */ 1709 newmp->b_datap->db_type = M_PROTO; 1710 tudi = (struct T_unitdata_ind *)newmp->b_rptr; 1711 newmp->b_wptr = (uchar_t *)tudi + udi_size; 1712 tudi->PRIM_type = T_UNITDATA_IND; 1713 tudi->SRC_length = sizeof (sin6_t); 1714 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 1715 tudi->OPT_offset = tudi->SRC_offset + sizeof (sin6_t); 1716 tudi->OPT_length = opt_length; 1717 1718 sin6 = (sin6_t *)&tudi[1]; 1719 bzero(sin6, sizeof (sin6_t)); 1720 sin6->sin6_family = AF_INET6; 1721 sin6->sin6_addr = udp->udp_v6dst; 1722 1723 toh = (struct T_opthdr *)&sin6[1]; 1724 toh->level = IPPROTO_IPV6; 1725 toh->name = IPV6_PATHMTU; 1726 toh->len = opt_length; 1727 toh->status = 0; 1728 1729 mtuinfo = (struct ip6_mtuinfo *)&toh[1]; 1730 bzero(mtuinfo, sizeof (struct ip6_mtuinfo)); 1731 mtuinfo->ip6m_addr.sin6_family = AF_INET6; 1732 mtuinfo->ip6m_addr.sin6_addr = ip6h->ip6_dst; 1733 mtuinfo->ip6m_mtu = icmp6->icmp6_mtu; 1734 /* 1735 * We've consumed everything we need from the original 1736 * message. Free it, then send our empty message. 1737 */ 1738 freemsg(mp); 1739 putnext(q, newmp); 1740 return; 1741 } 1742 case ICMP6_TIME_EXCEEDED: 1743 /* Transient errors */ 1744 break; 1745 case ICMP6_PARAM_PROB: 1746 /* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */ 1747 if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER && 1748 (uchar_t *)ip6h + icmp6->icmp6_pptr == 1749 (uchar_t *)nexthdrp) { 1750 error = ECONNREFUSED; 1751 break; 1752 } 1753 break; 1754 } 1755 if (error == 0) { 1756 freemsg(mp); 1757 return; 1758 } 1759 1760 sin6 = sin6_null; 1761 sin6.sin6_family = AF_INET6; 1762 sin6.sin6_addr = ip6h->ip6_dst; 1763 sin6.sin6_port = udpha->uha_dst_port; 1764 sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK; 1765 1766 mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t), NULL, 0, 1767 error); 1768 if (mp1) 1769 putnext(q, mp1); 1770 freemsg(mp); 1771 } 1772 1773 /* 1774 * This routine responds to T_ADDR_REQ messages. It is called by udp_wput. 1775 * The local address is filled in if endpoint is bound. The remote address 1776 * is filled in if remote address has been precified ("connected endpoint") 1777 * (The concept of connected CLTS sockets is alien to published TPI 1778 * but we support it anyway). 1779 */ 1780 static void 1781 udp_addr_req(queue_t *q, mblk_t *mp) 1782 { 1783 udp_t *udp = (udp_t *)q->q_ptr; 1784 sin_t *sin; 1785 sin6_t *sin6; 1786 mblk_t *ackmp; 1787 struct T_addr_ack *taa; 1788 1789 /* Make it large enough for worst case */ 1790 ackmp = reallocb(mp, sizeof (struct T_addr_ack) + 1791 2 * sizeof (sin6_t), 1); 1792 if (ackmp == NULL) { 1793 udp_err_ack(q, mp, TSYSERR, ENOMEM); 1794 return; 1795 } 1796 taa = (struct T_addr_ack *)ackmp->b_rptr; 1797 1798 bzero(taa, sizeof (struct T_addr_ack)); 1799 ackmp->b_wptr = (uchar_t *)&taa[1]; 1800 1801 taa->PRIM_type = T_ADDR_ACK; 1802 ackmp->b_datap->db_type = M_PCPROTO; 1803 /* 1804 * Note: Following code assumes 32 bit alignment of basic 1805 * data structures like sin_t and struct T_addr_ack. 1806 */ 1807 if (udp->udp_state != TS_UNBND) { 1808 /* 1809 * Fill in local address first 1810 */ 1811 taa->LOCADDR_offset = sizeof (*taa); 1812 if (udp->udp_family == AF_INET) { 1813 taa->LOCADDR_length = sizeof (sin_t); 1814 sin = (sin_t *)&taa[1]; 1815 /* Fill zeroes and then initialize non-zero fields */ 1816 *sin = sin_null; 1817 sin->sin_family = AF_INET; 1818 if (!IN6_IS_ADDR_V4MAPPED_ANY(&udp->udp_v6src) && 1819 !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 1820 IN6_V4MAPPED_TO_IPADDR(&udp->udp_v6src, 1821 sin->sin_addr.s_addr); 1822 } else { 1823 /* 1824 * INADDR_ANY 1825 * udp_v6src is not set, we might be bound to 1826 * broadcast/multicast. Use udp_bound_v6src as 1827 * local address instead (that could 1828 * also still be INADDR_ANY) 1829 */ 1830 IN6_V4MAPPED_TO_IPADDR(&udp->udp_bound_v6src, 1831 sin->sin_addr.s_addr); 1832 } 1833 sin->sin_port = udp->udp_port; 1834 ackmp->b_wptr = (uchar_t *)&sin[1]; 1835 if (udp->udp_state == TS_DATA_XFER) { 1836 /* 1837 * connected, fill remote address too 1838 */ 1839 taa->REMADDR_length = sizeof (sin_t); 1840 /* assumed 32-bit alignment */ 1841 taa->REMADDR_offset = taa->LOCADDR_offset + 1842 taa->LOCADDR_length; 1843 1844 sin = (sin_t *)(ackmp->b_rptr + 1845 taa->REMADDR_offset); 1846 /* initialize */ 1847 *sin = sin_null; 1848 sin->sin_family = AF_INET; 1849 sin->sin_addr.s_addr = 1850 V4_PART_OF_V6(udp->udp_v6dst); 1851 sin->sin_port = udp->udp_dstport; 1852 ackmp->b_wptr = (uchar_t *)&sin[1]; 1853 } 1854 } else { 1855 taa->LOCADDR_length = sizeof (sin6_t); 1856 sin6 = (sin6_t *)&taa[1]; 1857 /* Fill zeroes and then initialize non-zero fields */ 1858 *sin6 = sin6_null; 1859 sin6->sin6_family = AF_INET6; 1860 if (!IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 1861 sin6->sin6_addr = udp->udp_v6src; 1862 } else { 1863 /* 1864 * UNSPECIFIED 1865 * udp_v6src is not set, we might be bound to 1866 * broadcast/multicast. Use udp_bound_v6src as 1867 * local address instead (that could 1868 * also still be UNSPECIFIED) 1869 */ 1870 sin6->sin6_addr = 1871 udp->udp_bound_v6src; 1872 } 1873 sin6->sin6_port = udp->udp_port; 1874 ackmp->b_wptr = (uchar_t *)&sin6[1]; 1875 if (udp->udp_state == TS_DATA_XFER) { 1876 /* 1877 * connected, fill remote address too 1878 */ 1879 taa->REMADDR_length = sizeof (sin6_t); 1880 /* assumed 32-bit alignment */ 1881 taa->REMADDR_offset = taa->LOCADDR_offset + 1882 taa->LOCADDR_length; 1883 1884 sin6 = (sin6_t *)(ackmp->b_rptr + 1885 taa->REMADDR_offset); 1886 /* initialize */ 1887 *sin6 = sin6_null; 1888 sin6->sin6_family = AF_INET6; 1889 sin6->sin6_addr = udp->udp_v6dst; 1890 sin6->sin6_port = udp->udp_dstport; 1891 ackmp->b_wptr = (uchar_t *)&sin6[1]; 1892 } 1893 ackmp->b_wptr = (uchar_t *)&sin6[1]; 1894 } 1895 } 1896 ASSERT(ackmp->b_wptr <= ackmp->b_datap->db_lim); 1897 qreply(q, ackmp); 1898 } 1899 1900 static void 1901 udp_copy_info(struct T_info_ack *tap, udp_t *udp) 1902 { 1903 if (udp->udp_family == AF_INET) { 1904 *tap = udp_g_t_info_ack_ipv4; 1905 } else { 1906 *tap = udp_g_t_info_ack_ipv6; 1907 } 1908 tap->CURRENT_state = udp->udp_state; 1909 tap->OPT_size = udp_max_optsize; 1910 } 1911 1912 /* 1913 * This routine responds to T_CAPABILITY_REQ messages. It is called by 1914 * udp_wput. Much of the T_CAPABILITY_ACK information is copied from 1915 * udp_g_t_info_ack. The current state of the stream is copied from 1916 * udp_state. 1917 */ 1918 static void 1919 udp_capability_req(queue_t *q, mblk_t *mp) 1920 { 1921 udp_t *udp = (udp_t *)q->q_ptr; 1922 t_uscalar_t cap_bits1; 1923 struct T_capability_ack *tcap; 1924 1925 cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1; 1926 1927 mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack), 1928 mp->b_datap->db_type, T_CAPABILITY_ACK); 1929 if (!mp) 1930 return; 1931 1932 tcap = (struct T_capability_ack *)mp->b_rptr; 1933 tcap->CAP_bits1 = 0; 1934 1935 if (cap_bits1 & TC1_INFO) { 1936 udp_copy_info(&tcap->INFO_ack, udp); 1937 tcap->CAP_bits1 |= TC1_INFO; 1938 } 1939 1940 qreply(q, mp); 1941 } 1942 1943 /* 1944 * This routine responds to T_INFO_REQ messages. It is called by udp_wput. 1945 * Most of the T_INFO_ACK information is copied from udp_g_t_info_ack. 1946 * The current state of the stream is copied from udp_state. 1947 */ 1948 static void 1949 udp_info_req(queue_t *q, mblk_t *mp) 1950 { 1951 udp_t *udp = (udp_t *)q->q_ptr; 1952 1953 /* Create a T_INFO_ACK message. */ 1954 mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO, 1955 T_INFO_ACK); 1956 if (!mp) 1957 return; 1958 udp_copy_info((struct T_info_ack *)mp->b_rptr, udp); 1959 qreply(q, mp); 1960 } 1961 1962 /* 1963 * IP recognizes seven kinds of bind requests: 1964 * 1965 * - A zero-length address binds only to the protocol number. 1966 * 1967 * - A 4-byte address is treated as a request to 1968 * validate that the address is a valid local IPv4 1969 * address, appropriate for an application to bind to. 1970 * IP does the verification, but does not make any note 1971 * of the address at this time. 1972 * 1973 * - A 16-byte address contains is treated as a request 1974 * to validate a local IPv6 address, as the 4-byte 1975 * address case above. 1976 * 1977 * - A 16-byte sockaddr_in to validate the local IPv4 address and also 1978 * use it for the inbound fanout of packets. 1979 * 1980 * - A 24-byte sockaddr_in6 to validate the local IPv6 address and also 1981 * use it for the inbound fanout of packets. 1982 * 1983 * - A 12-byte address (ipa_conn_t) containing complete IPv4 fanout 1984 * information consisting of local and remote addresses 1985 * and ports. In this case, the addresses are both 1986 * validated as appropriate for this operation, and, if 1987 * so, the information is retained for use in the 1988 * inbound fanout. 1989 * 1990 * - A 36-byte address address (ipa6_conn_t) containing complete IPv6 1991 * fanout information, like the 12-byte case above. 1992 * 1993 * IP will also fill in the IRE request mblk with information 1994 * regarding our peer. In all cases, we notify IP of our protocol 1995 * type by appending a single protocol byte to the bind request. 1996 */ 1997 static mblk_t * 1998 udp_ip_bind_mp(udp_t *udp, t_scalar_t bind_prim, t_scalar_t addr_length) 1999 { 2000 char *cp; 2001 mblk_t *mp; 2002 struct T_bind_req *tbr; 2003 ipa_conn_t *ac; 2004 ipa6_conn_t *ac6; 2005 sin_t *sin; 2006 sin6_t *sin6; 2007 2008 ASSERT(bind_prim == O_T_BIND_REQ || bind_prim == T_BIND_REQ); 2009 2010 mp = allocb(sizeof (*tbr) + addr_length + 1, BPRI_HI); 2011 if (!mp) 2012 return (mp); 2013 mp->b_datap->db_type = M_PROTO; 2014 tbr = (struct T_bind_req *)mp->b_rptr; 2015 tbr->PRIM_type = bind_prim; 2016 tbr->ADDR_offset = sizeof (*tbr); 2017 tbr->CONIND_number = 0; 2018 tbr->ADDR_length = addr_length; 2019 cp = (char *)&tbr[1]; 2020 switch (addr_length) { 2021 case sizeof (ipa_conn_t): 2022 ASSERT(udp->udp_family == AF_INET); 2023 /* Append a request for an IRE */ 2024 mp->b_cont = allocb(sizeof (ire_t), BPRI_HI); 2025 if (!mp->b_cont) { 2026 freemsg(mp); 2027 return (NULL); 2028 } 2029 mp->b_cont->b_wptr += sizeof (ire_t); 2030 mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE; 2031 2032 /* cp known to be 32 bit aligned */ 2033 ac = (ipa_conn_t *)cp; 2034 ac->ac_laddr = V4_PART_OF_V6(udp->udp_v6src); 2035 ac->ac_faddr = V4_PART_OF_V6(udp->udp_v6dst); 2036 ac->ac_fport = udp->udp_dstport; 2037 ac->ac_lport = udp->udp_port; 2038 break; 2039 2040 case sizeof (ipa6_conn_t): 2041 ASSERT(udp->udp_family == AF_INET6); 2042 /* Append a request for an IRE */ 2043 mp->b_cont = allocb(sizeof (ire_t), BPRI_HI); 2044 if (!mp->b_cont) { 2045 freemsg(mp); 2046 return (NULL); 2047 } 2048 mp->b_cont->b_wptr += sizeof (ire_t); 2049 mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE; 2050 2051 /* cp known to be 32 bit aligned */ 2052 ac6 = (ipa6_conn_t *)cp; 2053 ac6->ac6_laddr = udp->udp_v6src; 2054 ac6->ac6_faddr = udp->udp_v6dst; 2055 ac6->ac6_fport = udp->udp_dstport; 2056 ac6->ac6_lport = udp->udp_port; 2057 break; 2058 2059 case sizeof (sin_t): 2060 ASSERT(udp->udp_family == AF_INET); 2061 /* Append a request for an IRE */ 2062 mp->b_cont = allocb(sizeof (ire_t), BPRI_HI); 2063 if (!mp->b_cont) { 2064 freemsg(mp); 2065 return (NULL); 2066 } 2067 mp->b_cont->b_wptr += sizeof (ire_t); 2068 mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE; 2069 2070 sin = (sin_t *)cp; 2071 *sin = sin_null; 2072 sin->sin_family = AF_INET; 2073 sin->sin_addr.s_addr = V4_PART_OF_V6(udp->udp_bound_v6src); 2074 sin->sin_port = udp->udp_port; 2075 break; 2076 2077 case sizeof (sin6_t): 2078 ASSERT(udp->udp_family == AF_INET6); 2079 /* Append a request for an IRE */ 2080 mp->b_cont = allocb(sizeof (ire_t), BPRI_HI); 2081 if (!mp->b_cont) { 2082 freemsg(mp); 2083 return (NULL); 2084 } 2085 mp->b_cont->b_wptr += sizeof (ire_t); 2086 mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE; 2087 2088 sin6 = (sin6_t *)cp; 2089 *sin6 = sin6_null; 2090 sin6->sin6_family = AF_INET6; 2091 sin6->sin6_addr = udp->udp_bound_v6src; 2092 sin6->sin6_port = udp->udp_port; 2093 break; 2094 } 2095 /* Add protocol number to end */ 2096 cp[addr_length] = (char)IPPROTO_UDP; 2097 mp->b_wptr = (uchar_t *)&cp[addr_length + 1]; 2098 return (mp); 2099 } 2100 2101 /* 2102 * This is the open routine for udp. It allocates a udp_t structure for 2103 * the stream and, on the first open of the module, creates an ND table. 2104 */ 2105 static int 2106 udp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 2107 { 2108 int err; 2109 udp_t *udp; 2110 2111 TRACE_1(TR_FAC_UDP, TR_UDP_OPEN, "udp_open: q %p", q); 2112 2113 /* 2114 * Defer the qprocson until everything is initialized since 2115 * we are D_MTPERQ and after qprocson the rput routine can 2116 * run. 2117 */ 2118 2119 /* If the stream is already open, return immediately. */ 2120 if (q->q_ptr != NULL) 2121 return (0); 2122 2123 /* If this is not a push of udp as a module, fail. */ 2124 if (sflag != MODOPEN) 2125 return (EINVAL); 2126 2127 /* 2128 * Create and initialize a udp_t structure for this stream. 2129 */ 2130 udp = (udp_t *)mi_open_alloc_sleep(sizeof (udp_t)); 2131 2132 /* Set the initial state of the stream and the privilege status. */ 2133 q->q_ptr = WR(q)->q_ptr = udp; 2134 udp->udp_state = TS_UNBND; 2135 if (getmajor(*devp) == (major_t)UDP6_MAJ) { 2136 udp->udp_family = AF_INET6; 2137 udp->udp_ipversion = IPV6_VERSION; 2138 udp->udp_max_hdr_len = IPV6_HDR_LEN + UDPH_SIZE; 2139 udp->udp_ttl = udp_ipv6_hoplimit; 2140 } else { 2141 udp->udp_family = AF_INET; 2142 udp->udp_ipversion = IPV4_VERSION; 2143 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE; 2144 udp->udp_ttl = udp_ipv4_ttl; 2145 } 2146 2147 /* 2148 * The receive hiwat is only looked at on the stream head queue. 2149 * Store in q_hiwat in order to return on SO_RCVBUF getsockopts. 2150 */ 2151 q->q_hiwat = udp_recv_hiwat; 2152 2153 udp->udp_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; 2154 udp->udp_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 2155 udp->udp_credp = credp; 2156 crhold(credp); 2157 2158 udp->udp_zoneid = getzoneid(); 2159 2160 /* 2161 * Acquire the lock and link it into the list of open streams. 2162 */ 2163 mutex_enter(&udp_g_lock); 2164 err = mi_open_link(&udp_g_head, (IDP)udp, devp, flag, sflag, credp); 2165 mutex_exit(&udp_g_lock); 2166 if (err != 0) 2167 goto error; 2168 2169 qprocson(q); 2170 2171 /* 2172 * The transmit hiwat/lowat is only looked at on IP's queue. 2173 * Store in q_hiwat in order to return on SO_SNDBUF 2174 * getsockopts. 2175 */ 2176 WR(q)->q_hiwat = udp_xmit_hiwat; 2177 WR(q)->q_next->q_hiwat = WR(q)->q_hiwat; 2178 WR(q)->q_lowat = udp_xmit_lowat; 2179 WR(q)->q_next->q_lowat = WR(q)->q_lowat; 2180 2181 if (udp->udp_family == AF_INET6) { 2182 /* Build initial header template for transmit */ 2183 if ((err = udp_build_hdrs(q, udp)) != 0) { 2184 qprocsoff(q); 2185 /* 2186 * Unlink the udp structure and release 2187 * the minor device number. 2188 */ 2189 mutex_enter(&udp_g_lock); 2190 mi_close_unlink(&udp_g_head, (IDP)udp); 2191 mutex_exit(&udp_g_lock); 2192 goto error; 2193 } 2194 } 2195 2196 /* Set the Stream head write offset. */ 2197 (void) mi_set_sth_wroff(q, udp->udp_max_hdr_len + udp_wroff_extra); 2198 (void) mi_set_sth_hiwat(q, q->q_hiwat); 2199 return (0); 2200 2201 error: 2202 q->q_ptr = WR(q)->q_ptr = NULL; 2203 crfree(credp); 2204 mi_close_free((IDP)udp); 2205 return (err); 2206 } 2207 2208 /* 2209 * Which UDP options OK to set through T_UNITDATA_REQ... 2210 */ 2211 /* ARGSUSED */ 2212 static boolean_t 2213 udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name) 2214 { 2215 2216 return (B_TRUE); 2217 } 2218 2219 /* 2220 * This routine gets default values of certain options whose default 2221 * values are maintained by protcol specific code 2222 */ 2223 /* ARGSUSED */ 2224 int 2225 udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 2226 { 2227 int *i1 = (int *)ptr; 2228 2229 switch (level) { 2230 case IPPROTO_IP: 2231 switch (name) { 2232 case IP_MULTICAST_TTL: 2233 *ptr = (uchar_t)IP_DEFAULT_MULTICAST_TTL; 2234 return (sizeof (uchar_t)); 2235 case IP_MULTICAST_LOOP: 2236 *ptr = (uchar_t)IP_DEFAULT_MULTICAST_LOOP; 2237 return (sizeof (uchar_t)); 2238 } 2239 break; 2240 case IPPROTO_IPV6: 2241 switch (name) { 2242 case IPV6_MULTICAST_HOPS: 2243 *i1 = IP_DEFAULT_MULTICAST_TTL; 2244 return (sizeof (int)); 2245 case IPV6_MULTICAST_LOOP: 2246 *i1 = IP_DEFAULT_MULTICAST_LOOP; 2247 return (sizeof (int)); 2248 case IPV6_UNICAST_HOPS: 2249 *i1 = udp_ipv6_hoplimit; 2250 return (sizeof (int)); 2251 } 2252 break; 2253 } 2254 return (-1); 2255 } 2256 2257 /* 2258 * This routine retrieves the current status of socket options. 2259 * It returns the size of the option retrieved. 2260 */ 2261 int 2262 udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 2263 { 2264 int *i1 = (int *)ptr; 2265 udp_t *udp = (udp_t *)q->q_ptr; 2266 ip6_pkt_t *ipp = &udp->udp_sticky_ipp; 2267 2268 switch (level) { 2269 case SOL_SOCKET: 2270 switch (name) { 2271 case SO_DEBUG: 2272 *i1 = udp->udp_debug; 2273 break; /* goto sizeof (int) option return */ 2274 case SO_REUSEADDR: 2275 *i1 = udp->udp_reuseaddr; 2276 break; /* goto sizeof (int) option return */ 2277 case SO_TYPE: 2278 *i1 = SOCK_DGRAM; 2279 break; /* goto sizeof (int) option return */ 2280 2281 /* 2282 * The following three items are available here, 2283 * but are only meaningful to IP. 2284 */ 2285 case SO_DONTROUTE: 2286 *i1 = udp->udp_dontroute; 2287 break; /* goto sizeof (int) option return */ 2288 case SO_USELOOPBACK: 2289 *i1 = udp->udp_useloopback; 2290 break; /* goto sizeof (int) option return */ 2291 case SO_BROADCAST: 2292 *i1 = udp->udp_broadcast; 2293 break; /* goto sizeof (int) option return */ 2294 2295 case SO_SNDBUF: 2296 *i1 = q->q_hiwat; 2297 break; /* goto sizeof (int) option return */ 2298 case SO_RCVBUF: 2299 *i1 = RD(q)->q_hiwat; 2300 break; /* goto sizeof (int) option return */ 2301 case SO_DGRAM_ERRIND: 2302 *i1 = udp->udp_dgram_errind; 2303 break; /* goto sizeof (int) option return */ 2304 case SO_RECVUCRED: 2305 *i1 = udp->udp_recvucred; 2306 break; /* goto sizeof (int) option return */ 2307 default: 2308 return (-1); 2309 } 2310 break; 2311 case IPPROTO_IP: 2312 if (udp->udp_family != AF_INET) 2313 return (-1); 2314 switch (name) { 2315 case IP_OPTIONS: 2316 case T_IP_OPTIONS: 2317 if (udp->udp_ip_rcv_options_len) 2318 bcopy(udp->udp_ip_rcv_options, ptr, 2319 udp->udp_ip_rcv_options_len); 2320 return (udp->udp_ip_rcv_options_len); 2321 case IP_TOS: 2322 case T_IP_TOS: 2323 *i1 = (int)udp->udp_type_of_service; 2324 break; /* goto sizeof (int) option return */ 2325 case IP_TTL: 2326 *i1 = (int)udp->udp_ttl; 2327 break; /* goto sizeof (int) option return */ 2328 case IP_MULTICAST_IF: 2329 /* 0 address if not set */ 2330 *(ipaddr_t *)ptr = udp->udp_multicast_if_addr; 2331 return (sizeof (ipaddr_t)); 2332 case IP_MULTICAST_TTL: 2333 *(uchar_t *)ptr = udp->udp_multicast_ttl; 2334 return (sizeof (uchar_t)); 2335 case IP_MULTICAST_LOOP: 2336 *ptr = udp->udp_multicast_loop; 2337 return (sizeof (uint8_t)); 2338 case IP_RECVOPTS: 2339 *i1 = udp->udp_recvopts; 2340 break; /* goto sizeof (int) option return */ 2341 case IP_RECVDSTADDR: 2342 *i1 = udp->udp_recvdstaddr; 2343 break; /* goto sizeof (int) option return */ 2344 case IP_RECVIF: 2345 *i1 = udp->udp_recvif; 2346 break; /* goto sizeof (int) option return */ 2347 case IP_RECVSLLA: 2348 *i1 = udp->udp_recvslla; 2349 break; /* goto sizeof (int) option return */ 2350 case IP_RECVTTL: 2351 *i1 = udp->udp_recvttl; 2352 break; /* goto sizeof (int) option return */ 2353 case IP_ADD_MEMBERSHIP: 2354 case IP_DROP_MEMBERSHIP: 2355 case IP_BLOCK_SOURCE: 2356 case IP_UNBLOCK_SOURCE: 2357 case IP_ADD_SOURCE_MEMBERSHIP: 2358 case IP_DROP_SOURCE_MEMBERSHIP: 2359 case MCAST_JOIN_GROUP: 2360 case MCAST_LEAVE_GROUP: 2361 case MCAST_BLOCK_SOURCE: 2362 case MCAST_UNBLOCK_SOURCE: 2363 case MCAST_JOIN_SOURCE_GROUP: 2364 case MCAST_LEAVE_SOURCE_GROUP: 2365 case IP_DONTFAILOVER_IF: 2366 /* cannot "get" the value for these */ 2367 return (-1); 2368 case IP_BOUND_IF: 2369 /* Zero if not set */ 2370 *i1 = udp->udp_bound_if; 2371 break; /* goto sizeof (int) option return */ 2372 case IP_UNSPEC_SRC: 2373 *i1 = udp->udp_unspec_source; 2374 break; /* goto sizeof (int) option return */ 2375 case IP_XMIT_IF: 2376 *i1 = udp->udp_xmit_if; 2377 break; /* goto sizeof (int) option return */ 2378 default: 2379 return (-1); 2380 } 2381 break; 2382 case IPPROTO_IPV6: 2383 if (udp->udp_family != AF_INET6) 2384 return (-1); 2385 switch (name) { 2386 case IPV6_UNICAST_HOPS: 2387 *i1 = (unsigned int)udp->udp_ttl; 2388 break; /* goto sizeof (int) option return */ 2389 case IPV6_MULTICAST_IF: 2390 /* 0 index if not set */ 2391 *i1 = udp->udp_multicast_if_index; 2392 break; /* goto sizeof (int) option return */ 2393 case IPV6_MULTICAST_HOPS: 2394 *i1 = udp->udp_multicast_ttl; 2395 break; /* goto sizeof (int) option return */ 2396 case IPV6_MULTICAST_LOOP: 2397 *i1 = udp->udp_multicast_loop; 2398 break; /* goto sizeof (int) option return */ 2399 case IPV6_JOIN_GROUP: 2400 case IPV6_LEAVE_GROUP: 2401 case MCAST_JOIN_GROUP: 2402 case MCAST_LEAVE_GROUP: 2403 case MCAST_BLOCK_SOURCE: 2404 case MCAST_UNBLOCK_SOURCE: 2405 case MCAST_JOIN_SOURCE_GROUP: 2406 case MCAST_LEAVE_SOURCE_GROUP: 2407 /* cannot "get" the value for these */ 2408 return (-1); 2409 case IPV6_BOUND_IF: 2410 /* Zero if not set */ 2411 *i1 = udp->udp_bound_if; 2412 break; /* goto sizeof (int) option return */ 2413 case IPV6_UNSPEC_SRC: 2414 *i1 = udp->udp_unspec_source; 2415 break; /* goto sizeof (int) option return */ 2416 case IPV6_RECVPKTINFO: 2417 *i1 = udp->udp_ipv6_recvpktinfo; 2418 break; /* goto sizeof (int) option return */ 2419 case IPV6_RECVTCLASS: 2420 *i1 = udp->udp_ipv6_recvtclass; 2421 break; /* goto sizeof (int) option return */ 2422 case IPV6_RECVPATHMTU: 2423 *i1 = udp->udp_ipv6_recvpathmtu; 2424 break; /* goto sizeof (int) option return */ 2425 case IPV6_RECVHOPLIMIT: 2426 *i1 = udp->udp_ipv6_recvhoplimit; 2427 break; /* goto sizeof (int) option return */ 2428 case IPV6_RECVHOPOPTS: 2429 *i1 = udp->udp_ipv6_recvhopopts; 2430 break; /* goto sizeof (int) option return */ 2431 case IPV6_RECVDSTOPTS: 2432 *i1 = udp->udp_ipv6_recvdstopts; 2433 break; /* goto sizeof (int) option return */ 2434 case _OLD_IPV6_RECVDSTOPTS: 2435 *i1 = udp->udp_old_ipv6_recvdstopts; 2436 break; /* goto sizeof (int) option return */ 2437 case IPV6_RECVRTHDRDSTOPTS: 2438 *i1 = udp->udp_ipv6_recvrthdrdstopts; 2439 break; /* goto sizeof (int) option return */ 2440 case IPV6_RECVRTHDR: 2441 *i1 = udp->udp_ipv6_recvrthdr; 2442 break; /* goto sizeof (int) option return */ 2443 case IPV6_PKTINFO: { 2444 /* XXX assumes that caller has room for max size! */ 2445 struct in6_pktinfo *pkti; 2446 2447 pkti = (struct in6_pktinfo *)ptr; 2448 if (ipp->ipp_fields & IPPF_IFINDEX) 2449 pkti->ipi6_ifindex = ipp->ipp_ifindex; 2450 else 2451 pkti->ipi6_ifindex = 0; 2452 if (ipp->ipp_fields & IPPF_ADDR) 2453 pkti->ipi6_addr = ipp->ipp_addr; 2454 else 2455 pkti->ipi6_addr = ipv6_all_zeros; 2456 return (sizeof (struct in6_pktinfo)); 2457 } 2458 case IPV6_TCLASS: 2459 if (ipp->ipp_fields & IPPF_TCLASS) 2460 *i1 = ipp->ipp_tclass; 2461 else 2462 *i1 = IPV6_FLOW_TCLASS( 2463 IPV6_DEFAULT_VERS_AND_FLOW); 2464 break; /* goto sizeof (int) option return */ 2465 case IPV6_NEXTHOP: { 2466 sin6_t *sin6 = (sin6_t *)ptr; 2467 2468 if (!(ipp->ipp_fields & IPPF_NEXTHOP)) 2469 return (0); 2470 *sin6 = sin6_null; 2471 sin6->sin6_family = AF_INET6; 2472 sin6->sin6_addr = ipp->ipp_nexthop; 2473 return (sizeof (sin6_t)); 2474 } 2475 case IPV6_HOPOPTS: 2476 if (!(ipp->ipp_fields & IPPF_HOPOPTS)) 2477 return (0); 2478 bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen); 2479 return (ipp->ipp_hopoptslen); 2480 case IPV6_RTHDRDSTOPTS: 2481 if (!(ipp->ipp_fields & IPPF_RTDSTOPTS)) 2482 return (0); 2483 bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen); 2484 return (ipp->ipp_rtdstoptslen); 2485 case IPV6_RTHDR: 2486 if (!(ipp->ipp_fields & IPPF_RTHDR)) 2487 return (0); 2488 bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen); 2489 return (ipp->ipp_rthdrlen); 2490 case IPV6_DSTOPTS: 2491 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) 2492 return (0); 2493 bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen); 2494 return (ipp->ipp_dstoptslen); 2495 case IPV6_PATHMTU: 2496 return (ip_fill_mtuinfo(&udp->udp_v6dst, 2497 udp->udp_dstport, (struct ip6_mtuinfo *)ptr)); 2498 default: 2499 return (-1); 2500 } 2501 break; 2502 case IPPROTO_UDP: 2503 switch (name) { 2504 case UDP_ANONPRIVBIND: 2505 *i1 = udp->udp_anon_priv_bind; 2506 break; 2507 case UDP_EXCLBIND: 2508 *i1 = udp->udp_exclbind ? UDP_EXCLBIND : 0; 2509 break; 2510 case UDP_RCVHDR: 2511 *i1 = udp->udp_rcvhdr ? 1 : 0; 2512 break; 2513 default: 2514 return (-1); 2515 } 2516 break; 2517 default: 2518 return (-1); 2519 } 2520 return (sizeof (int)); 2521 } 2522 2523 /* This routine sets socket options. */ 2524 /* ARGSUSED */ 2525 int 2526 udp_opt_set(queue_t *q, uint_t optset_context, int level, 2527 int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 2528 uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk) 2529 { 2530 udp_t *udp = (udp_t *)q->q_ptr; 2531 int *i1 = (int *)invalp; 2532 boolean_t onoff = (*i1 == 0) ? 0 : 1; 2533 boolean_t checkonly; 2534 int error; 2535 2536 switch (optset_context) { 2537 case SETFN_OPTCOM_CHECKONLY: 2538 checkonly = B_TRUE; 2539 /* 2540 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ 2541 * inlen != 0 implies value supplied and 2542 * we have to "pretend" to set it. 2543 * inlen == 0 implies that there is no 2544 * value part in T_CHECK request and just validation 2545 * done elsewhere should be enough, we just return here. 2546 */ 2547 if (inlen == 0) { 2548 *outlenp = 0; 2549 return (0); 2550 } 2551 break; 2552 case SETFN_OPTCOM_NEGOTIATE: 2553 checkonly = B_FALSE; 2554 break; 2555 case SETFN_UD_NEGOTIATE: 2556 case SETFN_CONN_NEGOTIATE: 2557 checkonly = B_FALSE; 2558 /* 2559 * Negotiating local and "association-related" options 2560 * through T_UNITDATA_REQ. 2561 * 2562 * Following routine can filter out ones we do not 2563 * want to be "set" this way. 2564 */ 2565 if (!udp_opt_allow_udr_set(level, name)) { 2566 *outlenp = 0; 2567 return (EINVAL); 2568 } 2569 break; 2570 default: 2571 /* 2572 * We should never get here 2573 */ 2574 *outlenp = 0; 2575 return (EINVAL); 2576 } 2577 2578 ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) || 2579 (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0)); 2580 2581 /* 2582 * For fixed length options, no sanity check 2583 * of passed in length is done. It is assumed *_optcom_req() 2584 * routines do the right thing. 2585 */ 2586 2587 switch (level) { 2588 case SOL_SOCKET: 2589 switch (name) { 2590 case SO_REUSEADDR: 2591 if (!checkonly) 2592 udp->udp_reuseaddr = onoff; 2593 break; 2594 case SO_DEBUG: 2595 if (!checkonly) 2596 udp->udp_debug = onoff; 2597 break; 2598 /* 2599 * The following three items are available here, 2600 * but are only meaningful to IP. 2601 */ 2602 case SO_DONTROUTE: 2603 if (!checkonly) 2604 udp->udp_dontroute = onoff; 2605 break; 2606 case SO_USELOOPBACK: 2607 if (!checkonly) 2608 udp->udp_useloopback = onoff; 2609 break; 2610 case SO_BROADCAST: 2611 if (!checkonly) 2612 udp->udp_broadcast = onoff; 2613 break; 2614 2615 case SO_SNDBUF: 2616 if (*i1 > udp_max_buf) { 2617 *outlenp = 0; 2618 return (ENOBUFS); 2619 } 2620 if (!checkonly) { 2621 q->q_hiwat = *i1; 2622 q->q_next->q_hiwat = *i1; 2623 } 2624 break; 2625 case SO_RCVBUF: 2626 if (*i1 > udp_max_buf) { 2627 *outlenp = 0; 2628 return (ENOBUFS); 2629 } 2630 if (!checkonly) { 2631 RD(q)->q_hiwat = *i1; 2632 (void) mi_set_sth_hiwat(RD(q), *i1); 2633 } 2634 break; 2635 case SO_DGRAM_ERRIND: 2636 if (!checkonly) 2637 udp->udp_dgram_errind = onoff; 2638 break; 2639 case SO_RECVUCRED: 2640 if (!checkonly) 2641 udp->udp_recvucred = onoff; 2642 break; 2643 default: 2644 *outlenp = 0; 2645 return (EINVAL); 2646 } 2647 break; 2648 case IPPROTO_IP: 2649 if (udp->udp_family != AF_INET) { 2650 *outlenp = 0; 2651 return (ENOPROTOOPT); 2652 } 2653 switch (name) { 2654 case IP_OPTIONS: 2655 case T_IP_OPTIONS: 2656 /* Save options for use by IP. */ 2657 if (inlen & 0x3) { 2658 *outlenp = 0; 2659 return (EINVAL); 2660 } 2661 if (checkonly) 2662 break; 2663 2664 if (udp->udp_ip_snd_options) { 2665 mi_free((char *)udp->udp_ip_snd_options); 2666 udp->udp_ip_snd_options_len = 0; 2667 udp->udp_ip_snd_options = NULL; 2668 } 2669 if (inlen) { 2670 udp->udp_ip_snd_options = 2671 (uchar_t *)mi_alloc(inlen, BPRI_HI); 2672 if (udp->udp_ip_snd_options) { 2673 bcopy(invalp, udp->udp_ip_snd_options, 2674 inlen); 2675 udp->udp_ip_snd_options_len = inlen; 2676 } 2677 } 2678 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + 2679 UDPH_SIZE + udp->udp_ip_snd_options_len; 2680 (void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len + 2681 udp_wroff_extra); 2682 break; 2683 case IP_TTL: 2684 if (!checkonly) { 2685 udp->udp_ttl = (uchar_t)*i1; 2686 } 2687 break; 2688 case IP_TOS: 2689 case T_IP_TOS: 2690 if (!checkonly) { 2691 udp->udp_type_of_service = (uchar_t)*i1; 2692 } 2693 break; 2694 case IP_MULTICAST_IF: { 2695 /* 2696 * TODO should check OPTMGMT reply and undo this if 2697 * there is an error. 2698 */ 2699 struct in_addr *inap = (struct in_addr *)invalp; 2700 if (!checkonly) { 2701 udp->udp_multicast_if_addr = 2702 inap->s_addr; 2703 } 2704 break; 2705 } 2706 case IP_MULTICAST_TTL: 2707 if (!checkonly) 2708 udp->udp_multicast_ttl = *invalp; 2709 break; 2710 case IP_MULTICAST_LOOP: 2711 if (!checkonly) 2712 udp->udp_multicast_loop = *invalp; 2713 break; 2714 case IP_RECVOPTS: 2715 if (!checkonly) 2716 udp->udp_recvopts = onoff; 2717 break; 2718 case IP_RECVDSTADDR: 2719 if (!checkonly) 2720 udp->udp_recvdstaddr = onoff; 2721 break; 2722 case IP_RECVIF: 2723 if (!checkonly) 2724 udp->udp_recvif = onoff; 2725 break; 2726 case IP_RECVSLLA: 2727 if (!checkonly) 2728 udp->udp_recvslla = onoff; 2729 break; 2730 case IP_RECVTTL: 2731 if (!checkonly) 2732 udp->udp_recvttl = onoff; 2733 break; 2734 case IP_ADD_MEMBERSHIP: 2735 case IP_DROP_MEMBERSHIP: 2736 case IP_BLOCK_SOURCE: 2737 case IP_UNBLOCK_SOURCE: 2738 case IP_ADD_SOURCE_MEMBERSHIP: 2739 case IP_DROP_SOURCE_MEMBERSHIP: 2740 case MCAST_JOIN_GROUP: 2741 case MCAST_LEAVE_GROUP: 2742 case MCAST_BLOCK_SOURCE: 2743 case MCAST_UNBLOCK_SOURCE: 2744 case MCAST_JOIN_SOURCE_GROUP: 2745 case MCAST_LEAVE_SOURCE_GROUP: 2746 case IP_SEC_OPT: 2747 /* 2748 * "soft" error (negative) 2749 * option not handled at this level 2750 * Do not modify *outlenp. 2751 */ 2752 return (-EINVAL); 2753 case IP_BOUND_IF: 2754 if (!checkonly) 2755 udp->udp_bound_if = *i1; 2756 break; 2757 case IP_UNSPEC_SRC: 2758 if (!checkonly) 2759 udp->udp_unspec_source = onoff; 2760 break; 2761 case IP_XMIT_IF: 2762 if (!checkonly) 2763 udp->udp_xmit_if = *i1; 2764 break; 2765 default: 2766 *outlenp = 0; 2767 return (EINVAL); 2768 } 2769 break; 2770 case IPPROTO_IPV6: { 2771 ip6_pkt_t *ipp; 2772 boolean_t sticky; 2773 2774 if (udp->udp_family != AF_INET6) { 2775 *outlenp = 0; 2776 return (ENOPROTOOPT); 2777 } 2778 /* 2779 * Deal with both sticky options and ancillary data 2780 */ 2781 if (thisdg_attrs == NULL) { 2782 /* sticky options, or none */ 2783 ipp = &udp->udp_sticky_ipp; 2784 sticky = B_TRUE; 2785 } else { 2786 /* ancillary data */ 2787 ipp = (ip6_pkt_t *)thisdg_attrs; 2788 sticky = B_FALSE; 2789 } 2790 2791 switch (name) { 2792 case IPV6_MULTICAST_IF: 2793 if (!checkonly) 2794 udp->udp_multicast_if_index = *i1; 2795 break; 2796 case IPV6_UNICAST_HOPS: 2797 /* -1 means use default */ 2798 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 2799 *outlenp = 0; 2800 return (EINVAL); 2801 } 2802 if (!checkonly) { 2803 if (*i1 == -1) { 2804 udp->udp_ttl = ipp->ipp_unicast_hops = 2805 udp_ipv6_hoplimit; 2806 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 2807 /* Pass modified value to IP. */ 2808 *i1 = udp->udp_ttl; 2809 } else { 2810 udp->udp_ttl = ipp->ipp_unicast_hops = 2811 (uint8_t)*i1; 2812 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 2813 } 2814 /* Rebuild the header template */ 2815 error = udp_build_hdrs(q, udp); 2816 if (error != 0) { 2817 *outlenp = 0; 2818 return (error); 2819 } 2820 } 2821 break; 2822 case IPV6_MULTICAST_HOPS: 2823 /* -1 means use default */ 2824 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 2825 *outlenp = 0; 2826 return (EINVAL); 2827 } 2828 if (!checkonly) { 2829 if (*i1 == -1) { 2830 udp->udp_multicast_ttl = 2831 ipp->ipp_multicast_hops = 2832 IP_DEFAULT_MULTICAST_TTL; 2833 ipp->ipp_fields &= ~IPPF_MULTICAST_HOPS; 2834 /* Pass modified value to IP. */ 2835 *i1 = udp->udp_multicast_ttl; 2836 } else { 2837 udp->udp_multicast_ttl = 2838 ipp->ipp_multicast_hops = 2839 (uint8_t)*i1; 2840 ipp->ipp_fields |= IPPF_MULTICAST_HOPS; 2841 } 2842 } 2843 break; 2844 case IPV6_MULTICAST_LOOP: 2845 if (*i1 != 0 && *i1 != 1) { 2846 *outlenp = 0; 2847 return (EINVAL); 2848 } 2849 if (!checkonly) 2850 udp->udp_multicast_loop = *i1; 2851 break; 2852 case IPV6_JOIN_GROUP: 2853 case IPV6_LEAVE_GROUP: 2854 case MCAST_JOIN_GROUP: 2855 case MCAST_LEAVE_GROUP: 2856 case MCAST_BLOCK_SOURCE: 2857 case MCAST_UNBLOCK_SOURCE: 2858 case MCAST_JOIN_SOURCE_GROUP: 2859 case MCAST_LEAVE_SOURCE_GROUP: 2860 /* 2861 * "soft" error (negative) 2862 * option not handled at this level 2863 * Note: Do not modify *outlenp 2864 */ 2865 return (-EINVAL); 2866 case IPV6_BOUND_IF: 2867 if (!checkonly) 2868 udp->udp_bound_if = *i1; 2869 break; 2870 case IPV6_UNSPEC_SRC: 2871 if (!checkonly) 2872 udp->udp_unspec_source = onoff; 2873 break; 2874 /* 2875 * Set boolean switches for ancillary data delivery 2876 */ 2877 case IPV6_RECVPKTINFO: 2878 if (!checkonly) 2879 udp->udp_ipv6_recvpktinfo = onoff; 2880 break; 2881 case IPV6_RECVTCLASS: 2882 if (!checkonly) { 2883 udp->udp_ipv6_recvtclass = onoff; 2884 } 2885 break; 2886 case IPV6_RECVPATHMTU: 2887 if (!checkonly) { 2888 udp->udp_ipv6_recvpathmtu = onoff; 2889 } 2890 break; 2891 case IPV6_RECVHOPLIMIT: 2892 if (!checkonly) 2893 udp->udp_ipv6_recvhoplimit = onoff; 2894 break; 2895 case IPV6_RECVHOPOPTS: 2896 if (!checkonly) 2897 udp->udp_ipv6_recvhopopts = onoff; 2898 break; 2899 case IPV6_RECVDSTOPTS: 2900 if (!checkonly) 2901 udp->udp_ipv6_recvdstopts = onoff; 2902 break; 2903 case _OLD_IPV6_RECVDSTOPTS: 2904 if (!checkonly) 2905 udp->udp_old_ipv6_recvdstopts = onoff; 2906 break; 2907 case IPV6_RECVRTHDRDSTOPTS: 2908 if (!checkonly) 2909 udp->udp_ipv6_recvrthdrdstopts = onoff; 2910 break; 2911 case IPV6_RECVRTHDR: 2912 if (!checkonly) 2913 udp->udp_ipv6_recvrthdr = onoff; 2914 break; 2915 /* 2916 * Set sticky options or ancillary data. 2917 * If sticky options, (re)build any extension headers 2918 * that might be needed as a result. 2919 */ 2920 case IPV6_PKTINFO: 2921 /* 2922 * The source address and ifindex are verified 2923 * in ip_opt_set(). For ancillary data the 2924 * source address is checked in ip_wput_v6. 2925 */ 2926 if (inlen != 0 && inlen != sizeof (struct in6_pktinfo)) 2927 return (EINVAL); 2928 if (checkonly) 2929 break; 2930 2931 if (inlen == 0) { 2932 ipp->ipp_fields &= ~(IPPF_IFINDEX|IPPF_ADDR); 2933 ipp->ipp_sticky_ignored |= 2934 (IPPF_IFINDEX|IPPF_ADDR); 2935 } else { 2936 struct in6_pktinfo *pkti; 2937 2938 pkti = (struct in6_pktinfo *)invalp; 2939 ipp->ipp_ifindex = pkti->ipi6_ifindex; 2940 ipp->ipp_addr = pkti->ipi6_addr; 2941 if (ipp->ipp_ifindex != 0) 2942 ipp->ipp_fields |= IPPF_IFINDEX; 2943 else 2944 ipp->ipp_fields &= ~IPPF_IFINDEX; 2945 if (!IN6_IS_ADDR_UNSPECIFIED( 2946 &ipp->ipp_addr)) 2947 ipp->ipp_fields |= IPPF_ADDR; 2948 else 2949 ipp->ipp_fields &= ~IPPF_ADDR; 2950 } 2951 if (sticky) { 2952 error = udp_build_hdrs(q, udp); 2953 if (error != 0) 2954 return (error); 2955 } 2956 break; 2957 case IPV6_HOPLIMIT: 2958 if (sticky) 2959 return (EINVAL); 2960 if (inlen != 0 && inlen != sizeof (int)) 2961 return (EINVAL); 2962 if (checkonly) 2963 break; 2964 2965 if (inlen == 0) { 2966 ipp->ipp_fields &= ~IPPF_HOPLIMIT; 2967 ipp->ipp_sticky_ignored |= IPPF_HOPLIMIT; 2968 } else { 2969 if (*i1 > 255 || *i1 < -1) 2970 return (EINVAL); 2971 if (*i1 == -1) 2972 ipp->ipp_hoplimit = udp_ipv6_hoplimit; 2973 else 2974 ipp->ipp_hoplimit = *i1; 2975 ipp->ipp_fields |= IPPF_HOPLIMIT; 2976 } 2977 break; 2978 case IPV6_TCLASS: 2979 if (inlen != 0 && inlen != sizeof (int)) 2980 return (EINVAL); 2981 if (checkonly) 2982 break; 2983 2984 if (inlen == 0) { 2985 ipp->ipp_fields &= ~IPPF_TCLASS; 2986 ipp->ipp_sticky_ignored |= IPPF_TCLASS; 2987 } else { 2988 if (*i1 > 255 || *i1 < -1) 2989 return (EINVAL); 2990 if (*i1 == -1) 2991 ipp->ipp_tclass = 0; 2992 else 2993 ipp->ipp_tclass = *i1; 2994 ipp->ipp_fields |= IPPF_TCLASS; 2995 } 2996 if (sticky) { 2997 error = udp_build_hdrs(q, udp); 2998 if (error != 0) 2999 return (error); 3000 } 3001 break; 3002 case IPV6_NEXTHOP: 3003 /* 3004 * IP will verify that the nexthop is reachable 3005 * and fail for sticky options. 3006 */ 3007 if (inlen != 0 && inlen != sizeof (sin6_t)) 3008 return (EINVAL); 3009 if (checkonly) 3010 break; 3011 3012 if (inlen == 0) { 3013 ipp->ipp_fields &= ~IPPF_NEXTHOP; 3014 ipp->ipp_sticky_ignored |= IPPF_NEXTHOP; 3015 } else { 3016 sin6_t *sin6 = (sin6_t *)invalp; 3017 3018 if (sin6->sin6_family != AF_INET6) 3019 return (EAFNOSUPPORT); 3020 if (IN6_IS_ADDR_V4MAPPED( 3021 &sin6->sin6_addr)) 3022 return (EADDRNOTAVAIL); 3023 ipp->ipp_nexthop = sin6->sin6_addr; 3024 if (!IN6_IS_ADDR_UNSPECIFIED( 3025 &ipp->ipp_nexthop)) 3026 ipp->ipp_fields |= IPPF_NEXTHOP; 3027 else 3028 ipp->ipp_fields &= ~IPPF_NEXTHOP; 3029 } 3030 if (sticky) { 3031 error = udp_build_hdrs(q, udp); 3032 if (error != 0) 3033 return (error); 3034 } 3035 break; 3036 case IPV6_HOPOPTS: { 3037 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 3038 /* 3039 * Sanity checks - minimum size, size a multiple of 3040 * eight bytes, and matching size passed in. 3041 */ 3042 if (inlen != 0 && 3043 inlen != (8 * (hopts->ip6h_len + 1))) 3044 return (EINVAL); 3045 3046 if (checkonly) 3047 break; 3048 3049 if (inlen == 0) { 3050 if (sticky && 3051 (ipp->ipp_fields & IPPF_HOPOPTS) != 0) { 3052 kmem_free(ipp->ipp_hopopts, 3053 ipp->ipp_hopoptslen); 3054 ipp->ipp_hopopts = NULL; 3055 ipp->ipp_hopoptslen = 0; 3056 } 3057 ipp->ipp_fields &= ~IPPF_HOPOPTS; 3058 ipp->ipp_sticky_ignored |= IPPF_HOPOPTS; 3059 } else { 3060 error = udp_pkt_set(invalp, inlen, sticky, 3061 (uchar_t **)&ipp->ipp_hopopts, 3062 &ipp->ipp_hopoptslen); 3063 if (error != 0) 3064 return (error); 3065 ipp->ipp_fields |= IPPF_HOPOPTS; 3066 } 3067 if (sticky) { 3068 error = udp_build_hdrs(q, udp); 3069 if (error != 0) 3070 return (error); 3071 } 3072 break; 3073 } 3074 case IPV6_RTHDRDSTOPTS: { 3075 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 3076 3077 /* 3078 * Sanity checks - minimum size, size a multiple of 3079 * eight bytes, and matching size passed in. 3080 */ 3081 if (inlen != 0 && 3082 inlen != (8 * (dopts->ip6d_len + 1))) 3083 return (EINVAL); 3084 3085 if (checkonly) 3086 break; 3087 3088 if (inlen == 0) { 3089 if (sticky && 3090 (ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) { 3091 kmem_free(ipp->ipp_rtdstopts, 3092 ipp->ipp_rtdstoptslen); 3093 ipp->ipp_rtdstopts = NULL; 3094 ipp->ipp_rtdstoptslen = 0; 3095 } 3096 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 3097 ipp->ipp_sticky_ignored |= IPPF_RTDSTOPTS; 3098 } else { 3099 error = udp_pkt_set(invalp, inlen, sticky, 3100 (uchar_t **)&ipp->ipp_rtdstopts, 3101 &ipp->ipp_rtdstoptslen); 3102 if (error != 0) 3103 return (error); 3104 ipp->ipp_fields |= IPPF_RTDSTOPTS; 3105 } 3106 if (sticky) { 3107 error = udp_build_hdrs(q, udp); 3108 if (error != 0) 3109 return (error); 3110 } 3111 break; 3112 } 3113 case IPV6_DSTOPTS: { 3114 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 3115 3116 /* 3117 * Sanity checks - minimum size, size a multiple of 3118 * eight bytes, and matching size passed in. 3119 */ 3120 if (inlen != 0 && 3121 inlen != (8 * (dopts->ip6d_len + 1))) 3122 return (EINVAL); 3123 3124 if (checkonly) 3125 break; 3126 3127 if (inlen == 0) { 3128 if (sticky && 3129 (ipp->ipp_fields & IPPF_DSTOPTS) != 0) { 3130 kmem_free(ipp->ipp_dstopts, 3131 ipp->ipp_dstoptslen); 3132 ipp->ipp_dstopts = NULL; 3133 ipp->ipp_dstoptslen = 0; 3134 } 3135 ipp->ipp_fields &= ~IPPF_DSTOPTS; 3136 ipp->ipp_sticky_ignored |= IPPF_DSTOPTS; 3137 } else { 3138 error = udp_pkt_set(invalp, inlen, sticky, 3139 (uchar_t **)&ipp->ipp_dstopts, 3140 &ipp->ipp_dstoptslen); 3141 if (error != 0) 3142 return (error); 3143 ipp->ipp_fields |= IPPF_DSTOPTS; 3144 } 3145 if (sticky) { 3146 error = udp_build_hdrs(q, udp); 3147 if (error != 0) 3148 return (error); 3149 } 3150 break; 3151 } 3152 case IPV6_RTHDR: { 3153 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 3154 3155 /* 3156 * Sanity checks - minimum size, size a multiple of 3157 * eight bytes, and matching size passed in. 3158 */ 3159 if (inlen != 0 && 3160 inlen != (8 * (rt->ip6r_len + 1))) 3161 return (EINVAL); 3162 3163 if (checkonly) 3164 break; 3165 3166 if (inlen == 0) { 3167 if (sticky && 3168 (ipp->ipp_fields & IPPF_RTHDR) != 0) { 3169 kmem_free(ipp->ipp_rthdr, 3170 ipp->ipp_rthdrlen); 3171 ipp->ipp_rthdr = NULL; 3172 ipp->ipp_rthdrlen = 0; 3173 } 3174 ipp->ipp_fields &= ~IPPF_RTHDR; 3175 ipp->ipp_sticky_ignored |= IPPF_RTHDR; 3176 } else { 3177 error = udp_pkt_set(invalp, inlen, sticky, 3178 (uchar_t **)&ipp->ipp_rthdr, 3179 &ipp->ipp_rthdrlen); 3180 if (error != 0) 3181 return (error); 3182 ipp->ipp_fields |= IPPF_RTHDR; 3183 } 3184 if (sticky) { 3185 error = udp_build_hdrs(q, udp); 3186 if (error != 0) 3187 return (error); 3188 } 3189 break; 3190 } 3191 3192 case IPV6_DONTFRAG: 3193 if (checkonly) 3194 break; 3195 3196 if (onoff) { 3197 ipp->ipp_fields |= IPPF_DONTFRAG; 3198 } else { 3199 ipp->ipp_fields &= ~IPPF_DONTFRAG; 3200 } 3201 break; 3202 3203 case IPV6_USE_MIN_MTU: 3204 if (inlen != sizeof (int)) 3205 return (EINVAL); 3206 3207 if (*i1 < -1 || *i1 > 1) 3208 return (EINVAL); 3209 3210 if (checkonly) 3211 break; 3212 3213 ipp->ipp_fields |= IPPF_USE_MIN_MTU; 3214 ipp->ipp_use_min_mtu = *i1; 3215 break; 3216 3217 case IPV6_BOUND_PIF: 3218 case IPV6_SEC_OPT: 3219 case IPV6_DONTFAILOVER_IF: 3220 case IPV6_SRC_PREFERENCES: 3221 case IPV6_V6ONLY: 3222 /* Handled at the IP level */ 3223 return (-EINVAL); 3224 default: 3225 *outlenp = 0; 3226 return (EINVAL); 3227 } 3228 break; 3229 } /* end IPPROTO_IPV6 */ 3230 case IPPROTO_UDP: 3231 switch (name) { 3232 case UDP_ANONPRIVBIND: 3233 if ((error = secpolicy_net_privaddr(cr, 0)) != 0) { 3234 *outlenp = 0; 3235 return (error); 3236 } 3237 if (!checkonly) { 3238 udp->udp_anon_priv_bind = onoff; 3239 } 3240 break; 3241 case UDP_EXCLBIND: 3242 if (!checkonly) 3243 udp->udp_exclbind = onoff; 3244 break; 3245 case UDP_RCVHDR: 3246 if (!checkonly) 3247 udp->udp_rcvhdr = onoff; 3248 break; 3249 default: 3250 *outlenp = 0; 3251 return (EINVAL); 3252 } 3253 break; 3254 default: 3255 *outlenp = 0; 3256 return (EINVAL); 3257 } 3258 /* 3259 * Common case of OK return with outval same as inval. 3260 */ 3261 if (invalp != outvalp) { 3262 /* don't trust bcopy for identical src/dst */ 3263 (void) bcopy(invalp, outvalp, inlen); 3264 } 3265 *outlenp = inlen; 3266 return (0); 3267 } 3268 3269 /* 3270 * Update udp_sticky_hdrs based on udp_sticky_ipp, udp_v6src, and udp_ttl. 3271 * The headers include ip6i_t (if needed), ip6_t, any sticky extension 3272 * headers, and the udp header. 3273 * Returns failure if can't allocate memory. 3274 */ 3275 static int 3276 udp_build_hdrs(queue_t *q, udp_t *udp) 3277 { 3278 uchar_t *hdrs; 3279 uint_t hdrs_len; 3280 ip6_t *ip6h; 3281 ip6i_t *ip6i; 3282 udpha_t *udpha; 3283 ip6_pkt_t *ipp = &udp->udp_sticky_ipp; 3284 3285 hdrs_len = ip_total_hdrs_len_v6(ipp) + UDPH_SIZE; 3286 ASSERT(hdrs_len != 0); 3287 if (hdrs_len != udp->udp_sticky_hdrs_len) { 3288 /* Need to reallocate */ 3289 hdrs = kmem_alloc(hdrs_len, KM_NOSLEEP); 3290 if (hdrs == NULL) 3291 return (ENOMEM); 3292 3293 if (udp->udp_sticky_hdrs_len != 0) { 3294 kmem_free(udp->udp_sticky_hdrs, 3295 udp->udp_sticky_hdrs_len); 3296 } 3297 udp->udp_sticky_hdrs = hdrs; 3298 udp->udp_sticky_hdrs_len = hdrs_len; 3299 } 3300 ip_build_hdrs_v6(udp->udp_sticky_hdrs, 3301 udp->udp_sticky_hdrs_len - UDPH_SIZE, ipp, IPPROTO_UDP); 3302 3303 /* Set header fields not in ipp */ 3304 if (ipp->ipp_fields & IPPF_HAS_IP6I) { 3305 ip6i = (ip6i_t *)udp->udp_sticky_hdrs; 3306 ip6h = (ip6_t *)&ip6i[1]; 3307 } else { 3308 ip6h = (ip6_t *)udp->udp_sticky_hdrs; 3309 } 3310 3311 if (!(ipp->ipp_fields & IPPF_ADDR)) 3312 ip6h->ip6_src = udp->udp_v6src; 3313 3314 udpha = (udpha_t *)(udp->udp_sticky_hdrs + hdrs_len - UDPH_SIZE); 3315 udpha->uha_src_port = udp->udp_port; 3316 3317 /* Try to get everything in a single mblk */ 3318 if (hdrs_len > udp->udp_max_hdr_len) { 3319 udp->udp_max_hdr_len = hdrs_len; 3320 (void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len + 3321 udp_wroff_extra); 3322 } 3323 return (0); 3324 } 3325 3326 /* 3327 * Set optbuf and optlen for the option. 3328 * If sticky is set allocate memory (if not already present). 3329 * Otherwise just point optbuf and optlen at invalp and inlen. 3330 * Returns failure if memory can not be allocated. 3331 */ 3332 static int 3333 udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky, 3334 uchar_t **optbufp, uint_t *optlenp) 3335 { 3336 uchar_t *optbuf; 3337 3338 if (!sticky) { 3339 *optbufp = invalp; 3340 *optlenp = inlen; 3341 return (0); 3342 } 3343 if (inlen == *optlenp) { 3344 /* Unchanged length - no need to realocate */ 3345 bcopy(invalp, *optbufp, inlen); 3346 return (0); 3347 } 3348 if (inlen != 0) { 3349 /* Allocate new buffer before free */ 3350 optbuf = kmem_alloc(inlen, KM_NOSLEEP); 3351 if (optbuf == NULL) 3352 return (ENOMEM); 3353 } else { 3354 optbuf = NULL; 3355 } 3356 /* Free old buffer */ 3357 if (*optlenp != 0) 3358 kmem_free(*optbufp, *optlenp); 3359 3360 bcopy(invalp, optbuf, inlen); 3361 *optbufp = optbuf; 3362 *optlenp = inlen; 3363 return (0); 3364 } 3365 3366 /* 3367 * This routine retrieves the value of an ND variable in a udpparam_t 3368 * structure. It is called through nd_getset when a user reads the 3369 * variable. 3370 */ 3371 /* ARGSUSED */ 3372 static int 3373 udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 3374 { 3375 udpparam_t *udppa = (udpparam_t *)cp; 3376 3377 (void) mi_mpprintf(mp, "%d", udppa->udp_param_value); 3378 return (0); 3379 } 3380 3381 /* 3382 * Walk through the param array specified registering each element with the 3383 * named dispatch (ND) handler. 3384 */ 3385 static boolean_t 3386 udp_param_register(udpparam_t *udppa, int cnt) 3387 { 3388 for (; cnt-- > 0; udppa++) { 3389 if (udppa->udp_param_name && udppa->udp_param_name[0]) { 3390 if (!nd_load(&udp_g_nd, udppa->udp_param_name, 3391 udp_param_get, udp_param_set, 3392 (caddr_t)udppa)) { 3393 nd_free(&udp_g_nd); 3394 return (B_FALSE); 3395 } 3396 } 3397 } 3398 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports", 3399 udp_extra_priv_ports_get, NULL, NULL)) { 3400 nd_free(&udp_g_nd); 3401 return (B_FALSE); 3402 } 3403 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_add", 3404 NULL, udp_extra_priv_ports_add, NULL)) { 3405 nd_free(&udp_g_nd); 3406 return (B_FALSE); 3407 } 3408 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_del", 3409 NULL, udp_extra_priv_ports_del, NULL)) { 3410 nd_free(&udp_g_nd); 3411 return (B_FALSE); 3412 } 3413 if (!nd_load(&udp_g_nd, "udp_status", udp_status_report, NULL, 3414 NULL)) { 3415 nd_free(&udp_g_nd); 3416 return (B_FALSE); 3417 } 3418 if (!nd_load(&udp_g_nd, "udp_bind_hash", udp_bind_hash_report, NULL, 3419 NULL)) { 3420 nd_free(&udp_g_nd); 3421 return (B_FALSE); 3422 } 3423 return (B_TRUE); 3424 } 3425 3426 /* This routine sets an ND variable in a udpparam_t structure. */ 3427 /* ARGSUSED */ 3428 static int 3429 udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) 3430 { 3431 long new_value; 3432 udpparam_t *udppa = (udpparam_t *)cp; 3433 3434 /* 3435 * Fail the request if the new value does not lie within the 3436 * required bounds. 3437 */ 3438 if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 3439 new_value < udppa->udp_param_min || 3440 new_value > udppa->udp_param_max) { 3441 return (EINVAL); 3442 } 3443 3444 /* Set the new value */ 3445 udppa->udp_param_value = new_value; 3446 return (0); 3447 } 3448 3449 static void 3450 udp_rput(queue_t *q, mblk_t *mp) 3451 { 3452 struct T_unitdata_ind *tudi; 3453 uchar_t *rptr; 3454 int hdr_length; 3455 int udi_size; /* Size of T_unitdata_ind */ 3456 udp_t *udp; 3457 udpha_t *udpha; 3458 int ipversion; 3459 ip6_pkt_t ipp; 3460 ip6_t *ip6h; 3461 ip6i_t *ip6i; 3462 mblk_t *mp1; 3463 mblk_t *options_mp = NULL; 3464 in_pktinfo_t *pinfo = NULL; 3465 size_t mp_size = MBLKL(mp); 3466 cred_t *cr = NULL; 3467 pid_t cpid; 3468 3469 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START, 3470 "udp_rput_start: q %p mp %p", q, mp); 3471 3472 udp = (udp_t *)q->q_ptr; 3473 rptr = mp->b_rptr; 3474 3475 switch (mp->b_datap->db_type) { 3476 case M_DATA: 3477 /* 3478 * M_DATA messages contain IP datagrams. They are handled 3479 * after this switch. 3480 */ 3481 break; 3482 case M_PROTO: 3483 case M_PCPROTO: 3484 /* M_PROTO messages contain some type of TPI message. */ 3485 if ((mp->b_wptr - rptr) < sizeof (t_scalar_t)) { 3486 freemsg(mp); 3487 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3488 "udp_rput_end: q %p (%S)", q, "protoshort"); 3489 return; 3490 } 3491 qwriter(q, mp, udp_rput_other, PERIM_INNER); 3492 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3493 "udp_rput_end: q %p (%S)", q, "proto"); 3494 return; 3495 case M_FLUSH: 3496 if (*mp->b_rptr & FLUSHR) 3497 flushq(q, FLUSHDATA); 3498 putnext(q, mp); 3499 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3500 "udp_rput_end: q %p (%S)", q, "flush"); 3501 return; 3502 case M_CTL: 3503 if (udp->udp_recvif || udp->udp_recvslla || 3504 udp->udp_ipv6_recvpktinfo) { 3505 /* 3506 * IP should have prepended the options data in an M_CTL 3507 * Check M_CTL "type" to make sure are not here bcos of 3508 * a valid ICMP message 3509 */ 3510 if (mp_size == sizeof (in_pktinfo_t) && 3511 ((in_pktinfo_t *)mp->b_rptr)->in_pkt_ulp_type == 3512 IN_PKTINFO) { 3513 pinfo = (in_pktinfo_t *)mp->b_rptr; 3514 /* 3515 * Jump to normal data processing, this is not 3516 * an ICMP message 3517 */ 3518 break; 3519 } 3520 } 3521 /* 3522 * ICMP messages. 3523 */ 3524 udp_icmp_error(q, mp); 3525 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3526 "udp_rput_end: q %p (%S)", q, "m_ctl"); 3527 return; 3528 default: 3529 putnext(q, mp); 3530 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3531 "udp_rput_end: q %p (%S)", q, "default"); 3532 return; 3533 } 3534 3535 /* 3536 * If we are here bcos the IP_RECVIF or IP_RECVSLLA then we need to 3537 * extract the mblk and adjust the rptr 3538 */ 3539 if (pinfo != NULL) { 3540 ASSERT(mp->b_datap->db_type == M_CTL); 3541 options_mp = mp; 3542 mp = mp->b_cont; 3543 rptr = mp->b_rptr; 3544 mp_size = MBLKL(mp); 3545 } 3546 /* 3547 * This is the inbound data path. 3548 * First, we check to make sure the IP version number is correct, 3549 * and then pull the IP and UDP headers into the first mblk. 3550 */ 3551 /* 3552 * Assume IP provides aligned packets - otherwise toss. 3553 * Also, check if we have a complete IP header. 3554 */ 3555 if (!OK_32PTR(rptr) || (mp_size < sizeof (ipha_t))) { 3556 tossit: 3557 freemsg(mp); 3558 if (options_mp != NULL) 3559 freeb(options_mp); 3560 BUMP_MIB(&udp_mib, udpInErrors); 3561 return; 3562 } 3563 3564 /* Initialize regardless if ipversion is IPv4 or IPv6 */ 3565 ipp.ipp_fields = 0; 3566 3567 ipversion = IPH_HDR_VERSION(rptr); 3568 switch (ipversion) { 3569 case IPV4_VERSION: 3570 hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE; 3571 /* Verify this is a UDP packet */ 3572 if (((ipha_t *)rptr)->ipha_protocol != IPPROTO_UDP) 3573 goto tossit; 3574 if ((hdr_length > IP_SIMPLE_HDR_LENGTH + UDPH_SIZE) || 3575 (udp->udp_ip_rcv_options_len)) { 3576 /* 3577 * Handle IPv4 packets with options outside of the 3578 * main data path. Not needed for AF_INET6 sockets 3579 * since they don't support a getsockopt of IP_OPTIONS. 3580 */ 3581 if (udp->udp_family == AF_INET6) 3582 break; 3583 /* 3584 * UDP length check performed for IPv4 packets with 3585 * options to check whether UDP length specified in 3586 * the header is the same as the physical length of 3587 * the packet. 3588 */ 3589 udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE)); 3590 if (msgdsize(mp) != (ntohs(udpha->uha_length) + 3591 hdr_length - UDPH_SIZE)) { 3592 goto tossit; 3593 } 3594 /* 3595 * Handle the case where the packet has IP options 3596 * and the IP_RECVSLLA & IP_RECVIF are set 3597 */ 3598 if (pinfo != NULL) 3599 mp = options_mp; 3600 qwriter(q, mp, udp_rput_other, PERIM_INNER); 3601 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3602 "udp_rput_end: q %p (%S)", q, "end"); 3603 return; 3604 } 3605 3606 /* Handle IPV6_RECVHOPLIMIT. */ 3607 if ((udp->udp_family == AF_INET6) && (pinfo != NULL)) { 3608 if (pinfo->in_pkt_flags & IPF_RECVIF) { 3609 ipp.ipp_fields |= IPPF_IFINDEX; 3610 ipp.ipp_ifindex = pinfo->in_pkt_ifindex; 3611 } 3612 } 3613 break; 3614 case IPV6_VERSION: 3615 /* 3616 * IPv6 packets can only be received by applications 3617 * that are prepared to receive IPv6 addresses. 3618 * The IP fanout must ensure this. 3619 */ 3620 ASSERT(udp->udp_family == AF_INET6); 3621 3622 ip6h = (ip6_t *)rptr; 3623 if ((uchar_t *)&ip6h[1] > mp->b_wptr) 3624 goto tossit; 3625 3626 if (ip6h->ip6_nxt != IPPROTO_UDP) { 3627 uint8_t nexthdrp; 3628 /* Look for ifindex information */ 3629 if (ip6h->ip6_nxt == IPPROTO_RAW) { 3630 ip6i = (ip6i_t *)ip6h; 3631 if ((uchar_t *)&ip6i[1] > mp->b_wptr) 3632 goto tossit; 3633 3634 if (ip6i->ip6i_flags & IP6I_IFINDEX) { 3635 ASSERT(ip6i->ip6i_ifindex != 0); 3636 ipp.ipp_fields |= IPPF_IFINDEX; 3637 ipp.ipp_ifindex = ip6i->ip6i_ifindex; 3638 } 3639 rptr = (uchar_t *)&ip6i[1]; 3640 mp->b_rptr = rptr; 3641 if (rptr == mp->b_wptr) { 3642 mp1 = mp->b_cont; 3643 freeb(mp); 3644 mp = mp1; 3645 rptr = mp->b_rptr; 3646 } 3647 if (MBLKL(mp) < (IPV6_HDR_LEN + UDPH_SIZE)) 3648 goto tossit; 3649 ip6h = (ip6_t *)rptr; 3650 } 3651 /* 3652 * Find any potentially interesting extension headers 3653 * as well as the length of the IPv6 + extension 3654 * headers. 3655 */ 3656 hdr_length = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdrp) + 3657 UDPH_SIZE; 3658 /* Verify this is a UDP packet */ 3659 if (nexthdrp != IPPROTO_UDP) 3660 goto tossit; 3661 } else { 3662 hdr_length = IPV6_HDR_LEN + UDPH_SIZE; 3663 ip6i = NULL; 3664 } 3665 break; 3666 default: 3667 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3668 "udp_rput_end: q %p (%S)", q, "Unknown IP version"); 3669 goto tossit; 3670 } 3671 3672 /* 3673 * IP inspected the UDP header thus all of it must be in the mblk. 3674 * UDP length check is performed for IPv6 packets and IPv4 packets 3675 * without options to check if the size of the packet as specified 3676 * by the header is the same as the physical size of the packet. 3677 */ 3678 udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE)); 3679 if ((MBLKL(mp) < hdr_length) || 3680 (msgdsize(mp) != (ntohs(udpha->uha_length) + 3681 hdr_length - UDPH_SIZE))) { 3682 goto tossit; 3683 } 3684 3685 /* Walk past the headers. */ 3686 if (!udp->udp_rcvhdr) 3687 mp->b_rptr = rptr + hdr_length; 3688 3689 /* 3690 * This is the inbound data path. Packets are passed upstream as 3691 * T_UNITDATA_IND messages with full IP headers still attached. 3692 */ 3693 if (udp->udp_family == AF_INET) { 3694 sin_t *sin; 3695 3696 ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION); 3697 3698 /* 3699 * Normally only send up the address. 3700 * If IP_RECVDSTADDR is set we include the destination IP 3701 * address as an option. With IP_RECVOPTS we include all 3702 * the IP options. Only ip_rput_other() handles packets 3703 * that contain IP options. 3704 */ 3705 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 3706 if (udp->udp_recvdstaddr) { 3707 udi_size += sizeof (struct T_opthdr) + 3708 sizeof (struct in_addr); 3709 } 3710 3711 /* 3712 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate 3713 * space accordingly 3714 */ 3715 if (udp->udp_recvif && (pinfo != NULL) && 3716 (pinfo->in_pkt_flags & IPF_RECVIF)) { 3717 udi_size += sizeof (struct T_opthdr) + 3718 sizeof (uint_t); 3719 } 3720 3721 if (udp->udp_recvslla && (pinfo != NULL) && 3722 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 3723 udi_size += sizeof (struct T_opthdr) + 3724 sizeof (struct sockaddr_dl); 3725 } 3726 3727 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 3728 udi_size += sizeof (struct T_opthdr) + ucredsize; 3729 cpid = DB_CPID(mp); 3730 } 3731 /* 3732 * If IP_RECVTTL is set allocate the appropriate sized buffer 3733 */ 3734 if (udp->udp_recvttl) { 3735 udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t); 3736 } 3737 3738 ASSERT(IPH_HDR_LENGTH((ipha_t *)rptr) == IP_SIMPLE_HDR_LENGTH); 3739 3740 /* Allocate a message block for the T_UNITDATA_IND structure. */ 3741 mp1 = allocb(udi_size, BPRI_MED); 3742 if (mp1 == NULL) { 3743 freemsg(mp); 3744 if (options_mp != NULL) 3745 freeb(options_mp); 3746 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3747 "udp_rput_end: q %p (%S)", q, "allocbfail"); 3748 BUMP_MIB(&udp_mib, udpInErrors); 3749 return; 3750 } 3751 mp1->b_cont = mp; 3752 mp = mp1; 3753 mp->b_datap->db_type = M_PROTO; 3754 tudi = (struct T_unitdata_ind *)mp->b_rptr; 3755 mp->b_wptr = (uchar_t *)tudi + udi_size; 3756 tudi->PRIM_type = T_UNITDATA_IND; 3757 tudi->SRC_length = sizeof (sin_t); 3758 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 3759 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 3760 sizeof (sin_t); 3761 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t)); 3762 tudi->OPT_length = udi_size; 3763 sin = (sin_t *)&tudi[1]; 3764 sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src; 3765 sin->sin_port = udpha->uha_src_port; 3766 sin->sin_family = udp->udp_family; 3767 *(uint32_t *)&sin->sin_zero[0] = 0; 3768 *(uint32_t *)&sin->sin_zero[4] = 0; 3769 3770 /* 3771 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or 3772 * IP_RECVTTL has been set. 3773 */ 3774 if (udi_size != 0) { 3775 /* 3776 * Copy in destination address before options to avoid 3777 * any padding issues. 3778 */ 3779 char *dstopt; 3780 3781 dstopt = (char *)&sin[1]; 3782 if (udp->udp_recvdstaddr) { 3783 struct T_opthdr *toh; 3784 ipaddr_t *dstptr; 3785 3786 toh = (struct T_opthdr *)dstopt; 3787 toh->level = IPPROTO_IP; 3788 toh->name = IP_RECVDSTADDR; 3789 toh->len = sizeof (struct T_opthdr) + 3790 sizeof (ipaddr_t); 3791 toh->status = 0; 3792 dstopt += sizeof (struct T_opthdr); 3793 dstptr = (ipaddr_t *)dstopt; 3794 *dstptr = ((ipha_t *)rptr)->ipha_dst; 3795 dstopt += sizeof (ipaddr_t); 3796 udi_size -= toh->len; 3797 } 3798 3799 if (udp->udp_recvslla && (pinfo != NULL) && 3800 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 3801 3802 struct T_opthdr *toh; 3803 struct sockaddr_dl *dstptr; 3804 3805 toh = (struct T_opthdr *)dstopt; 3806 toh->level = IPPROTO_IP; 3807 toh->name = IP_RECVSLLA; 3808 toh->len = sizeof (struct T_opthdr) + 3809 sizeof (struct sockaddr_dl); 3810 toh->status = 0; 3811 dstopt += sizeof (struct T_opthdr); 3812 dstptr = (struct sockaddr_dl *)dstopt; 3813 bcopy(&pinfo->in_pkt_slla, dstptr, 3814 sizeof (struct sockaddr_dl)); 3815 dstopt += sizeof (struct sockaddr_dl); 3816 udi_size -= toh->len; 3817 } 3818 3819 if (udp->udp_recvif && (pinfo != NULL) && 3820 (pinfo->in_pkt_flags & IPF_RECVIF)) { 3821 3822 struct T_opthdr *toh; 3823 uint_t *dstptr; 3824 3825 toh = (struct T_opthdr *)dstopt; 3826 toh->level = IPPROTO_IP; 3827 toh->name = IP_RECVIF; 3828 toh->len = sizeof (struct T_opthdr) + 3829 sizeof (uint_t); 3830 toh->status = 0; 3831 dstopt += sizeof (struct T_opthdr); 3832 dstptr = (uint_t *)dstopt; 3833 *dstptr = pinfo->in_pkt_ifindex; 3834 dstopt += sizeof (uint_t); 3835 udi_size -= toh->len; 3836 } 3837 3838 if (cr != NULL) { 3839 struct T_opthdr *toh; 3840 3841 toh = (struct T_opthdr *)dstopt; 3842 toh->level = SOL_SOCKET; 3843 toh->name = SCM_UCRED; 3844 toh->len = sizeof (struct T_opthdr) + ucredsize; 3845 toh->status = 0; 3846 (void) cred2ucred(cr, cpid, &toh[1]); 3847 dstopt += toh->len; 3848 udi_size -= toh->len; 3849 } 3850 3851 if (udp->udp_recvttl) { 3852 struct T_opthdr *toh; 3853 uint8_t *dstptr; 3854 3855 toh = (struct T_opthdr *)dstopt; 3856 toh->level = IPPROTO_IP; 3857 toh->name = IP_RECVTTL; 3858 toh->len = sizeof (struct T_opthdr) + 3859 sizeof (uint8_t); 3860 toh->status = 0; 3861 dstopt += sizeof (struct T_opthdr); 3862 dstptr = (uint8_t *)dstopt; 3863 *dstptr = ((ipha_t *)rptr)->ipha_ttl; 3864 dstopt += sizeof (uint8_t); 3865 udi_size -= toh->len; 3866 } 3867 3868 /* Consumed all of allocated space */ 3869 ASSERT(udi_size == 0); 3870 } 3871 } else { 3872 sin6_t *sin6; 3873 3874 /* 3875 * Handle both IPv4 and IPv6 packets for IPv6 sockets. 3876 * 3877 * Normally we only send up the address. If receiving of any 3878 * optional receive side information is enabled, we also send 3879 * that up as options. 3880 * [ Only udp_rput_other() handles packets that contain IP 3881 * options so code to account for does not appear immediately 3882 * below but elsewhere ] 3883 */ 3884 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t); 3885 3886 if (ipp.ipp_fields & (IPPF_HOPOPTS|IPPF_DSTOPTS|IPPF_RTDSTOPTS| 3887 IPPF_RTHDR|IPPF_IFINDEX)) { 3888 if (udp->udp_ipv6_recvhopopts && 3889 (ipp.ipp_fields & IPPF_HOPOPTS)) { 3890 udi_size += sizeof (struct T_opthdr) + 3891 ipp.ipp_hopoptslen; 3892 } 3893 if ((udp->udp_ipv6_recvdstopts || 3894 udp->udp_old_ipv6_recvdstopts) && 3895 (ipp.ipp_fields & IPPF_DSTOPTS)) { 3896 udi_size += sizeof (struct T_opthdr) + 3897 ipp.ipp_dstoptslen; 3898 } 3899 if (((udp->udp_ipv6_recvdstopts && 3900 udp->udp_ipv6_recvrthdr && 3901 (ipp.ipp_fields & IPPF_RTHDR)) || 3902 udp->udp_ipv6_recvrthdrdstopts) && 3903 (ipp.ipp_fields & IPPF_RTDSTOPTS)) { 3904 udi_size += sizeof (struct T_opthdr) + 3905 ipp.ipp_rtdstoptslen; 3906 } 3907 if (udp->udp_ipv6_recvrthdr && 3908 (ipp.ipp_fields & IPPF_RTHDR)) { 3909 udi_size += sizeof (struct T_opthdr) + 3910 ipp.ipp_rthdrlen; 3911 } 3912 if (udp->udp_ipv6_recvpktinfo && 3913 (ipp.ipp_fields & IPPF_IFINDEX)) { 3914 udi_size += sizeof (struct T_opthdr) + 3915 sizeof (struct in6_pktinfo); 3916 } 3917 3918 } 3919 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 3920 udi_size += sizeof (struct T_opthdr) + ucredsize; 3921 cpid = DB_CPID(mp); 3922 } 3923 3924 if (udp->udp_ipv6_recvhoplimit) 3925 udi_size += sizeof (struct T_opthdr) + sizeof (int); 3926 3927 if (udp->udp_ipv6_recvtclass) 3928 udi_size += sizeof (struct T_opthdr) + sizeof (int); 3929 3930 mp1 = allocb(udi_size, BPRI_MED); 3931 if (mp1 == NULL) { 3932 freemsg(mp); 3933 if (options_mp != NULL) 3934 freeb(options_mp); 3935 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3936 "udp_rput_end: q %p (%S)", q, "allocbfail"); 3937 BUMP_MIB(&udp_mib, udpInErrors); 3938 return; 3939 } 3940 mp1->b_cont = mp; 3941 mp = mp1; 3942 mp->b_datap->db_type = M_PROTO; 3943 tudi = (struct T_unitdata_ind *)mp->b_rptr; 3944 mp->b_wptr = (uchar_t *)tudi + udi_size; 3945 tudi->PRIM_type = T_UNITDATA_IND; 3946 tudi->SRC_length = sizeof (sin6_t); 3947 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 3948 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 3949 sizeof (sin6_t); 3950 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin6_t)); 3951 tudi->OPT_length = udi_size; 3952 sin6 = (sin6_t *)&tudi[1]; 3953 if (ipversion == IPV4_VERSION) { 3954 in6_addr_t v6dst; 3955 3956 IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_src, 3957 &sin6->sin6_addr); 3958 IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_dst, 3959 &v6dst); 3960 sin6->sin6_flowinfo = 0; 3961 sin6->sin6_scope_id = 0; 3962 sin6->__sin6_src_id = ip_srcid_find_addr(&v6dst, 3963 udp->udp_zoneid); 3964 } else { 3965 sin6->sin6_addr = ip6h->ip6_src; 3966 /* No sin6_flowinfo per API */ 3967 sin6->sin6_flowinfo = 0; 3968 /* For link-scope source pass up scope id */ 3969 if ((ipp.ipp_fields & IPPF_IFINDEX) && 3970 IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) 3971 sin6->sin6_scope_id = ipp.ipp_ifindex; 3972 else 3973 sin6->sin6_scope_id = 0; 3974 sin6->__sin6_src_id = 3975 ip_srcid_find_addr(&ip6h->ip6_dst, udp->udp_zoneid); 3976 } 3977 sin6->sin6_port = udpha->uha_src_port; 3978 sin6->sin6_family = udp->udp_family; 3979 3980 if (udi_size != 0) { 3981 uchar_t *dstopt; 3982 3983 dstopt = (uchar_t *)&sin6[1]; 3984 if (udp->udp_ipv6_recvpktinfo && 3985 (ipp.ipp_fields & IPPF_IFINDEX)) { 3986 struct T_opthdr *toh; 3987 struct in6_pktinfo *pkti; 3988 3989 toh = (struct T_opthdr *)dstopt; 3990 toh->level = IPPROTO_IPV6; 3991 toh->name = IPV6_PKTINFO; 3992 toh->len = sizeof (struct T_opthdr) + 3993 sizeof (*pkti); 3994 toh->status = 0; 3995 dstopt += sizeof (struct T_opthdr); 3996 pkti = (struct in6_pktinfo *)dstopt; 3997 if (ipversion == IPV6_VERSION) 3998 pkti->ipi6_addr = ip6h->ip6_dst; 3999 else 4000 IN6_IPADDR_TO_V4MAPPED( 4001 ((ipha_t *)rptr)->ipha_dst, 4002 &pkti->ipi6_addr); 4003 pkti->ipi6_ifindex = ipp.ipp_ifindex; 4004 dstopt += sizeof (*pkti); 4005 udi_size -= toh->len; 4006 } 4007 if (udp->udp_ipv6_recvhoplimit) { 4008 struct T_opthdr *toh; 4009 4010 toh = (struct T_opthdr *)dstopt; 4011 toh->level = IPPROTO_IPV6; 4012 toh->name = IPV6_HOPLIMIT; 4013 toh->len = sizeof (struct T_opthdr) + 4014 sizeof (uint_t); 4015 toh->status = 0; 4016 dstopt += sizeof (struct T_opthdr); 4017 if (ipversion == IPV6_VERSION) 4018 *(uint_t *)dstopt = ip6h->ip6_hops; 4019 else 4020 *(uint_t *)dstopt = 4021 ((ipha_t *)rptr)->ipha_ttl; 4022 dstopt += sizeof (uint_t); 4023 udi_size -= toh->len; 4024 } 4025 if (udp->udp_ipv6_recvtclass) { 4026 struct T_opthdr *toh; 4027 4028 toh = (struct T_opthdr *)dstopt; 4029 toh->level = IPPROTO_IPV6; 4030 toh->name = IPV6_TCLASS; 4031 toh->len = sizeof (struct T_opthdr) + 4032 sizeof (uint_t); 4033 toh->status = 0; 4034 dstopt += sizeof (struct T_opthdr); 4035 if (ipversion == IPV6_VERSION) { 4036 *(uint_t *)dstopt = 4037 IPV6_FLOW_TCLASS(ip6h->ip6_flow); 4038 } else { 4039 ipha_t *ipha = (ipha_t *)rptr; 4040 *(uint_t *)dstopt = 4041 ipha->ipha_type_of_service; 4042 } 4043 dstopt += sizeof (uint_t); 4044 udi_size -= toh->len; 4045 } 4046 if (udp->udp_ipv6_recvhopopts && 4047 (ipp.ipp_fields & IPPF_HOPOPTS)) { 4048 struct T_opthdr *toh; 4049 4050 toh = (struct T_opthdr *)dstopt; 4051 toh->level = IPPROTO_IPV6; 4052 toh->name = IPV6_HOPOPTS; 4053 toh->len = sizeof (struct T_opthdr) + 4054 ipp.ipp_hopoptslen; 4055 toh->status = 0; 4056 dstopt += sizeof (struct T_opthdr); 4057 bcopy(ipp.ipp_hopopts, dstopt, 4058 ipp.ipp_hopoptslen); 4059 dstopt += ipp.ipp_hopoptslen; 4060 udi_size -= toh->len; 4061 } 4062 if (udp->udp_ipv6_recvdstopts && 4063 udp->udp_ipv6_recvrthdr && 4064 (ipp.ipp_fields & IPPF_RTHDR) && 4065 (ipp.ipp_fields & IPPF_RTDSTOPTS)) { 4066 struct T_opthdr *toh; 4067 4068 toh = (struct T_opthdr *)dstopt; 4069 toh->level = IPPROTO_IPV6; 4070 toh->name = IPV6_DSTOPTS; 4071 toh->len = sizeof (struct T_opthdr) + 4072 ipp.ipp_rtdstoptslen; 4073 toh->status = 0; 4074 dstopt += sizeof (struct T_opthdr); 4075 bcopy(ipp.ipp_rtdstopts, dstopt, 4076 ipp.ipp_rtdstoptslen); 4077 dstopt += ipp.ipp_rtdstoptslen; 4078 udi_size -= toh->len; 4079 } 4080 if (udp->udp_ipv6_recvrthdr && 4081 (ipp.ipp_fields & IPPF_RTHDR)) { 4082 struct T_opthdr *toh; 4083 4084 toh = (struct T_opthdr *)dstopt; 4085 toh->level = IPPROTO_IPV6; 4086 toh->name = IPV6_RTHDR; 4087 toh->len = sizeof (struct T_opthdr) + 4088 ipp.ipp_rthdrlen; 4089 toh->status = 0; 4090 dstopt += sizeof (struct T_opthdr); 4091 bcopy(ipp.ipp_rthdr, dstopt, ipp.ipp_rthdrlen); 4092 dstopt += ipp.ipp_rthdrlen; 4093 udi_size -= toh->len; 4094 } 4095 if (udp->udp_ipv6_recvdstopts && 4096 (ipp.ipp_fields & IPPF_DSTOPTS)) { 4097 struct T_opthdr *toh; 4098 4099 toh = (struct T_opthdr *)dstopt; 4100 toh->level = IPPROTO_IPV6; 4101 toh->name = IPV6_DSTOPTS; 4102 toh->len = sizeof (struct T_opthdr) + 4103 ipp.ipp_dstoptslen; 4104 toh->status = 0; 4105 dstopt += sizeof (struct T_opthdr); 4106 bcopy(ipp.ipp_dstopts, dstopt, 4107 ipp.ipp_dstoptslen); 4108 dstopt += ipp.ipp_dstoptslen; 4109 udi_size -= toh->len; 4110 } 4111 4112 if (cr != NULL) { 4113 struct T_opthdr *toh; 4114 4115 toh = (struct T_opthdr *)dstopt; 4116 toh->level = SOL_SOCKET; 4117 toh->name = SCM_UCRED; 4118 toh->len = sizeof (struct T_opthdr) + ucredsize; 4119 toh->status = 0; 4120 (void) cred2ucred(cr, cpid, &toh[1]); 4121 dstopt += toh->len; 4122 udi_size -= toh->len; 4123 } 4124 /* Consumed all of allocated space */ 4125 ASSERT(udi_size == 0); 4126 } 4127 #undef sin6 4128 /* No IP_RECVDSTADDR for IPv6. */ 4129 } 4130 4131 BUMP_MIB(&udp_mib, udpInDatagrams); 4132 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4133 "udp_rput_end: q %p (%S)", q, "end"); 4134 if (options_mp != NULL) 4135 freeb(options_mp); 4136 putnext(q, mp); 4137 } 4138 4139 /* 4140 * Process non-M_DATA messages as well as M_DATA messages that requires 4141 * modifications to udp_ip_rcv_options i.e. IPv4 packets with IP options. 4142 */ 4143 static void 4144 udp_rput_other(queue_t *q, mblk_t *mp) 4145 { 4146 struct T_unitdata_ind *tudi; 4147 mblk_t *mp1; 4148 uchar_t *rptr; 4149 uchar_t *new_rptr; 4150 int hdr_length; 4151 int udi_size; /* Size of T_unitdata_ind */ 4152 int opt_len; /* Length of IP options */ 4153 sin_t *sin; 4154 struct T_error_ack *tea; 4155 udp_t *udp; 4156 mblk_t *options_mp = NULL; 4157 in_pktinfo_t *pinfo; 4158 boolean_t recv_on = B_FALSE; 4159 cred_t *cr = NULL; 4160 pid_t cpid; 4161 4162 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START, 4163 "udp_rput_other: q %p mp %p", q, mp); 4164 4165 ASSERT(OK_32PTR(mp->b_rptr)); 4166 udp = (udp_t *)q->q_ptr; 4167 rptr = mp->b_rptr; 4168 4169 switch (mp->b_datap->db_type) { 4170 case M_CTL: 4171 /* 4172 * We are here only if IP_RECVSLLA and/or IP_RECVIF are set 4173 */ 4174 recv_on = B_TRUE; 4175 options_mp = mp; 4176 pinfo = (in_pktinfo_t *)options_mp->b_rptr; 4177 4178 /* 4179 * The actual data is in mp->b_cont 4180 */ 4181 mp = mp->b_cont; 4182 ASSERT(OK_32PTR(mp->b_rptr)); 4183 rptr = mp->b_rptr; 4184 break; 4185 case M_DATA: 4186 /* 4187 * M_DATA messages contain IPv4 datagrams. They are handled 4188 * after this switch. 4189 */ 4190 break; 4191 case M_PROTO: 4192 case M_PCPROTO: 4193 /* M_PROTO messages contain some type of TPI message. */ 4194 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 4195 if (mp->b_wptr - rptr < sizeof (t_scalar_t)) { 4196 freemsg(mp); 4197 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4198 "udp_rput_other_end: q %p (%S)", q, "protoshort"); 4199 return; 4200 } 4201 tea = (struct T_error_ack *)rptr; 4202 4203 switch (tea->PRIM_type) { 4204 case T_ERROR_ACK: 4205 switch (tea->ERROR_prim) { 4206 case O_T_BIND_REQ: 4207 case T_BIND_REQ: { 4208 /* 4209 * If our O_T_BIND_REQ/T_BIND_REQ fails, 4210 * clear out the associated port and source 4211 * address before passing the message 4212 * upstream. If this was caused by a T_CONN_REQ 4213 * revert back to bound state. 4214 */ 4215 udp_fanout_t *udpf; 4216 4217 udpf = &udp_bind_fanout[ 4218 UDP_BIND_HASH(udp->udp_port)]; 4219 mutex_enter(&udpf->uf_lock); 4220 if (udp->udp_state == TS_DATA_XFER) { 4221 /* Connect failed */ 4222 tea->ERROR_prim = T_CONN_REQ; 4223 /* Revert back to the bound source */ 4224 udp->udp_v6src = udp->udp_bound_v6src; 4225 udp->udp_state = TS_IDLE; 4226 mutex_exit(&udpf->uf_lock); 4227 if (udp->udp_family == AF_INET6) 4228 (void) udp_build_hdrs(q, udp); 4229 break; 4230 } 4231 4232 if (udp->udp_discon_pending) { 4233 tea->ERROR_prim = T_DISCON_REQ; 4234 udp->udp_discon_pending = 0; 4235 } 4236 V6_SET_ZERO(udp->udp_v6src); 4237 V6_SET_ZERO(udp->udp_bound_v6src); 4238 udp->udp_state = TS_UNBND; 4239 udp_bind_hash_remove(udp, B_TRUE); 4240 udp->udp_port = 0; 4241 mutex_exit(&udpf->uf_lock); 4242 if (udp->udp_family == AF_INET6) 4243 (void) udp_build_hdrs(q, udp); 4244 break; 4245 } 4246 default: 4247 break; 4248 } 4249 break; 4250 case T_BIND_ACK: 4251 udp_rput_bind_ack(q, mp); 4252 return; 4253 4254 case T_OPTMGMT_ACK: 4255 case T_OK_ACK: 4256 break; 4257 default: 4258 freemsg(mp); 4259 return; 4260 } 4261 putnext(q, mp); 4262 return; 4263 } 4264 4265 /* 4266 * This is the inbound data path. 4267 * First, we make sure the data contains both IP and UDP headers. 4268 * 4269 * This handle IPv4 packets for only AF_INET sockets. 4270 * AF_INET6 sockets can never access udp_ip_rcv_options thus there 4271 * is no need saving the options. 4272 */ 4273 ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION); 4274 hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE; 4275 if (mp->b_wptr - rptr < hdr_length) { 4276 if (!pullupmsg(mp, hdr_length)) { 4277 freemsg(mp); 4278 if (options_mp != NULL) 4279 freeb(options_mp); 4280 BUMP_MIB(&udp_mib, udpInErrors); 4281 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4282 "udp_rput_other_end: q %p (%S)", q, "hdrshort"); 4283 BUMP_MIB(&udp_mib, udpInErrors); 4284 return; 4285 } 4286 rptr = mp->b_rptr; 4287 } 4288 /* Walk past the headers. */ 4289 new_rptr = rptr + hdr_length; 4290 if (!udp->udp_rcvhdr) 4291 mp->b_rptr = new_rptr; 4292 4293 /* Save the options if any */ 4294 opt_len = hdr_length - (IP_SIMPLE_HDR_LENGTH + UDPH_SIZE); 4295 if (opt_len > 0) { 4296 if (opt_len > udp->udp_ip_rcv_options_len) { 4297 if (udp->udp_ip_rcv_options_len) 4298 mi_free((char *)udp->udp_ip_rcv_options); 4299 udp->udp_ip_rcv_options_len = 0; 4300 udp->udp_ip_rcv_options = 4301 (uchar_t *)mi_alloc(opt_len, BPRI_HI); 4302 if (udp->udp_ip_rcv_options) 4303 udp->udp_ip_rcv_options_len = opt_len; 4304 } 4305 if (udp->udp_ip_rcv_options_len) { 4306 bcopy(rptr + IP_SIMPLE_HDR_LENGTH, 4307 udp->udp_ip_rcv_options, opt_len); 4308 /* Adjust length if we are resusing the space */ 4309 udp->udp_ip_rcv_options_len = opt_len; 4310 } 4311 } else if (udp->udp_ip_rcv_options_len) { 4312 mi_free((char *)udp->udp_ip_rcv_options); 4313 udp->udp_ip_rcv_options = NULL; 4314 udp->udp_ip_rcv_options_len = 0; 4315 } 4316 4317 /* 4318 * Normally only send up the address. 4319 * If IP_RECVDSTADDR is set we include the destination IP 4320 * address as an option. With IP_RECVOPTS we include all 4321 * the IP options. 4322 */ 4323 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 4324 if (udp->udp_recvdstaddr) { 4325 udi_size += sizeof (struct T_opthdr) + sizeof (struct in_addr); 4326 } 4327 if (udp->udp_recvopts && opt_len > 0) 4328 udi_size += sizeof (struct T_opthdr) + opt_len; 4329 4330 /* 4331 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate 4332 * space accordingly 4333 */ 4334 if (udp->udp_recvif && recv_on && 4335 (pinfo->in_pkt_flags & IPF_RECVIF)) { 4336 udi_size += sizeof (struct T_opthdr) + 4337 sizeof (uint_t); 4338 } 4339 4340 if (udp->udp_recvslla && recv_on && 4341 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 4342 udi_size += sizeof (struct T_opthdr) + 4343 sizeof (struct sockaddr_dl); 4344 } 4345 4346 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 4347 udi_size += sizeof (struct T_opthdr) + ucredsize; 4348 cpid = DB_CPID(mp); 4349 } 4350 /* 4351 * If IP_RECVTTL is set allocate the appropriate sized buffer 4352 */ 4353 if (udp->udp_recvttl) { 4354 udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t); 4355 } 4356 4357 /* Allocate a message block for the T_UNITDATA_IND structure. */ 4358 mp1 = allocb(udi_size, BPRI_MED); 4359 if (mp1 == NULL) { 4360 freemsg(mp); 4361 if (options_mp != NULL) 4362 freeb(options_mp); 4363 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4364 "udp_rput_other_end: q %p (%S)", q, "allocbfail"); 4365 BUMP_MIB(&udp_mib, udpInErrors); 4366 return; 4367 } 4368 mp1->b_cont = mp; 4369 mp = mp1; 4370 mp->b_datap->db_type = M_PROTO; 4371 tudi = (struct T_unitdata_ind *)mp->b_rptr; 4372 mp->b_wptr = (uchar_t *)tudi + udi_size; 4373 tudi->PRIM_type = T_UNITDATA_IND; 4374 tudi->SRC_length = sizeof (sin_t); 4375 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 4376 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 4377 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t)); 4378 tudi->OPT_length = udi_size; 4379 4380 sin = (sin_t *)&tudi[1]; 4381 sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src; 4382 sin->sin_port = ((in_port_t *) 4383 new_rptr)[-(UDPH_SIZE/sizeof (in_port_t))]; 4384 sin->sin_family = AF_INET; 4385 *(uint32_t *)&sin->sin_zero[0] = 0; 4386 *(uint32_t *)&sin->sin_zero[4] = 0; 4387 4388 /* 4389 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or 4390 * IP_RECVTTL has been set. 4391 */ 4392 if (udi_size != 0) { 4393 /* 4394 * Copy in destination address before options to avoid any 4395 * padding issues. 4396 */ 4397 char *dstopt; 4398 4399 dstopt = (char *)&sin[1]; 4400 if (udp->udp_recvdstaddr) { 4401 struct T_opthdr *toh; 4402 ipaddr_t *dstptr; 4403 4404 toh = (struct T_opthdr *)dstopt; 4405 toh->level = IPPROTO_IP; 4406 toh->name = IP_RECVDSTADDR; 4407 toh->len = sizeof (struct T_opthdr) + sizeof (ipaddr_t); 4408 toh->status = 0; 4409 dstopt += sizeof (struct T_opthdr); 4410 dstptr = (ipaddr_t *)dstopt; 4411 *dstptr = (((ipaddr_t *)rptr)[4]); 4412 dstopt += sizeof (ipaddr_t); 4413 udi_size -= toh->len; 4414 } 4415 if (udp->udp_recvopts && udi_size != 0) { 4416 struct T_opthdr *toh; 4417 4418 toh = (struct T_opthdr *)dstopt; 4419 toh->level = IPPROTO_IP; 4420 toh->name = IP_RECVOPTS; 4421 toh->len = sizeof (struct T_opthdr) + opt_len; 4422 toh->status = 0; 4423 dstopt += sizeof (struct T_opthdr); 4424 bcopy(rptr + IP_SIMPLE_HDR_LENGTH, dstopt, opt_len); 4425 dstopt += opt_len; 4426 udi_size -= toh->len; 4427 } 4428 4429 if (udp->udp_recvslla && recv_on && 4430 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 4431 4432 struct T_opthdr *toh; 4433 struct sockaddr_dl *dstptr; 4434 4435 toh = (struct T_opthdr *)dstopt; 4436 toh->level = IPPROTO_IP; 4437 toh->name = IP_RECVSLLA; 4438 toh->len = sizeof (struct T_opthdr) + 4439 sizeof (struct sockaddr_dl); 4440 toh->status = 0; 4441 dstopt += sizeof (struct T_opthdr); 4442 dstptr = (struct sockaddr_dl *)dstopt; 4443 bcopy(&pinfo->in_pkt_slla, dstptr, 4444 sizeof (struct sockaddr_dl)); 4445 dstopt += sizeof (struct sockaddr_dl); 4446 udi_size -= toh->len; 4447 } 4448 4449 if (udp->udp_recvif && recv_on && 4450 (pinfo->in_pkt_flags & IPF_RECVIF)) { 4451 4452 struct T_opthdr *toh; 4453 uint_t *dstptr; 4454 4455 toh = (struct T_opthdr *)dstopt; 4456 toh->level = IPPROTO_IP; 4457 toh->name = IP_RECVIF; 4458 toh->len = sizeof (struct T_opthdr) + 4459 sizeof (uint_t); 4460 toh->status = 0; 4461 dstopt += sizeof (struct T_opthdr); 4462 dstptr = (uint_t *)dstopt; 4463 *dstptr = pinfo->in_pkt_ifindex; 4464 dstopt += sizeof (uint_t); 4465 udi_size -= toh->len; 4466 } 4467 4468 if (cr != NULL) { 4469 struct T_opthdr *toh; 4470 4471 toh = (struct T_opthdr *)dstopt; 4472 toh->level = SOL_SOCKET; 4473 toh->name = SCM_UCRED; 4474 toh->len = sizeof (struct T_opthdr) + ucredsize; 4475 toh->status = 0; 4476 (void) cred2ucred(cr, cpid, &toh[1]); 4477 dstopt += toh->len; 4478 udi_size -= toh->len; 4479 } 4480 4481 if (udp->udp_recvttl) { 4482 struct T_opthdr *toh; 4483 uint8_t *dstptr; 4484 4485 toh = (struct T_opthdr *)dstopt; 4486 toh->level = IPPROTO_IP; 4487 toh->name = IP_RECVTTL; 4488 toh->len = sizeof (struct T_opthdr) + 4489 sizeof (uint8_t); 4490 toh->status = 0; 4491 dstopt += sizeof (struct T_opthdr); 4492 dstptr = (uint8_t *)dstopt; 4493 *dstptr = ((ipha_t *)rptr)->ipha_ttl; 4494 dstopt += sizeof (uint8_t); 4495 udi_size -= toh->len; 4496 } 4497 4498 ASSERT(udi_size == 0); /* "Consumed" all of allocated space */ 4499 } 4500 BUMP_MIB(&udp_mib, udpInDatagrams); 4501 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4502 "udp_rput_other_end: q %p (%S)", q, "end"); 4503 if (options_mp != NULL) 4504 freeb(options_mp); 4505 putnext(q, mp); 4506 } 4507 4508 /* 4509 * Process a T_BIND_ACK 4510 */ 4511 static void 4512 udp_rput_bind_ack(queue_t *q, mblk_t *mp) 4513 { 4514 udp_t *udp = (udp_t *)q->q_ptr; 4515 mblk_t *mp1; 4516 ire_t *ire; 4517 struct T_bind_ack *tba; 4518 uchar_t *addrp; 4519 ipa_conn_t *ac; 4520 ipa6_conn_t *ac6; 4521 4522 if (udp->udp_discon_pending) 4523 udp->udp_discon_pending = 0; 4524 4525 /* 4526 * If a broadcast/multicast address was bound set 4527 * the source address to 0. 4528 * This ensures no datagrams with broadcast address 4529 * as source address are emitted (which would violate 4530 * RFC1122 - Hosts requirements) 4531 * 4532 * Note that when connecting the returned IRE is 4533 * for the destination address and we only perform 4534 * the broadcast check for the source address (it 4535 * is OK to connect to a broadcast/multicast address.) 4536 */ 4537 mp1 = mp->b_cont; 4538 if (mp1 != NULL && mp1->b_datap->db_type == IRE_DB_TYPE) { 4539 ire = (ire_t *)mp1->b_rptr; 4540 4541 /* 4542 * Note: we get IRE_BROADCAST for IPv6 to "mark" a multicast 4543 * local address. 4544 */ 4545 if (ire->ire_type == IRE_BROADCAST && 4546 udp->udp_state != TS_DATA_XFER) { 4547 /* This was just a local bind to a broadcast addr */ 4548 V6_SET_ZERO(udp->udp_v6src); 4549 if (udp->udp_family == AF_INET6) 4550 (void) udp_build_hdrs(q, udp); 4551 } else if (V6_OR_V4_INADDR_ANY(udp->udp_v6src)) { 4552 /* 4553 * Local address not yet set - pick it from the 4554 * T_bind_ack 4555 */ 4556 tba = (struct T_bind_ack *)mp->b_rptr; 4557 addrp = &mp->b_rptr[tba->ADDR_offset]; 4558 switch (udp->udp_family) { 4559 case AF_INET: 4560 if (tba->ADDR_length == sizeof (ipa_conn_t)) { 4561 ac = (ipa_conn_t *)addrp; 4562 } else { 4563 ASSERT(tba->ADDR_length == 4564 sizeof (ipa_conn_x_t)); 4565 ac = &((ipa_conn_x_t *)addrp)->acx_conn; 4566 } 4567 IN6_IPADDR_TO_V4MAPPED(ac->ac_laddr, 4568 &udp->udp_v6src); 4569 break; 4570 case AF_INET6: 4571 if (tba->ADDR_length == sizeof (ipa6_conn_t)) { 4572 ac6 = (ipa6_conn_t *)addrp; 4573 } else { 4574 ASSERT(tba->ADDR_length == 4575 sizeof (ipa6_conn_x_t)); 4576 ac6 = &((ipa6_conn_x_t *) 4577 addrp)->ac6x_conn; 4578 } 4579 udp->udp_v6src = ac6->ac6_laddr; 4580 (void) udp_build_hdrs(q, udp); 4581 break; 4582 } 4583 } 4584 mp1 = mp1->b_cont; 4585 } 4586 /* 4587 * Look for one or more appended ACK message added by 4588 * udp_connect or udp_disconnect. 4589 * If none found just send up the T_BIND_ACK. 4590 * udp_connect has appended a T_OK_ACK and a T_CONN_CON. 4591 * udp_disconnect has appended a T_OK_ACK. 4592 */ 4593 if (mp1 != NULL) { 4594 if (mp->b_cont == mp1) 4595 mp->b_cont = NULL; 4596 else { 4597 ASSERT(mp->b_cont->b_cont == mp1); 4598 mp->b_cont->b_cont = NULL; 4599 } 4600 freemsg(mp); 4601 mp = mp1; 4602 while (mp != NULL) { 4603 mp1 = mp->b_cont; 4604 mp->b_cont = NULL; 4605 putnext(q, mp); 4606 mp = mp1; 4607 } 4608 return; 4609 } 4610 freemsg(mp->b_cont); 4611 mp->b_cont = NULL; 4612 putnext(q, mp); 4613 } 4614 4615 /* 4616 * return SNMP stuff in buffer in mpdata 4617 */ 4618 static int 4619 udp_snmp_get(queue_t *q, mblk_t *mpctl) 4620 { 4621 mblk_t *mpdata; 4622 mblk_t *mp_conn_ctl; 4623 mblk_t *mp6_conn_ctl; 4624 mblk_t *mp_conn_data; 4625 mblk_t *mp6_conn_data; 4626 mblk_t *mp_conn_tail = NULL; 4627 mblk_t *mp6_conn_tail = NULL; 4628 struct opthdr *optp; 4629 IDP idp; 4630 udp_t *udp; 4631 mib2_udpEntry_t ude; 4632 mib2_udp6Entry_t ude6; 4633 int state; 4634 zoneid_t zoneid; 4635 4636 if (mpctl == NULL || 4637 (mpdata = mpctl->b_cont) == NULL || 4638 (mp_conn_ctl = copymsg(mpctl)) == NULL || 4639 (mp6_conn_ctl = copymsg(mpctl)) == NULL) { 4640 freemsg(mp_conn_ctl); 4641 return (0); 4642 } 4643 4644 mp_conn_data = mp_conn_ctl->b_cont; 4645 mp6_conn_data = mp6_conn_ctl->b_cont; 4646 4647 udp = (udp_t *)q->q_ptr; 4648 zoneid = udp->udp_zoneid; 4649 4650 /* fixed length structure for IPv4 and IPv6 counters */ 4651 SET_MIB(udp_mib.udpEntrySize, sizeof (mib2_udpEntry_t)); 4652 SET_MIB(udp_mib.udp6EntrySize, sizeof (mib2_udp6Entry_t)); 4653 optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 4654 optp->level = MIB2_UDP; 4655 optp->name = 0; 4656 (void) snmp_append_data(mpdata, (char *)&udp_mib, sizeof (udp_mib)); 4657 optp->len = msgdsize(mpdata); 4658 qreply(q, mpctl); 4659 4660 mutex_enter(&udp_g_lock); 4661 for (idp = mi_first_ptr(&udp_g_head); 4662 (udp = (udp_t *)idp) != 0; 4663 idp = mi_next_ptr(&udp_g_head, idp)) { 4664 4665 if (zoneid != udp->udp_zoneid) 4666 continue; 4667 4668 /* Note that the port numbers are sent in host byte order */ 4669 4670 if (udp->udp_state == TS_UNBND) 4671 state = MIB2_UDP_unbound; 4672 else if (udp->udp_state == TS_IDLE) 4673 state = MIB2_UDP_idle; 4674 else if (udp->udp_state == TS_DATA_XFER) 4675 state = MIB2_UDP_connected; 4676 else 4677 state = MIB2_UDP_unknown; 4678 4679 /* 4680 * Create an IPv4 table entry for IPv4 entries and also 4681 * any IPv6 entries which are bound to in6addr_any 4682 * (i.e. anything a IPv4 peer could connect/send to). 4683 */ 4684 if (udp->udp_ipversion == IPV4_VERSION || 4685 (udp->udp_state <= TS_IDLE && 4686 IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src))) { 4687 ude.udpEntryInfo.ue_state = state; 4688 /* If in6addr_any this will set it to INADDR_ANY */ 4689 ude.udpLocalAddress = V4_PART_OF_V6(udp->udp_v6src); 4690 ude.udpLocalPort = ntohs(udp->udp_port); 4691 if (udp->udp_state == TS_DATA_XFER) { 4692 /* 4693 * Can potentially get here for v6 socket 4694 * if another process (say, ping) has just 4695 * done a sendto(), changing the state 4696 * from the TS_IDLE above to TS_DATA_XFER 4697 * by the time we hit this part of the code. 4698 */ 4699 ude.udpEntryInfo.ue_RemoteAddress = 4700 V4_PART_OF_V6(udp->udp_v6dst); 4701 ude.udpEntryInfo.ue_RemotePort = 4702 ntohs(udp->udp_dstport); 4703 } else { 4704 ude.udpEntryInfo.ue_RemoteAddress = 0; 4705 ude.udpEntryInfo.ue_RemotePort = 0; 4706 } 4707 (void) snmp_append_data2(mp_conn_data, &mp_conn_tail, 4708 (char *)&ude, sizeof (ude)); 4709 } 4710 if (udp->udp_ipversion == IPV6_VERSION) { 4711 ude6.udp6EntryInfo.ue_state = state; 4712 ude6.udp6LocalAddress = udp->udp_v6src; 4713 ude6.udp6LocalPort = ntohs(udp->udp_port); 4714 ude6.udp6IfIndex = udp->udp_bound_if; 4715 if (udp->udp_state == TS_DATA_XFER) { 4716 ude6.udp6EntryInfo.ue_RemoteAddress = 4717 udp->udp_v6dst; 4718 ude6.udp6EntryInfo.ue_RemotePort = 4719 ntohs(udp->udp_dstport); 4720 } else { 4721 ude6.udp6EntryInfo.ue_RemoteAddress = 4722 sin6_null.sin6_addr; 4723 ude6.udp6EntryInfo.ue_RemotePort = 0; 4724 } 4725 (void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail, 4726 (char *)&ude6, sizeof (ude6)); 4727 } 4728 } 4729 mutex_exit(&udp_g_lock); 4730 4731 /* IPv4 UDP endpoints */ 4732 optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 4733 sizeof (struct T_optmgmt_ack)]; 4734 optp->level = MIB2_UDP; 4735 optp->name = MIB2_UDP_ENTRY; 4736 optp->len = msgdsize(mp_conn_data); 4737 qreply(q, mp_conn_ctl); 4738 4739 /* IPv6 UDP endpoints */ 4740 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 4741 sizeof (struct T_optmgmt_ack)]; 4742 optp->level = MIB2_UDP6; 4743 optp->name = MIB2_UDP6_ENTRY; 4744 optp->len = msgdsize(mp6_conn_data); 4745 qreply(q, mp6_conn_ctl); 4746 4747 return (1); 4748 } 4749 4750 /* 4751 * Return 0 if invalid set request, 1 otherwise, including non-udp requests. 4752 * NOTE: Per MIB-II, UDP has no writable data. 4753 * TODO: If this ever actually tries to set anything, it needs to be 4754 * to do the appropriate locking. 4755 */ 4756 /* ARGSUSED */ 4757 static int 4758 udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name, 4759 uchar_t *ptr, int len) 4760 { 4761 switch (level) { 4762 case MIB2_UDP: 4763 return (0); 4764 default: 4765 return (1); 4766 } 4767 } 4768 4769 static void 4770 udp_report_item(mblk_t *mp, udp_t *udp) 4771 { 4772 char *state; 4773 char addrbuf1[INET6_ADDRSTRLEN]; 4774 char addrbuf2[INET6_ADDRSTRLEN]; 4775 uint_t print_len, buf_len; 4776 4777 buf_len = mp->b_datap->db_lim - mp->b_wptr; 4778 ASSERT(buf_len >= 0); 4779 if (buf_len == 0) 4780 return; 4781 4782 if (udp->udp_state == TS_UNBND) 4783 state = "UNBOUND"; 4784 else if (udp->udp_state == TS_IDLE) 4785 state = "IDLE"; 4786 else if (udp->udp_state == TS_DATA_XFER) 4787 state = "CONNECTED"; 4788 else 4789 state = "UnkState"; 4790 print_len = snprintf((char *)mp->b_wptr, buf_len, 4791 MI_COL_PTRFMT_STR "%4d %5u %s %s %5u %s\n", 4792 (void *)udp, udp->udp_zoneid, ntohs(udp->udp_port), 4793 inet_ntop(AF_INET6, &udp->udp_v6src, 4794 addrbuf1, sizeof (addrbuf1)), 4795 inet_ntop(AF_INET6, &udp->udp_v6dst, 4796 addrbuf2, sizeof (addrbuf2)), 4797 ntohs(udp->udp_dstport), state); 4798 if (print_len < buf_len) { 4799 mp->b_wptr += print_len; 4800 } else { 4801 mp->b_wptr += buf_len; 4802 } 4803 } 4804 4805 /* Report for ndd "udp_status" */ 4806 /* ARGSUSED */ 4807 static int 4808 udp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 4809 { 4810 IDP idp; 4811 udp_t *udp; 4812 zoneid_t zoneid; 4813 4814 /* 4815 * Because of the ndd constraint, at most we can have 64K buffer 4816 * to put in all UDP info. So to be more efficient, just 4817 * allocate a 64K buffer here, assuming we need that large buffer. 4818 * This may be a problem as any user can read udp_status. Therefore 4819 * we limit the rate of doing this using udp_ndd_get_info_interval. 4820 * This should be OK as normal users should not do this too often. 4821 */ 4822 if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) { 4823 if (ddi_get_lbolt() - udp_last_ndd_get_info_time < 4824 drv_usectohz(udp_ndd_get_info_interval * 1000)) { 4825 (void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG); 4826 return (0); 4827 } 4828 } 4829 if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) { 4830 /* The following may work even if we cannot get a large buf. */ 4831 (void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG); 4832 return (0); 4833 } 4834 (void) mi_mpprintf(mp, 4835 "UDP " MI_COL_HDRPAD_STR 4836 /* 12345678[89ABCDEF] */ 4837 " zone lport src addr dest addr port state"); 4838 /* 1234 12345 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx 12345 UNBOUND */ 4839 4840 udp = (udp_t *)q->q_ptr; 4841 zoneid = udp->udp_zoneid; 4842 4843 mutex_enter(&udp_g_lock); 4844 for (idp = mi_first_ptr(&udp_g_head); 4845 (udp = (udp_t *)idp) != 0; 4846 idp = mi_next_ptr(&udp_g_head, idp)) { 4847 4848 if (zoneid != GLOBAL_ZONEID && 4849 zoneid != udp->udp_zoneid) 4850 continue; 4851 4852 udp_report_item(mp->b_cont, udp); 4853 } 4854 mutex_exit(&udp_g_lock); 4855 udp_last_ndd_get_info_time = ddi_get_lbolt(); 4856 return (0); 4857 } 4858 4859 /* 4860 * This routine creates a T_UDERROR_IND message and passes it upstream. 4861 * The address and options are copied from the T_UNITDATA_REQ message 4862 * passed in mp. This message is freed. 4863 */ 4864 static void 4865 udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err) 4866 { 4867 mblk_t *mp1; 4868 struct T_unitdata_req *tudr = (struct T_unitdata_req *)mp->b_rptr; 4869 uchar_t *destaddr, *optaddr; 4870 4871 if ((mp->b_wptr < mp->b_rptr) || 4872 (mp->b_wptr - mp->b_rptr) < sizeof (struct T_unitdata_req)) { 4873 goto done; 4874 } 4875 destaddr = mp->b_rptr + tudr->DEST_offset; 4876 if (destaddr < mp->b_rptr || destaddr >= mp->b_wptr || 4877 destaddr + tudr->DEST_length < mp->b_rptr || 4878 destaddr + tudr->DEST_length > mp->b_wptr) { 4879 goto done; 4880 } 4881 optaddr = mp->b_rptr + tudr->OPT_offset; 4882 if (optaddr < mp->b_rptr || optaddr >= mp->b_wptr || 4883 optaddr + tudr->OPT_length < mp->b_rptr || 4884 optaddr + tudr->OPT_length > mp->b_wptr) { 4885 goto done; 4886 } 4887 mp1 = mi_tpi_uderror_ind((char *)destaddr, tudr->DEST_length, 4888 (char *)optaddr, tudr->OPT_length, err); 4889 if (mp1) 4890 qreply(q, mp1); 4891 4892 done: 4893 freemsg(mp); 4894 } 4895 4896 /* 4897 * This routine removes a port number association from a stream. It 4898 * is called by udp_wput to handle T_UNBIND_REQ messages. 4899 */ 4900 static void 4901 udp_unbind(queue_t *q, mblk_t *mp) 4902 { 4903 udp_t *udp; 4904 4905 udp = (udp_t *)q->q_ptr; 4906 /* If a bind has not been done, we can't unbind. */ 4907 if (udp->udp_state == TS_UNBND) { 4908 udp_err_ack(q, mp, TOUTSTATE, 0); 4909 return; 4910 } 4911 if (cl_inet_unbind != NULL) { 4912 /* 4913 * Running in cluster mode - register unbind information 4914 */ 4915 if (udp->udp_ipversion == IPV4_VERSION) { 4916 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET, 4917 (uint8_t *)(&V4_PART_OF_V6(udp->udp_v6src)), 4918 (in_port_t)udp->udp_port); 4919 } else { 4920 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET6, 4921 (uint8_t *)&(udp->udp_v6src), 4922 (in_port_t)udp->udp_port); 4923 } 4924 } 4925 4926 udp_bind_hash_remove(udp, B_FALSE); 4927 V6_SET_ZERO(udp->udp_v6src); 4928 V6_SET_ZERO(udp->udp_bound_v6src); 4929 udp->udp_port = 0; 4930 udp->udp_state = TS_UNBND; 4931 4932 if (udp->udp_family == AF_INET6) { 4933 int error; 4934 4935 /* Rebuild the header template */ 4936 error = udp_build_hdrs(q, udp); 4937 if (error != 0) { 4938 udp_err_ack(q, mp, TSYSERR, error); 4939 return; 4940 } 4941 } 4942 /* Pass the unbind to IP */ 4943 putnext(q, mp); 4944 } 4945 4946 /* 4947 * Don't let port fall into the privileged range. 4948 * Since the extra priviledged ports can be arbitrary we also 4949 * ensure that we exclude those from consideration. 4950 * udp_g_epriv_ports is not sorted thus we loop over it until 4951 * there are no changes. 4952 */ 4953 static in_port_t 4954 udp_update_next_port(in_port_t port, boolean_t random) 4955 { 4956 int i; 4957 4958 if (random && udp_random_anon_port != 0) { 4959 (void) random_get_pseudo_bytes((uint8_t *)&port, 4960 sizeof (in_port_t)); 4961 /* 4962 * Unless changed by a sys admin, the smallest anon port 4963 * is 32768 and the largest anon port is 65535. It is 4964 * very likely (50%) for the random port to be smaller 4965 * than the smallest anon port. When that happens, 4966 * add port % (anon port range) to the smallest anon 4967 * port to get the random port. It should fall into the 4968 * valid anon port range. 4969 */ 4970 if (port < udp_smallest_anon_port) { 4971 port = udp_smallest_anon_port + 4972 port % (udp_largest_anon_port - 4973 udp_smallest_anon_port); 4974 } 4975 } 4976 4977 retry: 4978 if (port < udp_smallest_anon_port || port > udp_largest_anon_port) 4979 port = udp_smallest_anon_port; 4980 4981 if (port < udp_smallest_nonpriv_port) 4982 port = udp_smallest_nonpriv_port; 4983 4984 for (i = 0; i < udp_g_num_epriv_ports; i++) { 4985 if (port == udp_g_epriv_ports[i]) { 4986 port++; 4987 /* 4988 * Make sure that the port is in the 4989 * valid range. 4990 */ 4991 goto retry; 4992 } 4993 } 4994 return (port); 4995 } 4996 4997 /* 4998 * This routine handles all messages passed downstream. It either 4999 * consumes the message or passes it downstream; it never queues a 5000 * a message. 5001 */ 5002 static void 5003 udp_wput(queue_t *q, mblk_t *mp) 5004 { 5005 uchar_t *rptr = mp->b_rptr; 5006 struct datab *db; 5007 ipha_t *ipha; 5008 udpha_t *udpha; 5009 mblk_t *mp1; 5010 int ip_hdr_length; 5011 #define tudr ((struct T_unitdata_req *)rptr) 5012 uint32_t ip_len; 5013 udp_t *udp; 5014 sin6_t *sin6; 5015 sin_t *sin; 5016 ipaddr_t v4dst; 5017 uint16_t port; 5018 uint_t srcid; 5019 5020 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_START, 5021 "udp_wput_start: q %p mp %p", q, mp); 5022 5023 db = mp->b_datap; 5024 switch (db->db_type) { 5025 case M_PROTO: 5026 case M_PCPROTO: 5027 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 5028 if (mp->b_wptr - rptr >= sizeof (struct T_unitdata_req)) { 5029 /* Detect valid T_UNITDATA_REQ here */ 5030 if (((union T_primitives *)rptr)->type 5031 == T_UNITDATA_REQ) 5032 break; 5033 } 5034 /* FALLTHRU */ 5035 default: 5036 qwriter(q, mp, udp_wput_other, PERIM_INNER); 5037 return; 5038 } 5039 5040 udp = (udp_t *)q->q_ptr; 5041 5042 /* Handle UNITDATA_REQ messages here */ 5043 if (udp->udp_state == TS_UNBND) { 5044 /* If a port has not been bound to the stream, fail. */ 5045 BUMP_MIB(&udp_mib, udpOutErrors); 5046 udp_ud_err(q, mp, EPROTO); 5047 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5048 "udp_wput_end: q %p (%S)", q, "outstate"); 5049 return; 5050 } 5051 mp1 = mp->b_cont; 5052 if (mp1 == NULL) { 5053 BUMP_MIB(&udp_mib, udpOutErrors); 5054 udp_ud_err(q, mp, EPROTO); 5055 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5056 "udp_wput_end: q %p (%S)", q, "badaddr"); 5057 return; 5058 } 5059 5060 if ((rptr + tudr->DEST_offset + tudr->DEST_length) > mp->b_wptr) { 5061 BUMP_MIB(&udp_mib, udpOutErrors); 5062 udp_ud_err(q, mp, EADDRNOTAVAIL); 5063 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5064 "udp_wput_end: q %p (%S)", q, "badaddr"); 5065 return; 5066 } 5067 5068 switch (udp->udp_family) { 5069 case AF_INET6: 5070 sin6 = (sin6_t *)&rptr[tudr->DEST_offset]; 5071 if (!OK_32PTR((char *)sin6) || 5072 tudr->DEST_length != sizeof (sin6_t) || 5073 sin6->sin6_family != AF_INET6) { 5074 BUMP_MIB(&udp_mib, udpOutErrors); 5075 udp_ud_err(q, mp, EADDRNOTAVAIL); 5076 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5077 "udp_wput_end: q %p (%S)", q, "badaddr"); 5078 return; 5079 } 5080 5081 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 5082 /* 5083 * Destination is a non-IPv4-compatible IPv6 address. 5084 * Send out an IPv6 format packet. 5085 */ 5086 udp_wput_ipv6(q, mp, sin6, tudr->OPT_length); 5087 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5088 "udp_wput_end: q %p (%S)", q, "udp_wput_ipv6"); 5089 return; 5090 } 5091 /* 5092 * If the local address is not zero or a mapped address return 5093 * an error. 5094 * I would be possible to send an IPv4 packet but the 5095 * response would never make it back to the application 5096 * since it is bound to a non-mapped address. 5097 */ 5098 if (!IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src) && 5099 !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 5100 BUMP_MIB(&udp_mib, udpOutErrors); 5101 udp_ud_err(q, mp, EADDRNOTAVAIL); 5102 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5103 "udp_wput_end: q %p (%S)", q, "badaddr"); 5104 return; 5105 } 5106 /* Send IPv4 packet without modifying udp_ipversion */ 5107 /* Extract port and ipaddr */ 5108 port = sin6->sin6_port; 5109 IN6_V4MAPPED_TO_IPADDR(&sin6->sin6_addr, v4dst); 5110 srcid = sin6->__sin6_src_id; 5111 break; 5112 5113 case AF_INET: 5114 sin = (sin_t *)&rptr[tudr->DEST_offset]; 5115 if (!OK_32PTR((char *)sin) || 5116 tudr->DEST_length != sizeof (sin_t) || 5117 sin->sin_family != AF_INET) { 5118 BUMP_MIB(&udp_mib, udpOutErrors); 5119 udp_ud_err(q, mp, EADDRNOTAVAIL); 5120 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5121 "udp_wput_end: q %p (%S)", q, "badaddr"); 5122 return; 5123 } 5124 /* Extract port and ipaddr */ 5125 port = sin->sin_port; 5126 v4dst = sin->sin_addr.s_addr; 5127 srcid = 0; 5128 break; 5129 } 5130 5131 5132 /* 5133 * If options passed in, feed it for verification and handling 5134 */ 5135 if (tudr->OPT_length != 0) { 5136 int error; 5137 5138 if (udp_unitdata_opt_process(q, mp, &error, NULL) < 0) { 5139 /* failure */ 5140 BUMP_MIB(&udp_mib, udpOutErrors); 5141 udp_ud_err(q, mp, error); 5142 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5143 "udp_wput_end: q %p (%S)", q, 5144 "udp_unitdata_opt_process"); 5145 return; 5146 } 5147 ASSERT(error == 0); 5148 /* 5149 * Note: success in processing options. 5150 * mp option buffer represented by 5151 * OPT_length/offset now potentially modified 5152 * and contain option setting results 5153 */ 5154 } 5155 5156 /* Add an IP header */ 5157 ip_hdr_length = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE + 5158 udp->udp_ip_snd_options_len; 5159 ipha = (ipha_t *)&mp1->b_rptr[-ip_hdr_length]; 5160 if ((mp1->b_datap->db_ref != 1) || 5161 ((uchar_t *)ipha < mp1->b_datap->db_base) || 5162 !OK_32PTR(ipha)) { 5163 uchar_t *wptr; 5164 5165 mp1 = allocb(ip_hdr_length + udp_wroff_extra, BPRI_LO); 5166 if (!mp1) { 5167 BUMP_MIB(&udp_mib, udpOutErrors); 5168 udp_ud_err(q, mp, ENOMEM); 5169 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5170 "udp_wput_end: q %p (%S)", q, "allocbfail2"); 5171 return; 5172 } 5173 mp1->b_cont = mp->b_cont; 5174 mp->b_cont = mp1; 5175 wptr = mp1->b_datap->db_lim; 5176 mp1->b_wptr = wptr; 5177 ipha = (ipha_t *)(wptr - ip_hdr_length); 5178 } 5179 mp1->b_rptr = (uchar_t *)ipha; 5180 5181 ASSERT((uintptr_t)(mp1->b_wptr - (uchar_t *)ipha) <= 5182 (uintptr_t)UINT_MAX); 5183 5184 ip_hdr_length -= UDPH_SIZE; 5185 #ifdef _BIG_ENDIAN 5186 /* Set version, header length, and tos */ 5187 *(uint16_t *)&ipha->ipha_version_and_hdr_length = 5188 ((((IP_VERSION << 4) | (ip_hdr_length>>2)) << 8) | 5189 udp->udp_type_of_service); 5190 /* Set ttl and protocol */ 5191 *(uint16_t *)&ipha->ipha_ttl = (udp->udp_ttl << 8) | IPPROTO_UDP; 5192 #else 5193 /* Set version, header length, and tos */ 5194 *(uint16_t *)&ipha->ipha_version_and_hdr_length = 5195 ((udp->udp_type_of_service << 8) | 5196 ((IP_VERSION << 4) | (ip_hdr_length>>2))); 5197 /* Set ttl and protocol */ 5198 *(uint16_t *)&ipha->ipha_ttl = (IPPROTO_UDP << 8) | udp->udp_ttl; 5199 #endif 5200 /* 5201 * Copy our address into the packet. If this is zero, 5202 * first look at __sin6_src_id for a hint. If we leave the source 5203 * as INADDR_ANY then ip will fill in the real source address. 5204 */ 5205 IN6_V4MAPPED_TO_IPADDR(&udp->udp_v6src, ipha->ipha_src); 5206 if (srcid != 0 && ipha->ipha_src == INADDR_ANY) { 5207 in6_addr_t v6src; 5208 5209 ip_srcid_find_id(srcid, &v6src, udp->udp_zoneid); 5210 IN6_V4MAPPED_TO_IPADDR(&v6src, ipha->ipha_src); 5211 } 5212 5213 ipha->ipha_fragment_offset_and_flags = 0; 5214 ipha->ipha_ident = 0; 5215 5216 /* Determine length of packet */ 5217 ip_len = (uint32_t)(mp1->b_wptr - (uchar_t *)ipha); 5218 { 5219 mblk_t *mp2; 5220 if ((mp2 = mp1->b_cont) != NULL) { 5221 do { 5222 ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) 5223 <= (uintptr_t)UINT_MAX); 5224 ip_len += (uint32_t)(mp2->b_wptr - mp2->b_rptr); 5225 } while ((mp2 = mp2->b_cont) != NULL); 5226 } 5227 } 5228 /* 5229 * If the size of the packet is greater than the maximum allowed by 5230 * ip, return an error. Passing this down could cause panics because 5231 * the size will have wrapped and be inconsistent with the msg size. 5232 */ 5233 if (ip_len > IP_MAXPACKET) { 5234 BUMP_MIB(&udp_mib, udpOutErrors); 5235 udp_ud_err(q, mp, EMSGSIZE); 5236 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5237 "udp_wput_end: q %p (%S)", q, "IP length exceeded"); 5238 return; 5239 } 5240 ipha->ipha_length = htons((uint16_t)ip_len); 5241 ip_len -= ip_hdr_length; 5242 ip_len = htons((uint16_t)ip_len); 5243 udpha = (udpha_t *)(((uchar_t *)ipha) + ip_hdr_length); 5244 /* 5245 * Copy in the destination address and port from the T_UNITDATA 5246 * request 5247 */ 5248 if (v4dst == INADDR_ANY) 5249 ipha->ipha_dst = htonl(INADDR_LOOPBACK); 5250 else 5251 ipha->ipha_dst = v4dst; 5252 5253 /* 5254 * Set ttl based on IP_MULTICAST_TTL to match IPv6 logic. 5255 */ 5256 if (CLASSD(v4dst)) 5257 ipha->ipha_ttl = udp->udp_multicast_ttl; 5258 5259 udpha->uha_dst_port = port; 5260 udpha->uha_src_port = udp->udp_port; 5261 5262 if (ip_hdr_length > IP_SIMPLE_HDR_LENGTH) { 5263 uint32_t cksum; 5264 5265 bcopy(udp->udp_ip_snd_options, &ipha[1], 5266 udp->udp_ip_snd_options_len); 5267 /* 5268 * Massage source route putting first source route in ipha_dst. 5269 * Ignore the destination in T_unitdata_req. 5270 * Create a checksum adjustment for a source route, if any. 5271 */ 5272 cksum = ip_massage_options(ipha); 5273 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5274 cksum -= ((ipha->ipha_dst >> 16) & 0xFFFF) + 5275 (ipha->ipha_dst & 0xFFFF); 5276 if ((int)cksum < 0) 5277 cksum--; 5278 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5279 /* 5280 * IP does the checksum if uha_checksum is non-zero, 5281 * We make it easy for IP to include our pseudo header 5282 * by putting our length in uha_checksum. 5283 */ 5284 cksum += ip_len; 5285 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5286 /* There might be a carry. */ 5287 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5288 #ifdef _LITTLE_ENDIAN 5289 if (udp_do_checksum) 5290 ip_len = (cksum << 16) | ip_len; 5291 #else 5292 if (udp_do_checksum) 5293 ip_len = (ip_len << 16) | cksum; 5294 else 5295 ip_len <<= 16; 5296 #endif 5297 } else { 5298 /* 5299 * IP does the checksum if uha_checksum is non-zero, 5300 * We make it easy for IP to include our pseudo header 5301 * by putting our length in uha_checksum. 5302 */ 5303 if (udp_do_checksum) 5304 ip_len |= (ip_len << 16); 5305 #ifndef _LITTLE_ENDIAN 5306 else 5307 ip_len <<= 16; 5308 #endif 5309 } 5310 /* Set UDP length and checksum */ 5311 *((uint32_t *)&udpha->uha_length) = ip_len; 5312 5313 freeb(mp); 5314 5315 /* We're done. Pass the packet to ip. */ 5316 BUMP_MIB(&udp_mib, udpOutDatagrams); 5317 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5318 "udp_wput_end: q %p (%S)", q, "end"); 5319 putnext(q, mp1); 5320 #undef tudr 5321 } 5322 5323 /* 5324 * udp_wput_ipv6(): 5325 * Assumes that udp_wput did some sanity checking on the destination 5326 * address. 5327 */ 5328 static void 5329 udp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6, t_scalar_t tudr_optlen) 5330 { 5331 ip6_t *ip6h; 5332 ip6i_t *ip6i; /* mp1->b_rptr even if no ip6i_t */ 5333 mblk_t *mp1; 5334 int udp_ip_hdr_len = IPV6_HDR_LEN + UDPH_SIZE; 5335 size_t ip_len; 5336 udpha_t *udph; 5337 udp_t *udp; 5338 ip6_pkt_t ipp_s; /* For ancillary data options */ 5339 ip6_pkt_t *ipp = &ipp_s; 5340 ip6_pkt_t *tipp; /* temporary ipp */ 5341 uint32_t csum = 0; 5342 uint_t ignore = 0; 5343 uint_t option_exists = 0, is_sticky = 0; 5344 uint8_t *cp; 5345 uint8_t *nxthdr_ptr; 5346 5347 udp = (udp_t *)q->q_ptr; 5348 5349 /* 5350 * If the local address is a mapped address return 5351 * an error. 5352 * It would be possible to send an IPv6 packet but the 5353 * response would never make it back to the application 5354 * since it is bound to a mapped address. 5355 */ 5356 if (IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src)) { 5357 BUMP_MIB(&udp_mib, udpOutErrors); 5358 udp_ud_err(q, mp, EADDRNOTAVAIL); 5359 return; 5360 } 5361 5362 ipp->ipp_fields = 0; 5363 ipp->ipp_sticky_ignored = 0; 5364 5365 /* 5366 * If TPI options passed in, feed it for verification and handling 5367 */ 5368 if (tudr_optlen != 0) { 5369 int error; 5370 5371 if (udp_unitdata_opt_process(q, mp, &error, 5372 (void *)ipp) < 0) { 5373 /* failure */ 5374 BUMP_MIB(&udp_mib, udpOutErrors); 5375 udp_ud_err(q, mp, error); 5376 return; 5377 } 5378 ignore = ipp->ipp_sticky_ignored; 5379 ASSERT(error == 0); 5380 } 5381 5382 if (sin6->sin6_scope_id != 0 && 5383 IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5384 /* 5385 * IPPF_SCOPE_ID is special. It's neither a sticky 5386 * option nor ancillary data. It needs to be 5387 * explicitly set in options_exists. 5388 */ 5389 option_exists |= IPPF_SCOPE_ID; 5390 } 5391 5392 if ((udp->udp_sticky_ipp.ipp_fields == 0) && 5393 (ipp->ipp_fields == 0)) { 5394 /* No sticky options nor ancillary data. */ 5395 goto no_options; 5396 } 5397 5398 /* 5399 * Go through the options figuring out where each is going to 5400 * come from and build two masks. The first mask indicates if 5401 * the option exists at all. The second mask indicates if the 5402 * option is sticky or ancillary. 5403 */ 5404 if (!(ignore & IPPF_HOPOPTS)) { 5405 if (ipp->ipp_fields & IPPF_HOPOPTS) { 5406 option_exists |= IPPF_HOPOPTS; 5407 udp_ip_hdr_len += ipp->ipp_hopoptslen; 5408 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) { 5409 option_exists |= IPPF_HOPOPTS; 5410 is_sticky |= IPPF_HOPOPTS; 5411 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_hopoptslen; 5412 } 5413 } 5414 5415 if (!(ignore & IPPF_RTHDR)) { 5416 if (ipp->ipp_fields & IPPF_RTHDR) { 5417 option_exists |= IPPF_RTHDR; 5418 udp_ip_hdr_len += ipp->ipp_rthdrlen; 5419 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) { 5420 option_exists |= IPPF_RTHDR; 5421 is_sticky |= IPPF_RTHDR; 5422 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rthdrlen; 5423 } 5424 } 5425 5426 if (!(ignore & IPPF_RTDSTOPTS) && (option_exists & IPPF_RTHDR)) { 5427 if (ipp->ipp_fields & IPPF_RTDSTOPTS) { 5428 option_exists |= IPPF_RTDSTOPTS; 5429 udp_ip_hdr_len += ipp->ipp_rtdstoptslen; 5430 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) { 5431 option_exists |= IPPF_RTDSTOPTS; 5432 is_sticky |= IPPF_RTDSTOPTS; 5433 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rtdstoptslen; 5434 } 5435 } 5436 5437 if (!(ignore & IPPF_DSTOPTS)) { 5438 if (ipp->ipp_fields & IPPF_DSTOPTS) { 5439 option_exists |= IPPF_DSTOPTS; 5440 udp_ip_hdr_len += ipp->ipp_dstoptslen; 5441 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) { 5442 option_exists |= IPPF_DSTOPTS; 5443 is_sticky |= IPPF_DSTOPTS; 5444 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_dstoptslen; 5445 } 5446 } 5447 5448 if (!(ignore & IPPF_IFINDEX)) { 5449 if (ipp->ipp_fields & IPPF_IFINDEX) { 5450 option_exists |= IPPF_IFINDEX; 5451 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_IFINDEX) { 5452 option_exists |= IPPF_IFINDEX; 5453 is_sticky |= IPPF_IFINDEX; 5454 } 5455 } 5456 5457 if (!(ignore & IPPF_ADDR)) { 5458 if (ipp->ipp_fields & IPPF_ADDR) { 5459 option_exists |= IPPF_ADDR; 5460 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_ADDR) { 5461 option_exists |= IPPF_ADDR; 5462 is_sticky |= IPPF_ADDR; 5463 } 5464 } 5465 5466 if (!(ignore & IPPF_DONTFRAG)) { 5467 if (ipp->ipp_fields & IPPF_DONTFRAG) { 5468 option_exists |= IPPF_DONTFRAG; 5469 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DONTFRAG) { 5470 option_exists |= IPPF_DONTFRAG; 5471 is_sticky |= IPPF_DONTFRAG; 5472 } 5473 } 5474 5475 if (!(ignore & IPPF_USE_MIN_MTU)) { 5476 if (ipp->ipp_fields & IPPF_USE_MIN_MTU) { 5477 option_exists |= IPPF_USE_MIN_MTU; 5478 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_USE_MIN_MTU) { 5479 option_exists |= IPPF_USE_MIN_MTU; 5480 is_sticky |= IPPF_USE_MIN_MTU; 5481 } 5482 } 5483 5484 if (!(ignore & IPPF_HOPLIMIT) && (ipp->ipp_fields & IPPF_HOPLIMIT)) 5485 option_exists |= IPPF_HOPLIMIT; 5486 /* IPV6_HOPLIMIT can never be sticky */ 5487 ASSERT(!(udp->udp_sticky_ipp.ipp_fields & IPPF_HOPLIMIT)); 5488 5489 if (!(ignore & IPPF_UNICAST_HOPS) && 5490 (udp->udp_sticky_ipp.ipp_fields & IPPF_UNICAST_HOPS)) { 5491 option_exists |= IPPF_UNICAST_HOPS; 5492 is_sticky |= IPPF_UNICAST_HOPS; 5493 } 5494 5495 if (!(ignore & IPPF_MULTICAST_HOPS) && 5496 (udp->udp_sticky_ipp.ipp_fields & IPPF_MULTICAST_HOPS)) { 5497 option_exists |= IPPF_MULTICAST_HOPS; 5498 is_sticky |= IPPF_MULTICAST_HOPS; 5499 } 5500 5501 if (!(ignore & IPPF_TCLASS)) { 5502 if (ipp->ipp_fields & IPPF_TCLASS) { 5503 option_exists |= IPPF_TCLASS; 5504 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_TCLASS) { 5505 option_exists |= IPPF_TCLASS; 5506 is_sticky |= IPPF_TCLASS; 5507 } 5508 } 5509 5510 no_options: 5511 5512 /* 5513 * If any options carried in the ip6i_t were specified, we 5514 * need to account for the ip6i_t in the data we'll be sending 5515 * down. 5516 */ 5517 if (option_exists & IPPF_HAS_IP6I) 5518 udp_ip_hdr_len += sizeof (ip6i_t); 5519 5520 /* check/fix buffer config, setup pointers into it */ 5521 mp1 = mp->b_cont; 5522 ip6h = (ip6_t *)&mp1->b_rptr[-udp_ip_hdr_len]; 5523 if ((mp1->b_datap->db_ref != 1) || 5524 ((unsigned char *)ip6h < mp1->b_datap->db_base) || 5525 !OK_32PTR(ip6h)) { 5526 /* Try to get everything in a single mblk next time */ 5527 if (udp_ip_hdr_len > udp->udp_max_hdr_len) { 5528 udp->udp_max_hdr_len = udp_ip_hdr_len; 5529 (void) mi_set_sth_wroff(RD(q), 5530 udp->udp_max_hdr_len + udp_wroff_extra); 5531 } 5532 mp1 = allocb(udp_ip_hdr_len + udp_wroff_extra, BPRI_LO); 5533 if (!mp1) { 5534 BUMP_MIB(&udp_mib, udpOutErrors); 5535 udp_ud_err(q, mp, ENOMEM); 5536 return; 5537 } 5538 mp1->b_cont = mp->b_cont; 5539 mp->b_cont = mp1; 5540 mp1->b_wptr = mp1->b_datap->db_lim; 5541 ip6h = (ip6_t *)(mp1->b_wptr - udp_ip_hdr_len); 5542 } 5543 mp1->b_rptr = (unsigned char *)ip6h; 5544 ip6i = (ip6i_t *)ip6h; 5545 5546 #define ANCIL_OR_STICKY_PTR(f) ((is_sticky & f) ? &udp->udp_sticky_ipp : ipp) 5547 if (option_exists & IPPF_HAS_IP6I) { 5548 ip6h = (ip6_t *)&ip6i[1]; 5549 ip6i->ip6i_flags = 0; 5550 ip6i->ip6i_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 5551 5552 /* sin6_scope_id takes precendence over IPPF_IFINDEX */ 5553 if (option_exists & IPPF_SCOPE_ID) { 5554 ip6i->ip6i_flags |= IP6I_IFINDEX; 5555 ip6i->ip6i_ifindex = sin6->sin6_scope_id; 5556 } else if (option_exists & IPPF_IFINDEX) { 5557 tipp = ANCIL_OR_STICKY_PTR(IPPF_IFINDEX); 5558 ASSERT(tipp->ipp_ifindex != 0); 5559 ip6i->ip6i_flags |= IP6I_IFINDEX; 5560 ip6i->ip6i_ifindex = tipp->ipp_ifindex; 5561 } 5562 5563 if (option_exists & IPPF_ADDR) { 5564 /* 5565 * Enable per-packet source address verification if 5566 * IPV6_PKTINFO specified the source address. 5567 * ip6_src is set in the transport's _wput function. 5568 */ 5569 ip6i->ip6i_flags |= IP6I_VERIFY_SRC; 5570 } 5571 5572 if (option_exists & IPPF_DONTFRAG) { 5573 ip6i->ip6i_flags |= IP6I_DONTFRAG; 5574 } 5575 5576 if (option_exists & IPPF_USE_MIN_MTU) { 5577 ip6i->ip6i_flags = IP6I_API_USE_MIN_MTU( 5578 ip6i->ip6i_flags, ipp->ipp_use_min_mtu); 5579 } 5580 5581 if (option_exists & IPPF_NEXTHOP) { 5582 tipp = ANCIL_OR_STICKY_PTR(IPPF_NEXTHOP); 5583 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_nexthop)); 5584 ip6i->ip6i_flags |= IP6I_NEXTHOP; 5585 ip6i->ip6i_nexthop = tipp->ipp_nexthop; 5586 } 5587 5588 /* 5589 * tell IP this is an ip6i_t private header 5590 */ 5591 ip6i->ip6i_nxt = IPPROTO_RAW; 5592 } 5593 5594 /* Initialize IPv6 header */ 5595 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 5596 bzero(&ip6h->ip6_src, sizeof (ip6h->ip6_src)); 5597 5598 /* Set the hoplimit of the outgoing packet. */ 5599 if (option_exists & IPPF_HOPLIMIT) { 5600 /* IPV6_HOPLIMIT ancillary data overrides all other settings. */ 5601 ip6h->ip6_hops = ipp->ipp_hoplimit; 5602 ip6i->ip6i_flags |= IP6I_HOPLIMIT; 5603 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 5604 ip6h->ip6_hops = udp->udp_multicast_ttl; 5605 if (option_exists & IPPF_MULTICAST_HOPS) 5606 ip6i->ip6i_flags |= IP6I_HOPLIMIT; 5607 } else { 5608 ip6h->ip6_hops = udp->udp_ttl; 5609 if (option_exists & IPPF_UNICAST_HOPS) 5610 ip6i->ip6i_flags |= IP6I_HOPLIMIT; 5611 } 5612 5613 if (option_exists & IPPF_ADDR) { 5614 tipp = ANCIL_OR_STICKY_PTR(IPPF_ADDR); 5615 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_addr)); 5616 ip6h->ip6_src = tipp->ipp_addr; 5617 } else { 5618 /* 5619 * The source address was not set using IPV6_PKTINFO. 5620 * First look at the bound source. 5621 * If unspecified fallback to __sin6_src_id. 5622 */ 5623 ip6h->ip6_src = udp->udp_v6src; 5624 if (sin6->__sin6_src_id != 0 && 5625 IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) { 5626 ip_srcid_find_id(sin6->__sin6_src_id, 5627 &ip6h->ip6_src, udp->udp_zoneid); 5628 } 5629 } 5630 5631 nxthdr_ptr = (uint8_t *)&ip6h->ip6_nxt; 5632 cp = (uint8_t *)&ip6h[1]; 5633 5634 /* 5635 * Here's where we have to start stringing together 5636 * any extension headers in the right order: 5637 * Hop-by-hop, destination, routing, and final destination opts. 5638 */ 5639 if (option_exists & IPPF_HOPOPTS) { 5640 /* Hop-by-hop options */ 5641 ip6_hbh_t *hbh = (ip6_hbh_t *)cp; 5642 tipp = ANCIL_OR_STICKY_PTR(IPPF_HOPOPTS); 5643 5644 *nxthdr_ptr = IPPROTO_HOPOPTS; 5645 nxthdr_ptr = &hbh->ip6h_nxt; 5646 5647 bcopy(tipp->ipp_hopopts, cp, tipp->ipp_hopoptslen); 5648 cp += tipp->ipp_hopoptslen; 5649 } 5650 /* 5651 * En-route destination options 5652 * Only do them if there's a routing header as well 5653 */ 5654 if (option_exists & IPPF_RTDSTOPTS) { 5655 ip6_dest_t *dst = (ip6_dest_t *)cp; 5656 tipp = ANCIL_OR_STICKY_PTR(IPPF_RTDSTOPTS); 5657 5658 *nxthdr_ptr = IPPROTO_DSTOPTS; 5659 nxthdr_ptr = &dst->ip6d_nxt; 5660 5661 bcopy(tipp->ipp_rtdstopts, cp, tipp->ipp_rtdstoptslen); 5662 cp += tipp->ipp_rtdstoptslen; 5663 } 5664 /* 5665 * Routing header next 5666 */ 5667 if (option_exists & IPPF_RTHDR) { 5668 ip6_rthdr_t *rt = (ip6_rthdr_t *)cp; 5669 tipp = ANCIL_OR_STICKY_PTR(IPPF_RTHDR); 5670 5671 *nxthdr_ptr = IPPROTO_ROUTING; 5672 nxthdr_ptr = &rt->ip6r_nxt; 5673 5674 bcopy(tipp->ipp_rthdr, cp, tipp->ipp_rthdrlen); 5675 cp += tipp->ipp_rthdrlen; 5676 } 5677 /* 5678 * Do ultimate destination options 5679 */ 5680 if (option_exists & IPPF_DSTOPTS) { 5681 ip6_dest_t *dest = (ip6_dest_t *)cp; 5682 tipp = ANCIL_OR_STICKY_PTR(IPPF_DSTOPTS); 5683 5684 *nxthdr_ptr = IPPROTO_DSTOPTS; 5685 nxthdr_ptr = &dest->ip6d_nxt; 5686 5687 bcopy(tipp->ipp_dstopts, cp, tipp->ipp_dstoptslen); 5688 cp += tipp->ipp_dstoptslen; 5689 } 5690 /* 5691 * Now set the last header pointer to the proto passed in 5692 */ 5693 ASSERT((int)(cp - (uint8_t *)ip6i) == (udp_ip_hdr_len - UDPH_SIZE)); 5694 *nxthdr_ptr = IPPROTO_UDP; 5695 5696 /* Update UDP header */ 5697 udph = (udpha_t *)((uchar_t *)ip6i + udp_ip_hdr_len - UDPH_SIZE); 5698 udph->uha_dst_port = sin6->sin6_port; 5699 udph->uha_src_port = udp->udp_port; 5700 5701 /* 5702 * Copy in the destination address 5703 */ 5704 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 5705 ip6h->ip6_dst = ipv6_loopback; 5706 else 5707 ip6h->ip6_dst = sin6->sin6_addr; 5708 5709 ip6h->ip6_vcf = 5710 (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) | 5711 (sin6->sin6_flowinfo & ~IPV6_VERS_AND_FLOW_MASK); 5712 5713 if (option_exists & IPPF_TCLASS) { 5714 tipp = ANCIL_OR_STICKY_PTR(IPPF_TCLASS); 5715 ip6h->ip6_vcf = IPV6_TCLASS_FLOW(ip6h->ip6_vcf, 5716 tipp->ipp_tclass); 5717 } 5718 5719 if (option_exists & IPPF_RTHDR) { 5720 ip6_rthdr_t *rth; 5721 5722 /* 5723 * Perform any processing needed for source routing. 5724 * We know that all extension headers will be in the same mblk 5725 * as the IPv6 header. 5726 */ 5727 rth = ip_find_rthdr_v6(ip6h, mp1->b_wptr); 5728 if (rth != NULL && rth->ip6r_segleft != 0) { 5729 if (rth->ip6r_type != IPV6_RTHDR_TYPE_0) { 5730 /* 5731 * Drop packet - only support Type 0 routing. 5732 * Notify the application as well. 5733 */ 5734 udp_ud_err(q, mp, EPROTO); 5735 BUMP_MIB(&udp_mib, udpOutErrors); 5736 return; 5737 } 5738 5739 /* 5740 * rth->ip6r_len is twice the number of 5741 * addresses in the header. Thus it must be even. 5742 */ 5743 if (rth->ip6r_len & 0x1) { 5744 udp_ud_err(q, mp, EPROTO); 5745 BUMP_MIB(&udp_mib, udpOutErrors); 5746 return; 5747 } 5748 /* 5749 * Shuffle the routing header and ip6_dst 5750 * addresses, and get the checksum difference 5751 * between the first hop (in ip6_dst) and 5752 * the destination (in the last routing hdr entry). 5753 */ 5754 csum = ip_massage_options_v6(ip6h, rth); 5755 /* 5756 * Verify that the first hop isn't a mapped address. 5757 * Routers along the path need to do this verification 5758 * for subsequent hops. 5759 */ 5760 if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst)) { 5761 udp_ud_err(q, mp, EADDRNOTAVAIL); 5762 BUMP_MIB(&udp_mib, udpOutErrors); 5763 return; 5764 } 5765 5766 cp += (rth->ip6r_len + 1)*8; 5767 } 5768 } 5769 5770 /* count up length of UDP packet */ 5771 ip_len = (mp1->b_wptr - (unsigned char *)ip6h) - IPV6_HDR_LEN; 5772 { 5773 mblk_t *mp2; 5774 5775 if ((mp2 = mp1->b_cont) != NULL) { 5776 do { 5777 ip_len += mp2->b_wptr - mp2->b_rptr; 5778 } while ((mp2 = mp2->b_cont) != NULL); 5779 } 5780 } 5781 5782 /* 5783 * If the size of the packet is greater than the maximum allowed by 5784 * ip, return an error. Passing this down could cause panics because 5785 * the size will have wrapped and be inconsistent with the msg size. 5786 */ 5787 if (ip_len > IP_MAXPACKET) { 5788 BUMP_MIB(&udp_mib, udpOutErrors); 5789 udp_ud_err(q, mp, EMSGSIZE); 5790 return; 5791 } 5792 5793 /* Store the UDP length. Subtract length of extension hdrs */ 5794 udph->uha_length = htons(ip_len + IPV6_HDR_LEN - 5795 (int)((uchar_t *)udph - (uchar_t *)ip6h)); 5796 5797 /* 5798 * We make it easy for IP to include our pseudo header 5799 * by putting our length in uh_checksum, modified (if 5800 * we have a routing header) by the checksum difference 5801 * between the ultimate destination and first hop addresses. 5802 * Note: UDP over IPv6 must always checksum the packet. 5803 */ 5804 csum += udph->uha_length; 5805 csum = (csum & 0xFFFF) + (csum >> 16); 5806 udph->uha_checksum = (uint16_t)csum; 5807 5808 #ifdef _LITTLE_ENDIAN 5809 ip_len = htons(ip_len); 5810 #endif 5811 ip6h->ip6_plen = ip_len; 5812 5813 freeb(mp); 5814 5815 /* We're done. Pass the packet to IP */ 5816 BUMP_MIB(&udp_mib, udpOutDatagrams); 5817 putnext(q, mp1); 5818 } 5819 5820 static void 5821 udp_wput_other(queue_t *q, mblk_t *mp) 5822 { 5823 uchar_t *rptr = mp->b_rptr; 5824 struct datab *db; 5825 struct iocblk *iocp; 5826 udp_t *udp; 5827 cred_t *cr; 5828 5829 TRACE_1(TR_FAC_UDP, TR_UDP_WPUT_OTHER_START, 5830 "udp_wput_other_start: q %p", q); 5831 5832 udp = (udp_t *)q->q_ptr; 5833 db = mp->b_datap; 5834 5835 cr = DB_CREDDEF(mp, udp->udp_credp); 5836 5837 switch (db->db_type) { 5838 case M_DATA: 5839 /* Not connected */ 5840 BUMP_MIB(&udp_mib, udpOutErrors); 5841 freemsg(mp); 5842 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5843 "udp_wput_other_end: q %p (%S)", 5844 q, "not-connected"); 5845 return; 5846 case M_PROTO: 5847 case M_PCPROTO: 5848 if (mp->b_wptr - rptr < sizeof (t_scalar_t)) { 5849 freemsg(mp); 5850 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5851 "udp_wput_other_end: q %p (%S)", 5852 q, "protoshort"); 5853 return; 5854 } 5855 switch (((union T_primitives *)rptr)->type) { 5856 case T_ADDR_REQ: 5857 udp_addr_req(q, mp); 5858 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5859 "udp_wput_other_end: q %p (%S)", q, "addrreq"); 5860 return; 5861 case O_T_BIND_REQ: 5862 case T_BIND_REQ: 5863 udp_bind(q, mp); 5864 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5865 "udp_wput_other_end: q %p (%S)", q, "bindreq"); 5866 return; 5867 case T_CONN_REQ: 5868 udp_connect(q, mp); 5869 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5870 "udp_wput_other_end: q %p (%S)", q, "connreq"); 5871 return; 5872 case T_CAPABILITY_REQ: 5873 udp_capability_req(q, mp); 5874 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5875 "udp_wput_other_end: q %p (%S)", q, "capabreq"); 5876 return; 5877 case T_INFO_REQ: 5878 udp_info_req(q, mp); 5879 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5880 "udp_wput_other_end: q %p (%S)", q, "inforeq"); 5881 return; 5882 case T_UNITDATA_REQ: 5883 /* 5884 * If a T_UNITDATA_REQ gets here, the address must 5885 * be bad. Valid T_UNITDATA_REQs are handled 5886 * in udp_wput. 5887 */ 5888 udp_ud_err(q, mp, EADDRNOTAVAIL); 5889 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5890 "udp_wput_other_end: q %p (%S)", 5891 q, "unitdatareq"); 5892 return; 5893 case T_UNBIND_REQ: 5894 udp_unbind(q, mp); 5895 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5896 "udp_wput_other_end: q %p (%S)", q, "unbindreq"); 5897 return; 5898 case T_SVR4_OPTMGMT_REQ: 5899 if (!snmpcom_req(q, mp, udp_snmp_set, udp_snmp_get, cr)) 5900 (void) svr4_optcom_req(q, mp, cr, &udp_opt_obj); 5901 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5902 "udp_wput_other_end: q %p (%S)", 5903 q, "optmgmtreq"); 5904 return; 5905 5906 case T_OPTMGMT_REQ: 5907 (void) tpi_optcom_req(q, mp, cr, &udp_opt_obj); 5908 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5909 "udp_wput_other_end: q %p (%S)", 5910 q, "optmgmtreq"); 5911 return; 5912 5913 case T_DISCON_REQ: 5914 udp_disconnect(q, mp); 5915 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5916 "udp_wput_other_end: q %p (%S)", 5917 q, "disconreq"); 5918 return; 5919 5920 /* The following TPI message is not supported by udp. */ 5921 case O_T_CONN_RES: 5922 case T_CONN_RES: 5923 udp_err_ack(q, mp, TNOTSUPPORT, 0); 5924 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5925 "udp_wput_other_end: q %p (%S)", 5926 q, "connres/disconreq"); 5927 return; 5928 5929 /* The following 3 TPI messages are illegal for udp. */ 5930 case T_DATA_REQ: 5931 case T_EXDATA_REQ: 5932 case T_ORDREL_REQ: 5933 udp_err_ack(q, mp, TNOTSUPPORT, 0); 5934 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5935 "udp_wput_other_end: q %p (%S)", 5936 q, "data/exdata/ordrel"); 5937 return; 5938 default: 5939 break; 5940 } 5941 break; 5942 case M_FLUSH: 5943 if (*rptr & FLUSHW) 5944 flushq(q, FLUSHDATA); 5945 break; 5946 case M_IOCTL: 5947 iocp = (struct iocblk *)mp->b_rptr; 5948 switch (iocp->ioc_cmd) { 5949 case TI_GETPEERNAME: 5950 if (udp->udp_state != TS_DATA_XFER) { 5951 /* 5952 * If a default destination address has not 5953 * been associated with the stream, then we 5954 * don't know the peer's name. 5955 */ 5956 iocp->ioc_error = ENOTCONN; 5957 err_ret:; 5958 iocp->ioc_count = 0; 5959 mp->b_datap->db_type = M_IOCACK; 5960 qreply(q, mp); 5961 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5962 "udp_wput_other_end: q %p (%S)", 5963 q, "getpeername"); 5964 return; 5965 } 5966 /* FALLTHRU */ 5967 case TI_GETMYNAME: { 5968 /* 5969 * For TI_GETPEERNAME and TI_GETMYNAME, we first 5970 * need to copyin the user's strbuf structure. 5971 * Processing will continue in the M_IOCDATA case 5972 * below. 5973 */ 5974 mi_copyin(q, mp, NULL, 5975 SIZEOF_STRUCT(strbuf, iocp->ioc_flag)); 5976 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5977 "udp_wput_other_end: q %p (%S)", 5978 q, "getmyname"); 5979 return; 5980 } 5981 case ND_SET: 5982 /* nd_getset performs the necessary checking */ 5983 case ND_GET: 5984 if (nd_getset(q, udp_g_nd, mp)) { 5985 qreply(q, mp); 5986 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5987 "udp_wput_other_end: q %p (%S)", 5988 q, "get"); 5989 return; 5990 } 5991 break; 5992 default: 5993 break; 5994 } 5995 break; 5996 case M_IOCDATA: 5997 udp_wput_iocdata(q, mp); 5998 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5999 "udp_wput_other_end: q %p (%S)", q, "iocdata"); 6000 return; 6001 default: 6002 /* Unrecognized messages are passed through without change. */ 6003 break; 6004 } 6005 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 6006 "udp_wput_other_end: q %p (%S)", q, "end"); 6007 putnext(q, mp); 6008 } 6009 6010 /* 6011 * udp_wput_iocdata is called by udp_wput_other to handle all M_IOCDATA 6012 * messages. 6013 */ 6014 static void 6015 udp_wput_iocdata(queue_t *q, mblk_t *mp) 6016 { 6017 mblk_t *mp1; 6018 STRUCT_HANDLE(strbuf, sb); 6019 uint16_t port; 6020 udp_t *udp; 6021 in6_addr_t v6addr; 6022 ipaddr_t v4addr; 6023 uint32_t flowinfo = 0; 6024 int addrlen; 6025 6026 /* Make sure it is one of ours. */ 6027 switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { 6028 case TI_GETMYNAME: 6029 case TI_GETPEERNAME: 6030 break; 6031 default: 6032 putnext(q, mp); 6033 return; 6034 } 6035 switch (mi_copy_state(q, mp, &mp1)) { 6036 case -1: 6037 return; 6038 case MI_COPY_CASE(MI_COPY_IN, 1): 6039 break; 6040 case MI_COPY_CASE(MI_COPY_OUT, 1): 6041 /* 6042 * The address has been copied out, so now 6043 * copyout the strbuf. 6044 */ 6045 mi_copyout(q, mp); 6046 return; 6047 case MI_COPY_CASE(MI_COPY_OUT, 2): 6048 /* 6049 * The address and strbuf have been copied out. 6050 * We're done, so just acknowledge the original 6051 * M_IOCTL. 6052 */ 6053 mi_copy_done(q, mp, 0); 6054 return; 6055 default: 6056 /* 6057 * Something strange has happened, so acknowledge 6058 * the original M_IOCTL with an EPROTO error. 6059 */ 6060 mi_copy_done(q, mp, EPROTO); 6061 return; 6062 } 6063 6064 /* 6065 * Now we have the strbuf structure for TI_GETMYNAME 6066 * and TI_GETPEERNAME. Next we copyout the requested 6067 * address and then we'll copyout the strbuf. 6068 */ 6069 STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag, 6070 (void *)mp1->b_rptr); 6071 udp = (udp_t *)q->q_ptr; 6072 if (udp->udp_family == AF_INET) 6073 addrlen = sizeof (sin_t); 6074 else 6075 addrlen = sizeof (sin6_t); 6076 6077 if (STRUCT_FGET(sb, maxlen) < addrlen) { 6078 mi_copy_done(q, mp, EINVAL); 6079 return; 6080 } 6081 switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { 6082 case TI_GETMYNAME: 6083 if (udp->udp_family == AF_INET) { 6084 ASSERT(udp->udp_ipversion == IPV4_VERSION); 6085 if (!IN6_IS_ADDR_V4MAPPED_ANY(&udp->udp_v6src) && 6086 !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 6087 v4addr = V4_PART_OF_V6(udp->udp_v6src); 6088 } else { 6089 /* 6090 * INADDR_ANY 6091 * udp_v6src is not set, we might be bound to 6092 * broadcast/multicast. Use udp_bound_v6src as 6093 * local address instead (that could 6094 * also still be INADDR_ANY) 6095 */ 6096 v4addr = V4_PART_OF_V6(udp->udp_bound_v6src); 6097 } 6098 } else { 6099 /* udp->udp_family == AF_INET6 */ 6100 if (!IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 6101 v6addr = udp->udp_v6src; 6102 } else { 6103 /* 6104 * UNSPECIFIED 6105 * udp_v6src is not set, we might be bound to 6106 * broadcast/multicast. Use udp_bound_v6src as 6107 * local address instead (that could 6108 * also still be UNSPECIFIED) 6109 */ 6110 v6addr = udp->udp_bound_v6src; 6111 } 6112 } 6113 port = udp->udp_port; 6114 break; 6115 case TI_GETPEERNAME: 6116 if (udp->udp_family == AF_INET) { 6117 ASSERT(udp->udp_ipversion == IPV4_VERSION); 6118 v4addr = V4_PART_OF_V6(udp->udp_v6dst); 6119 } else { 6120 /* udp->udp_family == AF_INET6) */ 6121 v6addr = udp->udp_v6dst; 6122 flowinfo = udp->udp_flowinfo; 6123 } 6124 port = udp->udp_dstport; 6125 break; 6126 default: 6127 mi_copy_done(q, mp, EPROTO); 6128 return; 6129 } 6130 mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE); 6131 if (!mp1) 6132 return; 6133 6134 if (udp->udp_family == AF_INET) { 6135 sin_t *sin; 6136 6137 STRUCT_FSET(sb, len, (int)sizeof (sin_t)); 6138 sin = (sin_t *)mp1->b_rptr; 6139 mp1->b_wptr = (uchar_t *)&sin[1]; 6140 *sin = sin_null; 6141 sin->sin_family = AF_INET; 6142 sin->sin_addr.s_addr = v4addr; 6143 sin->sin_port = port; 6144 } else { 6145 /* udp->udp_family == AF_INET6 */ 6146 sin6_t *sin6; 6147 6148 STRUCT_FSET(sb, len, (int)sizeof (sin6_t)); 6149 sin6 = (sin6_t *)mp1->b_rptr; 6150 mp1->b_wptr = (uchar_t *)&sin6[1]; 6151 *sin6 = sin6_null; 6152 sin6->sin6_family = AF_INET6; 6153 sin6->sin6_flowinfo = flowinfo; 6154 sin6->sin6_addr = v6addr; 6155 sin6->sin6_port = port; 6156 } 6157 /* Copy out the address */ 6158 mi_copyout(q, mp); 6159 } 6160 6161 6162 static int 6163 udp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp, 6164 void *thisdg_attrs) 6165 { 6166 udp_t *udp; 6167 struct T_unitdata_req *udreqp; 6168 int is_absreq_failure; 6169 cred_t *cr; 6170 6171 ASSERT(((union T_primitives *)mp->b_rptr)->type); 6172 6173 udp = (udp_t *)q->q_ptr; 6174 6175 cr = DB_CREDDEF(mp, udp->udp_credp); 6176 6177 udreqp = (struct T_unitdata_req *)mp->b_rptr; 6178 *errorp = 0; 6179 6180 *errorp = tpi_optcom_buf(q, mp, &udreqp->OPT_length, 6181 udreqp->OPT_offset, cr, &udp_opt_obj, 6182 thisdg_attrs, &is_absreq_failure); 6183 6184 if (*errorp != 0) { 6185 /* 6186 * Note: No special action needed in this 6187 * module for "is_absreq_failure" 6188 */ 6189 return (-1); /* failure */ 6190 } 6191 ASSERT(is_absreq_failure == 0); 6192 return (0); /* success */ 6193 } 6194 6195 void 6196 udp_ddi_init(void) 6197 { 6198 int i; 6199 6200 UDP6_MAJ = ddi_name_to_major(UDP6); 6201 mutex_init(&udp_g_lock, NULL, MUTEX_DEFAULT, NULL); 6202 6203 udp_max_optsize = optcom_max_optsize(udp_opt_obj.odb_opt_des_arr, 6204 udp_opt_obj.odb_opt_arr_cnt); 6205 6206 if (udp_bind_fanout_size & (udp_bind_fanout_size - 1)) { 6207 /* Not a power of two. Round up to nearest power of two */ 6208 for (i = 0; i < 31; i++) { 6209 if (udp_bind_fanout_size < (1 << i)) 6210 break; 6211 } 6212 udp_bind_fanout_size = 1 << i; 6213 } 6214 udp_bind_fanout = kmem_zalloc(udp_bind_fanout_size * 6215 sizeof (udp_fanout_t), KM_SLEEP); 6216 for (i = 0; i < udp_bind_fanout_size; i++) { 6217 mutex_init(&udp_bind_fanout[i].uf_lock, NULL, MUTEX_DEFAULT, 6218 NULL); 6219 } 6220 (void) udp_param_register(udp_param_arr, A_CNT(udp_param_arr)); 6221 udp_kstat_init(); 6222 } 6223 6224 void 6225 udp_ddi_destroy(void) 6226 { 6227 int i; 6228 6229 nd_free(&udp_g_nd); 6230 6231 mutex_destroy(&udp_g_lock); 6232 for (i = 0; i < udp_bind_fanout_size; i++) { 6233 mutex_destroy(&udp_bind_fanout[i].uf_lock); 6234 } 6235 kmem_free(udp_bind_fanout, udp_bind_fanout_size * 6236 sizeof (udp_fanout_t)); 6237 udp_kstat_fini(); 6238 6239 } 6240 6241 static void 6242 udp_kstat_init(void) 6243 { 6244 udp_named_kstat_t template = { 6245 { "inDatagrams", KSTAT_DATA_UINT32, 0 }, 6246 { "inErrors", KSTAT_DATA_UINT32, 0 }, 6247 { "outDatagrams", KSTAT_DATA_UINT32, 0 }, 6248 { "entrySize", KSTAT_DATA_INT32, 0 }, 6249 { "entry6Size", KSTAT_DATA_INT32, 0 }, 6250 { "outErrors", KSTAT_DATA_UINT32, 0 }, 6251 }; 6252 6253 udp_mibkp = kstat_create("udp", 0, "udp", "mib2", KSTAT_TYPE_NAMED, 6254 NUM_OF_FIELDS(udp_named_kstat_t), 6255 0); 6256 if (udp_mibkp == NULL) 6257 return; 6258 6259 template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t); 6260 template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t); 6261 6262 bcopy(&template, udp_mibkp->ks_data, sizeof (template)); 6263 6264 udp_mibkp->ks_update = udp_kstat_update; 6265 6266 kstat_install(udp_mibkp); 6267 } 6268 6269 static void 6270 udp_kstat_fini(void) 6271 { 6272 if (udp_mibkp) { 6273 kstat_delete(udp_mibkp); 6274 udp_mibkp = NULL; 6275 } 6276 } 6277 6278 static int 6279 udp_kstat_update(kstat_t *kp, int rw) 6280 { 6281 udp_named_kstat_t *udpkp; 6282 6283 if ((kp == NULL) || (kp->ks_data == NULL)) 6284 return (EIO); 6285 6286 if (rw == KSTAT_WRITE) 6287 return (EACCES); 6288 6289 udpkp = (udp_named_kstat_t *)kp->ks_data; 6290 6291 udpkp->inDatagrams.value.ui32 = udp_mib.udpInDatagrams; 6292 udpkp->inErrors.value.ui32 = udp_mib.udpInErrors; 6293 udpkp->outDatagrams.value.ui32 = udp_mib.udpOutDatagrams; 6294 udpkp->outErrors.value.ui32 = udp_mib.udpOutErrors; 6295 6296 return (0); 6297 } 6298 6299 /* 6300 * Little helper for IPsec's NAT-T processing. 6301 */ 6302 boolean_t 6303 udp_compute_checksum(void) 6304 { 6305 return (udp_do_checksum); 6306 } 6307