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_HOPLIMIT: 2459 if (ipp->ipp_fields & IPPF_HOPLIMIT) 2460 *i1 = ipp->ipp_hoplimit; 2461 else 2462 *i1 = -1; /* Not set */ 2463 break; /* goto sizeof (int) option return */ 2464 case IPV6_TCLASS: 2465 if (ipp->ipp_fields & IPPF_TCLASS) 2466 *i1 = ipp->ipp_tclass; 2467 else 2468 *i1 = IPV6_FLOW_TCLASS( 2469 IPV6_DEFAULT_VERS_AND_FLOW); 2470 break; /* goto sizeof (int) option return */ 2471 case IPV6_NEXTHOP: { 2472 sin6_t *sin6 = (sin6_t *)ptr; 2473 2474 if (!(ipp->ipp_fields & IPPF_NEXTHOP)) 2475 return (0); 2476 *sin6 = sin6_null; 2477 sin6->sin6_family = AF_INET6; 2478 sin6->sin6_addr = ipp->ipp_nexthop; 2479 return (sizeof (sin6_t)); 2480 } 2481 case IPV6_HOPOPTS: 2482 if (!(ipp->ipp_fields & IPPF_HOPOPTS)) 2483 return (0); 2484 bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen); 2485 return (ipp->ipp_hopoptslen); 2486 case IPV6_RTHDRDSTOPTS: 2487 if (!(ipp->ipp_fields & IPPF_RTDSTOPTS)) 2488 return (0); 2489 bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen); 2490 return (ipp->ipp_rtdstoptslen); 2491 case IPV6_RTHDR: 2492 if (!(ipp->ipp_fields & IPPF_RTHDR)) 2493 return (0); 2494 bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen); 2495 return (ipp->ipp_rthdrlen); 2496 case IPV6_DSTOPTS: 2497 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) 2498 return (0); 2499 bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen); 2500 return (ipp->ipp_dstoptslen); 2501 case IPV6_PATHMTU: 2502 return (ip_fill_mtuinfo(&udp->udp_v6dst, 2503 udp->udp_dstport, (struct ip6_mtuinfo *)ptr)); 2504 default: 2505 return (-1); 2506 } 2507 break; 2508 case IPPROTO_UDP: 2509 switch (name) { 2510 case UDP_ANONPRIVBIND: 2511 *i1 = udp->udp_anon_priv_bind; 2512 break; 2513 case UDP_EXCLBIND: 2514 *i1 = udp->udp_exclbind ? UDP_EXCLBIND : 0; 2515 break; 2516 case UDP_RCVHDR: 2517 *i1 = udp->udp_rcvhdr ? 1 : 0; 2518 break; 2519 default: 2520 return (-1); 2521 } 2522 break; 2523 default: 2524 return (-1); 2525 } 2526 return (sizeof (int)); 2527 } 2528 2529 /* This routine sets socket options. */ 2530 /* ARGSUSED */ 2531 int 2532 udp_opt_set(queue_t *q, uint_t optset_context, int level, 2533 int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 2534 uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk) 2535 { 2536 udp_t *udp = (udp_t *)q->q_ptr; 2537 int *i1 = (int *)invalp; 2538 boolean_t onoff = (*i1 == 0) ? 0 : 1; 2539 boolean_t checkonly; 2540 int error; 2541 2542 switch (optset_context) { 2543 case SETFN_OPTCOM_CHECKONLY: 2544 checkonly = B_TRUE; 2545 /* 2546 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ 2547 * inlen != 0 implies value supplied and 2548 * we have to "pretend" to set it. 2549 * inlen == 0 implies that there is no 2550 * value part in T_CHECK request and just validation 2551 * done elsewhere should be enough, we just return here. 2552 */ 2553 if (inlen == 0) { 2554 *outlenp = 0; 2555 return (0); 2556 } 2557 break; 2558 case SETFN_OPTCOM_NEGOTIATE: 2559 checkonly = B_FALSE; 2560 break; 2561 case SETFN_UD_NEGOTIATE: 2562 case SETFN_CONN_NEGOTIATE: 2563 checkonly = B_FALSE; 2564 /* 2565 * Negotiating local and "association-related" options 2566 * through T_UNITDATA_REQ. 2567 * 2568 * Following routine can filter out ones we do not 2569 * want to be "set" this way. 2570 */ 2571 if (!udp_opt_allow_udr_set(level, name)) { 2572 *outlenp = 0; 2573 return (EINVAL); 2574 } 2575 break; 2576 default: 2577 /* 2578 * We should never get here 2579 */ 2580 *outlenp = 0; 2581 return (EINVAL); 2582 } 2583 2584 ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) || 2585 (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0)); 2586 2587 /* 2588 * For fixed length options, no sanity check 2589 * of passed in length is done. It is assumed *_optcom_req() 2590 * routines do the right thing. 2591 */ 2592 2593 switch (level) { 2594 case SOL_SOCKET: 2595 switch (name) { 2596 case SO_REUSEADDR: 2597 if (!checkonly) 2598 udp->udp_reuseaddr = onoff; 2599 break; 2600 case SO_DEBUG: 2601 if (!checkonly) 2602 udp->udp_debug = onoff; 2603 break; 2604 /* 2605 * The following three items are available here, 2606 * but are only meaningful to IP. 2607 */ 2608 case SO_DONTROUTE: 2609 if (!checkonly) 2610 udp->udp_dontroute = onoff; 2611 break; 2612 case SO_USELOOPBACK: 2613 if (!checkonly) 2614 udp->udp_useloopback = onoff; 2615 break; 2616 case SO_BROADCAST: 2617 if (!checkonly) 2618 udp->udp_broadcast = onoff; 2619 break; 2620 2621 case SO_SNDBUF: 2622 if (*i1 > udp_max_buf) { 2623 *outlenp = 0; 2624 return (ENOBUFS); 2625 } 2626 if (!checkonly) { 2627 q->q_hiwat = *i1; 2628 q->q_next->q_hiwat = *i1; 2629 } 2630 break; 2631 case SO_RCVBUF: 2632 if (*i1 > udp_max_buf) { 2633 *outlenp = 0; 2634 return (ENOBUFS); 2635 } 2636 if (!checkonly) { 2637 RD(q)->q_hiwat = *i1; 2638 (void) mi_set_sth_hiwat(RD(q), *i1); 2639 } 2640 break; 2641 case SO_DGRAM_ERRIND: 2642 if (!checkonly) 2643 udp->udp_dgram_errind = onoff; 2644 break; 2645 case SO_RECVUCRED: 2646 if (!checkonly) 2647 udp->udp_recvucred = onoff; 2648 break; 2649 default: 2650 *outlenp = 0; 2651 return (EINVAL); 2652 } 2653 break; 2654 case IPPROTO_IP: 2655 if (udp->udp_family != AF_INET) { 2656 *outlenp = 0; 2657 return (ENOPROTOOPT); 2658 } 2659 switch (name) { 2660 case IP_OPTIONS: 2661 case T_IP_OPTIONS: 2662 /* Save options for use by IP. */ 2663 if (inlen & 0x3) { 2664 *outlenp = 0; 2665 return (EINVAL); 2666 } 2667 if (checkonly) 2668 break; 2669 2670 if (udp->udp_ip_snd_options) { 2671 mi_free((char *)udp->udp_ip_snd_options); 2672 udp->udp_ip_snd_options_len = 0; 2673 udp->udp_ip_snd_options = NULL; 2674 } 2675 if (inlen) { 2676 udp->udp_ip_snd_options = 2677 (uchar_t *)mi_alloc(inlen, BPRI_HI); 2678 if (udp->udp_ip_snd_options) { 2679 bcopy(invalp, udp->udp_ip_snd_options, 2680 inlen); 2681 udp->udp_ip_snd_options_len = inlen; 2682 } 2683 } 2684 udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + 2685 UDPH_SIZE + udp->udp_ip_snd_options_len; 2686 (void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len + 2687 udp_wroff_extra); 2688 break; 2689 case IP_TTL: 2690 if (!checkonly) { 2691 udp->udp_ttl = (uchar_t)*i1; 2692 } 2693 break; 2694 case IP_TOS: 2695 case T_IP_TOS: 2696 if (!checkonly) { 2697 udp->udp_type_of_service = (uchar_t)*i1; 2698 } 2699 break; 2700 case IP_MULTICAST_IF: { 2701 /* 2702 * TODO should check OPTMGMT reply and undo this if 2703 * there is an error. 2704 */ 2705 struct in_addr *inap = (struct in_addr *)invalp; 2706 if (!checkonly) { 2707 udp->udp_multicast_if_addr = 2708 inap->s_addr; 2709 } 2710 break; 2711 } 2712 case IP_MULTICAST_TTL: 2713 if (!checkonly) 2714 udp->udp_multicast_ttl = *invalp; 2715 break; 2716 case IP_MULTICAST_LOOP: 2717 if (!checkonly) 2718 udp->udp_multicast_loop = *invalp; 2719 break; 2720 case IP_RECVOPTS: 2721 if (!checkonly) 2722 udp->udp_recvopts = onoff; 2723 break; 2724 case IP_RECVDSTADDR: 2725 if (!checkonly) 2726 udp->udp_recvdstaddr = onoff; 2727 break; 2728 case IP_RECVIF: 2729 if (!checkonly) 2730 udp->udp_recvif = onoff; 2731 break; 2732 case IP_RECVSLLA: 2733 if (!checkonly) 2734 udp->udp_recvslla = onoff; 2735 break; 2736 case IP_RECVTTL: 2737 if (!checkonly) 2738 udp->udp_recvttl = onoff; 2739 break; 2740 case IP_ADD_MEMBERSHIP: 2741 case IP_DROP_MEMBERSHIP: 2742 case IP_BLOCK_SOURCE: 2743 case IP_UNBLOCK_SOURCE: 2744 case IP_ADD_SOURCE_MEMBERSHIP: 2745 case IP_DROP_SOURCE_MEMBERSHIP: 2746 case MCAST_JOIN_GROUP: 2747 case MCAST_LEAVE_GROUP: 2748 case MCAST_BLOCK_SOURCE: 2749 case MCAST_UNBLOCK_SOURCE: 2750 case MCAST_JOIN_SOURCE_GROUP: 2751 case MCAST_LEAVE_SOURCE_GROUP: 2752 case IP_SEC_OPT: 2753 /* 2754 * "soft" error (negative) 2755 * option not handled at this level 2756 * Do not modify *outlenp. 2757 */ 2758 return (-EINVAL); 2759 case IP_BOUND_IF: 2760 if (!checkonly) 2761 udp->udp_bound_if = *i1; 2762 break; 2763 case IP_UNSPEC_SRC: 2764 if (!checkonly) 2765 udp->udp_unspec_source = onoff; 2766 break; 2767 case IP_XMIT_IF: 2768 if (!checkonly) 2769 udp->udp_xmit_if = *i1; 2770 break; 2771 default: 2772 *outlenp = 0; 2773 return (EINVAL); 2774 } 2775 break; 2776 case IPPROTO_IPV6: { 2777 ip6_pkt_t *ipp; 2778 boolean_t sticky; 2779 2780 if (udp->udp_family != AF_INET6) { 2781 *outlenp = 0; 2782 return (ENOPROTOOPT); 2783 } 2784 /* 2785 * Deal with both sticky options and ancillary data 2786 */ 2787 if (thisdg_attrs == NULL) { 2788 /* sticky options, or none */ 2789 ipp = &udp->udp_sticky_ipp; 2790 sticky = B_TRUE; 2791 } else { 2792 /* ancillary data */ 2793 ipp = (ip6_pkt_t *)thisdg_attrs; 2794 sticky = B_FALSE; 2795 } 2796 2797 switch (name) { 2798 case IPV6_MULTICAST_IF: 2799 if (!checkonly) 2800 udp->udp_multicast_if_index = *i1; 2801 break; 2802 case IPV6_UNICAST_HOPS: 2803 /* -1 means use default */ 2804 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 2805 *outlenp = 0; 2806 return (EINVAL); 2807 } 2808 if (!checkonly) { 2809 if (*i1 == -1) { 2810 udp->udp_ttl = ipp->ipp_hoplimit = 2811 udp_ipv6_hoplimit; 2812 ipp->ipp_fields &= ~IPPF_HOPLIMIT; 2813 /* Pass modified value to IP. */ 2814 *i1 = udp->udp_ttl; 2815 } else { 2816 udp->udp_ttl = ipp->ipp_hoplimit = 2817 (uint8_t)*i1; 2818 ipp->ipp_fields |= IPPF_HOPLIMIT; 2819 } 2820 /* Rebuild the header template */ 2821 error = udp_build_hdrs(q, udp); 2822 if (error != 0) { 2823 *outlenp = 0; 2824 return (error); 2825 } 2826 } 2827 break; 2828 case IPV6_MULTICAST_HOPS: 2829 /* -1 means use default */ 2830 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 2831 *outlenp = 0; 2832 return (EINVAL); 2833 } 2834 if (!checkonly) { 2835 if (*i1 == -1) { 2836 udp->udp_multicast_ttl = 2837 ipp->ipp_multi_hoplimit = 2838 IP_DEFAULT_MULTICAST_TTL; 2839 ipp->ipp_fields &= ~IPPF_MULTI_HOPLIMIT; 2840 /* Pass modified value to IP. */ 2841 *i1 = udp->udp_multicast_ttl; 2842 } else { 2843 udp->udp_multicast_ttl = 2844 ipp->ipp_multi_hoplimit = 2845 (uint8_t)*i1; 2846 ipp->ipp_fields |= IPPF_MULTI_HOPLIMIT; 2847 } 2848 /* Rebuild the header template */ 2849 error = udp_build_hdrs(q, udp); 2850 if (error != 0) { 2851 *outlenp = 0; 2852 return (error); 2853 } 2854 } 2855 break; 2856 case IPV6_MULTICAST_LOOP: 2857 if (*i1 != 0 && *i1 != 1) { 2858 *outlenp = 0; 2859 return (EINVAL); 2860 } 2861 if (!checkonly) 2862 udp->udp_multicast_loop = *i1; 2863 break; 2864 case IPV6_JOIN_GROUP: 2865 case IPV6_LEAVE_GROUP: 2866 case MCAST_JOIN_GROUP: 2867 case MCAST_LEAVE_GROUP: 2868 case MCAST_BLOCK_SOURCE: 2869 case MCAST_UNBLOCK_SOURCE: 2870 case MCAST_JOIN_SOURCE_GROUP: 2871 case MCAST_LEAVE_SOURCE_GROUP: 2872 /* 2873 * "soft" error (negative) 2874 * option not handled at this level 2875 * Note: Do not modify *outlenp 2876 */ 2877 return (-EINVAL); 2878 case IPV6_BOUND_IF: 2879 if (!checkonly) 2880 udp->udp_bound_if = *i1; 2881 break; 2882 case IPV6_UNSPEC_SRC: 2883 if (!checkonly) 2884 udp->udp_unspec_source = onoff; 2885 break; 2886 /* 2887 * Set boolean switches for ancillary data delivery 2888 */ 2889 case IPV6_RECVPKTINFO: 2890 if (!checkonly) 2891 udp->udp_ipv6_recvpktinfo = onoff; 2892 break; 2893 case IPV6_RECVTCLASS: 2894 if (!checkonly) { 2895 udp->udp_ipv6_recvtclass = onoff; 2896 } 2897 break; 2898 case IPV6_RECVPATHMTU: 2899 if (!checkonly) { 2900 udp->udp_ipv6_recvpathmtu = onoff; 2901 } 2902 break; 2903 case IPV6_RECVHOPLIMIT: 2904 if (!checkonly) 2905 udp->udp_ipv6_recvhoplimit = onoff; 2906 break; 2907 case IPV6_RECVHOPOPTS: 2908 if (!checkonly) 2909 udp->udp_ipv6_recvhopopts = onoff; 2910 break; 2911 case IPV6_RECVDSTOPTS: 2912 if (!checkonly) 2913 udp->udp_ipv6_recvdstopts = onoff; 2914 break; 2915 case _OLD_IPV6_RECVDSTOPTS: 2916 if (!checkonly) 2917 udp->udp_old_ipv6_recvdstopts = onoff; 2918 break; 2919 case IPV6_RECVRTHDRDSTOPTS: 2920 if (!checkonly) 2921 udp->udp_ipv6_recvrthdrdstopts = onoff; 2922 break; 2923 case IPV6_RECVRTHDR: 2924 if (!checkonly) 2925 udp->udp_ipv6_recvrthdr = onoff; 2926 break; 2927 /* 2928 * Set sticky options or ancillary data. 2929 * If sticky options, (re)build any extension headers 2930 * that might be needed as a result. 2931 */ 2932 case IPV6_PKTINFO: 2933 /* 2934 * The source address and ifindex are verified 2935 * in ip_opt_set(). For ancillary data the 2936 * source address is checked in ip_wput_v6. 2937 */ 2938 if (inlen != 0 && inlen != sizeof (struct in6_pktinfo)) 2939 return (EINVAL); 2940 if (checkonly) 2941 break; 2942 2943 if (inlen == 0) { 2944 ipp->ipp_fields &= ~(IPPF_IFINDEX|IPPF_ADDR); 2945 ipp->ipp_sticky_ignored |= 2946 (IPPF_IFINDEX|IPPF_ADDR); 2947 } else { 2948 struct in6_pktinfo *pkti; 2949 2950 pkti = (struct in6_pktinfo *)invalp; 2951 ipp->ipp_ifindex = pkti->ipi6_ifindex; 2952 ipp->ipp_addr = pkti->ipi6_addr; 2953 if (ipp->ipp_ifindex != 0) 2954 ipp->ipp_fields |= IPPF_IFINDEX; 2955 else 2956 ipp->ipp_fields &= ~IPPF_IFINDEX; 2957 if (!IN6_IS_ADDR_UNSPECIFIED( 2958 &ipp->ipp_addr)) 2959 ipp->ipp_fields |= IPPF_ADDR; 2960 else 2961 ipp->ipp_fields &= ~IPPF_ADDR; 2962 } 2963 if (sticky) { 2964 error = udp_build_hdrs(q, udp); 2965 if (error != 0) 2966 return (error); 2967 } 2968 break; 2969 case IPV6_HOPLIMIT: 2970 if (inlen != 0 && inlen != sizeof (int)) 2971 return (EINVAL); 2972 if (checkonly) 2973 break; 2974 2975 if (inlen == 0) { 2976 ipp->ipp_fields &= ~IPPF_HOPLIMIT; 2977 ipp->ipp_sticky_ignored |= IPPF_HOPLIMIT; 2978 } else { 2979 if (*i1 > 255 || *i1 < -1) 2980 return (EINVAL); 2981 if (*i1 == -1) 2982 ipp->ipp_hoplimit = udp_ipv6_hoplimit; 2983 else 2984 ipp->ipp_hoplimit = *i1; 2985 ipp->ipp_fields |= IPPF_HOPLIMIT; 2986 } 2987 if (sticky) { 2988 error = udp_build_hdrs(q, udp); 2989 if (error != 0) 2990 return (error); 2991 } 2992 break; 2993 case IPV6_TCLASS: 2994 if (inlen != 0 && inlen != sizeof (int)) 2995 return (EINVAL); 2996 if (checkonly) 2997 break; 2998 2999 if (inlen == 0) { 3000 ipp->ipp_fields &= ~IPPF_TCLASS; 3001 ipp->ipp_sticky_ignored |= IPPF_TCLASS; 3002 } else { 3003 if (*i1 > 255 || *i1 < -1) 3004 return (EINVAL); 3005 if (*i1 == -1) 3006 ipp->ipp_tclass = 0; 3007 else 3008 ipp->ipp_tclass = *i1; 3009 ipp->ipp_fields |= IPPF_TCLASS; 3010 } 3011 if (sticky) { 3012 error = udp_build_hdrs(q, udp); 3013 if (error != 0) 3014 return (error); 3015 } 3016 break; 3017 case IPV6_NEXTHOP: 3018 /* 3019 * IP will verify that the nexthop is reachable 3020 * and fail for sticky options. 3021 */ 3022 if (inlen != 0 && inlen != sizeof (sin6_t)) 3023 return (EINVAL); 3024 if (checkonly) 3025 break; 3026 3027 if (inlen == 0) { 3028 ipp->ipp_fields &= ~IPPF_NEXTHOP; 3029 ipp->ipp_sticky_ignored |= IPPF_NEXTHOP; 3030 } else { 3031 sin6_t *sin6 = (sin6_t *)invalp; 3032 3033 if (sin6->sin6_family != AF_INET6) 3034 return (EAFNOSUPPORT); 3035 if (IN6_IS_ADDR_V4MAPPED( 3036 &sin6->sin6_addr)) 3037 return (EADDRNOTAVAIL); 3038 ipp->ipp_nexthop = sin6->sin6_addr; 3039 if (!IN6_IS_ADDR_UNSPECIFIED( 3040 &ipp->ipp_nexthop)) 3041 ipp->ipp_fields |= IPPF_NEXTHOP; 3042 else 3043 ipp->ipp_fields &= ~IPPF_NEXTHOP; 3044 } 3045 if (sticky) { 3046 error = udp_build_hdrs(q, udp); 3047 if (error != 0) 3048 return (error); 3049 } 3050 break; 3051 case IPV6_HOPOPTS: { 3052 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 3053 /* 3054 * Sanity checks - minimum size, size a multiple of 3055 * eight bytes, and matching size passed in. 3056 */ 3057 if (inlen != 0 && 3058 inlen != (8 * (hopts->ip6h_len + 1))) 3059 return (EINVAL); 3060 3061 if (checkonly) 3062 break; 3063 3064 if (inlen == 0) { 3065 if (sticky && 3066 (ipp->ipp_fields & IPPF_HOPOPTS) != 0) { 3067 kmem_free(ipp->ipp_hopopts, 3068 ipp->ipp_hopoptslen); 3069 ipp->ipp_hopopts = NULL; 3070 ipp->ipp_hopoptslen = 0; 3071 } 3072 ipp->ipp_fields &= ~IPPF_HOPOPTS; 3073 ipp->ipp_sticky_ignored |= IPPF_HOPOPTS; 3074 } else { 3075 error = udp_pkt_set(invalp, inlen, sticky, 3076 (uchar_t **)&ipp->ipp_hopopts, 3077 &ipp->ipp_hopoptslen); 3078 if (error != 0) 3079 return (error); 3080 ipp->ipp_fields |= IPPF_HOPOPTS; 3081 } 3082 if (sticky) { 3083 error = udp_build_hdrs(q, udp); 3084 if (error != 0) 3085 return (error); 3086 } 3087 break; 3088 } 3089 case IPV6_RTHDRDSTOPTS: { 3090 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 3091 3092 /* 3093 * Sanity checks - minimum size, size a multiple of 3094 * eight bytes, and matching size passed in. 3095 */ 3096 if (inlen != 0 && 3097 inlen != (8 * (dopts->ip6d_len + 1))) 3098 return (EINVAL); 3099 3100 if (checkonly) 3101 break; 3102 3103 if (inlen == 0) { 3104 if (sticky && 3105 (ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) { 3106 kmem_free(ipp->ipp_rtdstopts, 3107 ipp->ipp_rtdstoptslen); 3108 ipp->ipp_rtdstopts = NULL; 3109 ipp->ipp_rtdstoptslen = 0; 3110 } 3111 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 3112 ipp->ipp_sticky_ignored |= IPPF_RTDSTOPTS; 3113 } else { 3114 error = udp_pkt_set(invalp, inlen, sticky, 3115 (uchar_t **)&ipp->ipp_rtdstopts, 3116 &ipp->ipp_rtdstoptslen); 3117 if (error != 0) 3118 return (error); 3119 ipp->ipp_fields |= IPPF_RTDSTOPTS; 3120 } 3121 if (sticky) { 3122 error = udp_build_hdrs(q, udp); 3123 if (error != 0) 3124 return (error); 3125 } 3126 break; 3127 } 3128 case IPV6_DSTOPTS: { 3129 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 3130 3131 /* 3132 * Sanity checks - minimum size, size a multiple of 3133 * eight bytes, and matching size passed in. 3134 */ 3135 if (inlen != 0 && 3136 inlen != (8 * (dopts->ip6d_len + 1))) 3137 return (EINVAL); 3138 3139 if (checkonly) 3140 break; 3141 3142 if (inlen == 0) { 3143 if (sticky && 3144 (ipp->ipp_fields & IPPF_DSTOPTS) != 0) { 3145 kmem_free(ipp->ipp_dstopts, 3146 ipp->ipp_dstoptslen); 3147 ipp->ipp_dstopts = NULL; 3148 ipp->ipp_dstoptslen = 0; 3149 } 3150 ipp->ipp_fields &= ~IPPF_DSTOPTS; 3151 ipp->ipp_sticky_ignored |= IPPF_DSTOPTS; 3152 } else { 3153 error = udp_pkt_set(invalp, inlen, sticky, 3154 (uchar_t **)&ipp->ipp_dstopts, 3155 &ipp->ipp_dstoptslen); 3156 if (error != 0) 3157 return (error); 3158 ipp->ipp_fields |= IPPF_DSTOPTS; 3159 } 3160 if (sticky) { 3161 error = udp_build_hdrs(q, udp); 3162 if (error != 0) 3163 return (error); 3164 } 3165 break; 3166 } 3167 case IPV6_RTHDR: { 3168 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 3169 3170 /* 3171 * Sanity checks - minimum size, size a multiple of 3172 * eight bytes, and matching size passed in. 3173 */ 3174 if (inlen != 0 && 3175 inlen != (8 * (rt->ip6r_len + 1))) 3176 return (EINVAL); 3177 3178 if (checkonly) 3179 break; 3180 3181 if (inlen == 0) { 3182 if (sticky && 3183 (ipp->ipp_fields & IPPF_RTHDR) != 0) { 3184 kmem_free(ipp->ipp_rthdr, 3185 ipp->ipp_rthdrlen); 3186 ipp->ipp_rthdr = NULL; 3187 ipp->ipp_rthdrlen = 0; 3188 } 3189 ipp->ipp_fields &= ~IPPF_RTHDR; 3190 ipp->ipp_sticky_ignored |= IPPF_RTHDR; 3191 } else { 3192 error = udp_pkt_set(invalp, inlen, sticky, 3193 (uchar_t **)&ipp->ipp_rthdr, 3194 &ipp->ipp_rthdrlen); 3195 if (error != 0) 3196 return (error); 3197 ipp->ipp_fields |= IPPF_RTHDR; 3198 } 3199 if (sticky) { 3200 error = udp_build_hdrs(q, udp); 3201 if (error != 0) 3202 return (error); 3203 } 3204 break; 3205 } 3206 3207 case IPV6_DONTFRAG: 3208 if (checkonly) 3209 break; 3210 3211 if (onoff) { 3212 ipp->ipp_fields |= IPPF_DONTFRAG; 3213 } else { 3214 ipp->ipp_fields &= ~IPPF_DONTFRAG; 3215 } 3216 break; 3217 3218 case IPV6_USE_MIN_MTU: 3219 if (inlen != sizeof (int)) 3220 return (EINVAL); 3221 3222 if (*i1 < -1 || *i1 > 1) 3223 return (EINVAL); 3224 3225 if (checkonly) 3226 break; 3227 3228 ipp->ipp_fields |= IPPF_USE_MIN_MTU; 3229 ipp->ipp_use_min_mtu = *i1; 3230 break; 3231 3232 case IPV6_BOUND_PIF: 3233 case IPV6_SEC_OPT: 3234 case IPV6_DONTFAILOVER_IF: 3235 case IPV6_SRC_PREFERENCES: 3236 case IPV6_V6ONLY: 3237 /* Handled at the IP level */ 3238 return (-EINVAL); 3239 default: 3240 *outlenp = 0; 3241 return (EINVAL); 3242 } 3243 break; 3244 } /* end IPPROTO_IPV6 */ 3245 case IPPROTO_UDP: 3246 switch (name) { 3247 case UDP_ANONPRIVBIND: 3248 if ((error = secpolicy_net_privaddr(cr, 0)) != 0) { 3249 *outlenp = 0; 3250 return (error); 3251 } 3252 if (!checkonly) { 3253 udp->udp_anon_priv_bind = onoff; 3254 } 3255 break; 3256 case UDP_EXCLBIND: 3257 if (!checkonly) 3258 udp->udp_exclbind = onoff; 3259 break; 3260 case UDP_RCVHDR: 3261 if (!checkonly) 3262 udp->udp_rcvhdr = onoff; 3263 break; 3264 default: 3265 *outlenp = 0; 3266 return (EINVAL); 3267 } 3268 break; 3269 default: 3270 *outlenp = 0; 3271 return (EINVAL); 3272 } 3273 /* 3274 * Common case of OK return with outval same as inval. 3275 */ 3276 if (invalp != outvalp) { 3277 /* don't trust bcopy for identical src/dst */ 3278 (void) bcopy(invalp, outvalp, inlen); 3279 } 3280 *outlenp = inlen; 3281 return (0); 3282 } 3283 3284 /* 3285 * Update udp_sticky_hdrs based on udp_sticky_ipp, udp_v6src, and udp_ttl. 3286 * The headers include ip6i_t (if needed), ip6_t, any sticky extension 3287 * headers, and the udp header. 3288 * Returns failure if can't allocate memory. 3289 */ 3290 static int 3291 udp_build_hdrs(queue_t *q, udp_t *udp) 3292 { 3293 uchar_t *hdrs; 3294 uint_t hdrs_len; 3295 ip6_t *ip6h; 3296 ip6i_t *ip6i; 3297 udpha_t *udpha; 3298 ip6_pkt_t *ipp = &udp->udp_sticky_ipp; 3299 3300 hdrs_len = ip_total_hdrs_len_v6(ipp) + UDPH_SIZE; 3301 ASSERT(hdrs_len != 0); 3302 if (hdrs_len != udp->udp_sticky_hdrs_len) { 3303 /* Need to reallocate */ 3304 hdrs = kmem_alloc(hdrs_len, KM_NOSLEEP); 3305 if (hdrs == NULL) 3306 return (ENOMEM); 3307 3308 if (udp->udp_sticky_hdrs_len != 0) { 3309 kmem_free(udp->udp_sticky_hdrs, 3310 udp->udp_sticky_hdrs_len); 3311 } 3312 udp->udp_sticky_hdrs = hdrs; 3313 udp->udp_sticky_hdrs_len = hdrs_len; 3314 } 3315 ip_build_hdrs_v6(udp->udp_sticky_hdrs, 3316 udp->udp_sticky_hdrs_len - UDPH_SIZE, ipp, IPPROTO_UDP); 3317 3318 /* Set header fields not in ipp */ 3319 if (ipp->ipp_fields & IPPF_HAS_IP6I) { 3320 ip6i = (ip6i_t *)udp->udp_sticky_hdrs; 3321 ip6h = (ip6_t *)&ip6i[1]; 3322 } else { 3323 ip6h = (ip6_t *)udp->udp_sticky_hdrs; 3324 } 3325 3326 if (!(ipp->ipp_fields & IPPF_ADDR)) 3327 ip6h->ip6_src = udp->udp_v6src; 3328 3329 /* 3330 * If IPV6_HOPLIMIT was set in ipp, use that value. 3331 * For sticky options, if it does not exist use 3332 * the value in the udp structure. 3333 * All this as per RFC 2922. 3334 */ 3335 if (!(ipp->ipp_fields & IPPF_HOPLIMIT)) 3336 ip6h->ip6_hops = udp->udp_ttl; 3337 3338 udpha = (udpha_t *)(udp->udp_sticky_hdrs + hdrs_len - UDPH_SIZE); 3339 udpha->uha_src_port = udp->udp_port; 3340 3341 /* Try to get everything in a single mblk */ 3342 if (hdrs_len > udp->udp_max_hdr_len) { 3343 udp->udp_max_hdr_len = hdrs_len; 3344 (void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len + 3345 udp_wroff_extra); 3346 } 3347 return (0); 3348 } 3349 3350 /* 3351 * Set optbuf and optlen for the option. 3352 * If sticky is set allocate memory (if not already present). 3353 * Otherwise just point optbuf and optlen at invalp and inlen. 3354 * Returns failure if memory can not be allocated. 3355 */ 3356 static int 3357 udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky, 3358 uchar_t **optbufp, uint_t *optlenp) 3359 { 3360 uchar_t *optbuf; 3361 3362 if (!sticky) { 3363 *optbufp = invalp; 3364 *optlenp = inlen; 3365 return (0); 3366 } 3367 if (inlen == *optlenp) { 3368 /* Unchanged length - no need to realocate */ 3369 bcopy(invalp, *optbufp, inlen); 3370 return (0); 3371 } 3372 if (inlen != 0) { 3373 /* Allocate new buffer before free */ 3374 optbuf = kmem_alloc(inlen, KM_NOSLEEP); 3375 if (optbuf == NULL) 3376 return (ENOMEM); 3377 } else { 3378 optbuf = NULL; 3379 } 3380 /* Free old buffer */ 3381 if (*optlenp != 0) 3382 kmem_free(*optbufp, *optlenp); 3383 3384 bcopy(invalp, optbuf, inlen); 3385 *optbufp = optbuf; 3386 *optlenp = inlen; 3387 return (0); 3388 } 3389 3390 /* 3391 * This routine retrieves the value of an ND variable in a udpparam_t 3392 * structure. It is called through nd_getset when a user reads the 3393 * variable. 3394 */ 3395 /* ARGSUSED */ 3396 static int 3397 udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 3398 { 3399 udpparam_t *udppa = (udpparam_t *)cp; 3400 3401 (void) mi_mpprintf(mp, "%d", udppa->udp_param_value); 3402 return (0); 3403 } 3404 3405 /* 3406 * Walk through the param array specified registering each element with the 3407 * named dispatch (ND) handler. 3408 */ 3409 static boolean_t 3410 udp_param_register(udpparam_t *udppa, int cnt) 3411 { 3412 for (; cnt-- > 0; udppa++) { 3413 if (udppa->udp_param_name && udppa->udp_param_name[0]) { 3414 if (!nd_load(&udp_g_nd, udppa->udp_param_name, 3415 udp_param_get, udp_param_set, 3416 (caddr_t)udppa)) { 3417 nd_free(&udp_g_nd); 3418 return (B_FALSE); 3419 } 3420 } 3421 } 3422 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports", 3423 udp_extra_priv_ports_get, NULL, NULL)) { 3424 nd_free(&udp_g_nd); 3425 return (B_FALSE); 3426 } 3427 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_add", 3428 NULL, udp_extra_priv_ports_add, NULL)) { 3429 nd_free(&udp_g_nd); 3430 return (B_FALSE); 3431 } 3432 if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_del", 3433 NULL, udp_extra_priv_ports_del, NULL)) { 3434 nd_free(&udp_g_nd); 3435 return (B_FALSE); 3436 } 3437 if (!nd_load(&udp_g_nd, "udp_status", udp_status_report, NULL, 3438 NULL)) { 3439 nd_free(&udp_g_nd); 3440 return (B_FALSE); 3441 } 3442 if (!nd_load(&udp_g_nd, "udp_bind_hash", udp_bind_hash_report, NULL, 3443 NULL)) { 3444 nd_free(&udp_g_nd); 3445 return (B_FALSE); 3446 } 3447 return (B_TRUE); 3448 } 3449 3450 /* This routine sets an ND variable in a udpparam_t structure. */ 3451 /* ARGSUSED */ 3452 static int 3453 udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) 3454 { 3455 long new_value; 3456 udpparam_t *udppa = (udpparam_t *)cp; 3457 3458 /* 3459 * Fail the request if the new value does not lie within the 3460 * required bounds. 3461 */ 3462 if (ddi_strtol(value, NULL, 10, &new_value) != 0 || 3463 new_value < udppa->udp_param_min || 3464 new_value > udppa->udp_param_max) { 3465 return (EINVAL); 3466 } 3467 3468 /* Set the new value */ 3469 udppa->udp_param_value = new_value; 3470 return (0); 3471 } 3472 3473 static void 3474 udp_rput(queue_t *q, mblk_t *mp) 3475 { 3476 struct T_unitdata_ind *tudi; 3477 uchar_t *rptr; 3478 int hdr_length; 3479 int udi_size; /* Size of T_unitdata_ind */ 3480 udp_t *udp; 3481 udpha_t *udpha; 3482 int ipversion; 3483 ip6_pkt_t ipp; 3484 ip6_t *ip6h; 3485 ip6i_t *ip6i; 3486 mblk_t *mp1; 3487 mblk_t *options_mp = NULL; 3488 in_pktinfo_t *pinfo = NULL; 3489 size_t mp_size = MBLKL(mp); 3490 cred_t *cr = NULL; 3491 pid_t cpid; 3492 3493 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START, 3494 "udp_rput_start: q %p mp %p", q, mp); 3495 3496 udp = (udp_t *)q->q_ptr; 3497 rptr = mp->b_rptr; 3498 3499 switch (mp->b_datap->db_type) { 3500 case M_DATA: 3501 /* 3502 * M_DATA messages contain IP datagrams. They are handled 3503 * after this switch. 3504 */ 3505 break; 3506 case M_PROTO: 3507 case M_PCPROTO: 3508 /* M_PROTO messages contain some type of TPI message. */ 3509 if ((mp->b_wptr - rptr) < sizeof (t_scalar_t)) { 3510 freemsg(mp); 3511 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3512 "udp_rput_end: q %p (%S)", q, "protoshort"); 3513 return; 3514 } 3515 qwriter(q, mp, udp_rput_other, PERIM_INNER); 3516 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3517 "udp_rput_end: q %p (%S)", q, "proto"); 3518 return; 3519 case M_FLUSH: 3520 if (*mp->b_rptr & FLUSHR) 3521 flushq(q, FLUSHDATA); 3522 putnext(q, mp); 3523 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3524 "udp_rput_end: q %p (%S)", q, "flush"); 3525 return; 3526 case M_CTL: 3527 if (udp->udp_recvif || udp->udp_recvslla || 3528 udp->udp_ipv6_recvpktinfo) { 3529 /* 3530 * IP should have prepended the options data in an M_CTL 3531 * Check M_CTL "type" to make sure are not here bcos of 3532 * a valid ICMP message 3533 */ 3534 if (mp_size == sizeof (in_pktinfo_t) && 3535 ((in_pktinfo_t *)mp->b_rptr)->in_pkt_ulp_type == 3536 IN_PKTINFO) { 3537 pinfo = (in_pktinfo_t *)mp->b_rptr; 3538 /* 3539 * Jump to normal data processing, this is not 3540 * an ICMP message 3541 */ 3542 break; 3543 } 3544 } 3545 /* 3546 * ICMP messages. 3547 */ 3548 udp_icmp_error(q, mp); 3549 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3550 "udp_rput_end: q %p (%S)", q, "m_ctl"); 3551 return; 3552 default: 3553 putnext(q, mp); 3554 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3555 "udp_rput_end: q %p (%S)", q, "default"); 3556 return; 3557 } 3558 3559 /* 3560 * If we are here bcos the IP_RECVIF or IP_RECVSLLA then we need to 3561 * extract the mblk and adjust the rptr 3562 */ 3563 if (pinfo != NULL) { 3564 ASSERT(mp->b_datap->db_type == M_CTL); 3565 options_mp = mp; 3566 mp = mp->b_cont; 3567 rptr = mp->b_rptr; 3568 mp_size = MBLKL(mp); 3569 } 3570 /* 3571 * This is the inbound data path. 3572 * First, we check to make sure the IP version number is correct, 3573 * and then pull the IP and UDP headers into the first mblk. 3574 */ 3575 /* 3576 * Assume IP provides aligned packets - otherwise toss. 3577 * Also, check if we have a complete IP header. 3578 */ 3579 if (!OK_32PTR(rptr) || (mp_size < sizeof (ipha_t))) { 3580 tossit: 3581 freemsg(mp); 3582 if (options_mp != NULL) 3583 freeb(options_mp); 3584 BUMP_MIB(&udp_mib, udpInErrors); 3585 return; 3586 } 3587 3588 /* Initialize regardless if ipversion is IPv4 or IPv6 */ 3589 ipp.ipp_fields = 0; 3590 3591 ipversion = IPH_HDR_VERSION(rptr); 3592 switch (ipversion) { 3593 case IPV4_VERSION: 3594 hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE; 3595 /* Verify this is a UDP packet */ 3596 if (((ipha_t *)rptr)->ipha_protocol != IPPROTO_UDP) 3597 goto tossit; 3598 if ((hdr_length > IP_SIMPLE_HDR_LENGTH + UDPH_SIZE) || 3599 (udp->udp_ip_rcv_options_len)) { 3600 /* 3601 * Handle IPv4 packets with options outside of the 3602 * main data path. Not needed for AF_INET6 sockets 3603 * since they don't support a getsockopt of IP_OPTIONS. 3604 */ 3605 if (udp->udp_family == AF_INET6) 3606 break; 3607 /* 3608 * UDP length check performed for IPv4 packets with 3609 * options to check whether UDP length specified in 3610 * the header is the same as the physical length of 3611 * the packet. 3612 */ 3613 udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE)); 3614 if (msgdsize(mp) != (ntohs(udpha->uha_length) + 3615 hdr_length - UDPH_SIZE)) { 3616 goto tossit; 3617 } 3618 /* 3619 * Handle the case where the packet has IP options 3620 * and the IP_RECVSLLA & IP_RECVIF are set 3621 */ 3622 if (pinfo != NULL) 3623 mp = options_mp; 3624 qwriter(q, mp, udp_rput_other, PERIM_INNER); 3625 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3626 "udp_rput_end: q %p (%S)", q, "end"); 3627 return; 3628 } 3629 3630 /* Handle IPV6_RECVHOPLIMIT. */ 3631 if ((udp->udp_family == AF_INET6) && (pinfo != NULL)) { 3632 if (pinfo->in_pkt_flags & IPF_RECVIF) { 3633 ipp.ipp_fields |= IPPF_IFINDEX; 3634 ipp.ipp_ifindex = pinfo->in_pkt_ifindex; 3635 } 3636 } 3637 break; 3638 case IPV6_VERSION: 3639 /* 3640 * IPv6 packets can only be received by applications 3641 * that are prepared to receive IPv6 addresses. 3642 * The IP fanout must ensure this. 3643 */ 3644 ASSERT(udp->udp_family == AF_INET6); 3645 3646 ip6h = (ip6_t *)rptr; 3647 if ((uchar_t *)&ip6h[1] > mp->b_wptr) 3648 goto tossit; 3649 3650 if (ip6h->ip6_nxt != IPPROTO_UDP) { 3651 uint8_t nexthdrp; 3652 /* Look for ifindex information */ 3653 if (ip6h->ip6_nxt == IPPROTO_RAW) { 3654 ip6i = (ip6i_t *)ip6h; 3655 if ((uchar_t *)&ip6i[1] > mp->b_wptr) 3656 goto tossit; 3657 3658 if (ip6i->ip6i_flags & IP6I_IFINDEX) { 3659 ASSERT(ip6i->ip6i_ifindex != 0); 3660 ipp.ipp_fields |= IPPF_IFINDEX; 3661 ipp.ipp_ifindex = ip6i->ip6i_ifindex; 3662 } 3663 rptr = (uchar_t *)&ip6i[1]; 3664 mp->b_rptr = rptr; 3665 if (rptr == mp->b_wptr) { 3666 mp1 = mp->b_cont; 3667 freeb(mp); 3668 mp = mp1; 3669 rptr = mp->b_rptr; 3670 } 3671 if (MBLKL(mp) < (IPV6_HDR_LEN + UDPH_SIZE)) 3672 goto tossit; 3673 ip6h = (ip6_t *)rptr; 3674 } 3675 /* 3676 * Find any potentially interesting extension headers 3677 * as well as the length of the IPv6 + extension 3678 * headers. 3679 */ 3680 hdr_length = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdrp) + 3681 UDPH_SIZE; 3682 /* Verify this is a UDP packet */ 3683 if (nexthdrp != IPPROTO_UDP) 3684 goto tossit; 3685 } else { 3686 hdr_length = IPV6_HDR_LEN + UDPH_SIZE; 3687 ip6i = NULL; 3688 } 3689 break; 3690 default: 3691 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3692 "udp_rput_end: q %p (%S)", q, "Unknown IP version"); 3693 goto tossit; 3694 } 3695 3696 /* 3697 * IP inspected the UDP header thus all of it must be in the mblk. 3698 * UDP length check is performed for IPv6 packets and IPv4 packets 3699 * without options to check if the size of the packet as specified 3700 * by the header is the same as the physical size of the packet. 3701 */ 3702 udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE)); 3703 if ((MBLKL(mp) < hdr_length) || 3704 (msgdsize(mp) != (ntohs(udpha->uha_length) + 3705 hdr_length - UDPH_SIZE))) { 3706 goto tossit; 3707 } 3708 3709 /* Walk past the headers. */ 3710 if (!udp->udp_rcvhdr) 3711 mp->b_rptr = rptr + hdr_length; 3712 3713 /* 3714 * This is the inbound data path. Packets are passed upstream as 3715 * T_UNITDATA_IND messages with full IP headers still attached. 3716 */ 3717 if (udp->udp_family == AF_INET) { 3718 sin_t *sin; 3719 3720 ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION); 3721 3722 /* 3723 * Normally only send up the address. 3724 * If IP_RECVDSTADDR is set we include the destination IP 3725 * address as an option. With IP_RECVOPTS we include all 3726 * the IP options. Only ip_rput_other() handles packets 3727 * that contain IP options. 3728 */ 3729 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 3730 if (udp->udp_recvdstaddr) { 3731 udi_size += sizeof (struct T_opthdr) + 3732 sizeof (struct in_addr); 3733 } 3734 3735 /* 3736 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate 3737 * space accordingly 3738 */ 3739 if (udp->udp_recvif && (pinfo != NULL) && 3740 (pinfo->in_pkt_flags & IPF_RECVIF)) { 3741 udi_size += sizeof (struct T_opthdr) + 3742 sizeof (uint_t); 3743 } 3744 3745 if (udp->udp_recvslla && (pinfo != NULL) && 3746 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 3747 udi_size += sizeof (struct T_opthdr) + 3748 sizeof (struct sockaddr_dl); 3749 } 3750 3751 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 3752 udi_size += sizeof (struct T_opthdr) + ucredsize; 3753 cpid = DB_CPID(mp); 3754 } 3755 /* 3756 * If IP_RECVTTL is set allocate the appropriate sized buffer 3757 */ 3758 if (udp->udp_recvttl) { 3759 udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t); 3760 } 3761 3762 ASSERT(IPH_HDR_LENGTH((ipha_t *)rptr) == IP_SIMPLE_HDR_LENGTH); 3763 3764 /* Allocate a message block for the T_UNITDATA_IND structure. */ 3765 mp1 = allocb(udi_size, BPRI_MED); 3766 if (mp1 == NULL) { 3767 freemsg(mp); 3768 if (options_mp != NULL) 3769 freeb(options_mp); 3770 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3771 "udp_rput_end: q %p (%S)", q, "allocbfail"); 3772 BUMP_MIB(&udp_mib, udpInErrors); 3773 return; 3774 } 3775 mp1->b_cont = mp; 3776 mp = mp1; 3777 mp->b_datap->db_type = M_PROTO; 3778 tudi = (struct T_unitdata_ind *)mp->b_rptr; 3779 mp->b_wptr = (uchar_t *)tudi + udi_size; 3780 tudi->PRIM_type = T_UNITDATA_IND; 3781 tudi->SRC_length = sizeof (sin_t); 3782 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 3783 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 3784 sizeof (sin_t); 3785 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t)); 3786 tudi->OPT_length = udi_size; 3787 sin = (sin_t *)&tudi[1]; 3788 sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src; 3789 sin->sin_port = udpha->uha_src_port; 3790 sin->sin_family = udp->udp_family; 3791 *(uint32_t *)&sin->sin_zero[0] = 0; 3792 *(uint32_t *)&sin->sin_zero[4] = 0; 3793 3794 /* 3795 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or 3796 * IP_RECVTTL has been set. 3797 */ 3798 if (udi_size != 0) { 3799 /* 3800 * Copy in destination address before options to avoid 3801 * any padding issues. 3802 */ 3803 char *dstopt; 3804 3805 dstopt = (char *)&sin[1]; 3806 if (udp->udp_recvdstaddr) { 3807 struct T_opthdr *toh; 3808 ipaddr_t *dstptr; 3809 3810 toh = (struct T_opthdr *)dstopt; 3811 toh->level = IPPROTO_IP; 3812 toh->name = IP_RECVDSTADDR; 3813 toh->len = sizeof (struct T_opthdr) + 3814 sizeof (ipaddr_t); 3815 toh->status = 0; 3816 dstopt += sizeof (struct T_opthdr); 3817 dstptr = (ipaddr_t *)dstopt; 3818 *dstptr = ((ipha_t *)rptr)->ipha_dst; 3819 dstopt += sizeof (ipaddr_t); 3820 udi_size -= toh->len; 3821 } 3822 3823 if (udp->udp_recvslla && (pinfo != NULL) && 3824 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 3825 3826 struct T_opthdr *toh; 3827 struct sockaddr_dl *dstptr; 3828 3829 toh = (struct T_opthdr *)dstopt; 3830 toh->level = IPPROTO_IP; 3831 toh->name = IP_RECVSLLA; 3832 toh->len = sizeof (struct T_opthdr) + 3833 sizeof (struct sockaddr_dl); 3834 toh->status = 0; 3835 dstopt += sizeof (struct T_opthdr); 3836 dstptr = (struct sockaddr_dl *)dstopt; 3837 bcopy(&pinfo->in_pkt_slla, dstptr, 3838 sizeof (struct sockaddr_dl)); 3839 dstopt += sizeof (struct sockaddr_dl); 3840 udi_size -= toh->len; 3841 } 3842 3843 if (udp->udp_recvif && (pinfo != NULL) && 3844 (pinfo->in_pkt_flags & IPF_RECVIF)) { 3845 3846 struct T_opthdr *toh; 3847 uint_t *dstptr; 3848 3849 toh = (struct T_opthdr *)dstopt; 3850 toh->level = IPPROTO_IP; 3851 toh->name = IP_RECVIF; 3852 toh->len = sizeof (struct T_opthdr) + 3853 sizeof (uint_t); 3854 toh->status = 0; 3855 dstopt += sizeof (struct T_opthdr); 3856 dstptr = (uint_t *)dstopt; 3857 *dstptr = pinfo->in_pkt_ifindex; 3858 dstopt += sizeof (uint_t); 3859 udi_size -= toh->len; 3860 } 3861 3862 if (cr != NULL) { 3863 struct T_opthdr *toh; 3864 3865 toh = (struct T_opthdr *)dstopt; 3866 toh->level = SOL_SOCKET; 3867 toh->name = SCM_UCRED; 3868 toh->len = sizeof (struct T_opthdr) + ucredsize; 3869 toh->status = 0; 3870 (void) cred2ucred(cr, cpid, &toh[1]); 3871 dstopt += toh->len; 3872 udi_size -= toh->len; 3873 } 3874 3875 if (udp->udp_recvttl) { 3876 struct T_opthdr *toh; 3877 uint8_t *dstptr; 3878 3879 toh = (struct T_opthdr *)dstopt; 3880 toh->level = IPPROTO_IP; 3881 toh->name = IP_RECVTTL; 3882 toh->len = sizeof (struct T_opthdr) + 3883 sizeof (uint8_t); 3884 toh->status = 0; 3885 dstopt += sizeof (struct T_opthdr); 3886 dstptr = (uint8_t *)dstopt; 3887 *dstptr = ((ipha_t *)rptr)->ipha_ttl; 3888 dstopt += sizeof (uint8_t); 3889 udi_size -= toh->len; 3890 } 3891 3892 /* Consumed all of allocated space */ 3893 ASSERT(udi_size == 0); 3894 } 3895 } else { 3896 sin6_t *sin6; 3897 3898 /* 3899 * Handle both IPv4 and IPv6 packets for IPv6 sockets. 3900 * 3901 * Normally we only send up the address. If receiving of any 3902 * optional receive side information is enabled, we also send 3903 * that up as options. 3904 * [ Only udp_rput_other() handles packets that contain IP 3905 * options so code to account for does not appear immediately 3906 * below but elsewhere ] 3907 */ 3908 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t); 3909 3910 if (ipp.ipp_fields & (IPPF_HOPOPTS|IPPF_DSTOPTS|IPPF_RTDSTOPTS| 3911 IPPF_RTHDR|IPPF_IFINDEX)) { 3912 if (udp->udp_ipv6_recvhopopts && 3913 (ipp.ipp_fields & IPPF_HOPOPTS)) { 3914 udi_size += sizeof (struct T_opthdr) + 3915 ipp.ipp_hopoptslen; 3916 } 3917 if ((udp->udp_ipv6_recvdstopts || 3918 udp->udp_old_ipv6_recvdstopts) && 3919 (ipp.ipp_fields & IPPF_DSTOPTS)) { 3920 udi_size += sizeof (struct T_opthdr) + 3921 ipp.ipp_dstoptslen; 3922 } 3923 if (((udp->udp_ipv6_recvdstopts && 3924 udp->udp_ipv6_recvrthdr && 3925 (ipp.ipp_fields & IPPF_RTHDR)) || 3926 udp->udp_ipv6_recvrthdrdstopts) && 3927 (ipp.ipp_fields & IPPF_RTDSTOPTS)) { 3928 udi_size += sizeof (struct T_opthdr) + 3929 ipp.ipp_rtdstoptslen; 3930 } 3931 if (udp->udp_ipv6_recvrthdr && 3932 (ipp.ipp_fields & IPPF_RTHDR)) { 3933 udi_size += sizeof (struct T_opthdr) + 3934 ipp.ipp_rthdrlen; 3935 } 3936 if (udp->udp_ipv6_recvpktinfo && 3937 (ipp.ipp_fields & IPPF_IFINDEX)) { 3938 udi_size += sizeof (struct T_opthdr) + 3939 sizeof (struct in6_pktinfo); 3940 } 3941 3942 } 3943 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 3944 udi_size += sizeof (struct T_opthdr) + ucredsize; 3945 cpid = DB_CPID(mp); 3946 } 3947 3948 if (udp->udp_ipv6_recvhoplimit) 3949 udi_size += sizeof (struct T_opthdr) + sizeof (int); 3950 3951 if (udp->udp_ipv6_recvtclass) 3952 udi_size += sizeof (struct T_opthdr) + sizeof (int); 3953 3954 mp1 = allocb(udi_size, BPRI_MED); 3955 if (mp1 == NULL) { 3956 freemsg(mp); 3957 if (options_mp != NULL) 3958 freeb(options_mp); 3959 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 3960 "udp_rput_end: q %p (%S)", q, "allocbfail"); 3961 BUMP_MIB(&udp_mib, udpInErrors); 3962 return; 3963 } 3964 mp1->b_cont = mp; 3965 mp = mp1; 3966 mp->b_datap->db_type = M_PROTO; 3967 tudi = (struct T_unitdata_ind *)mp->b_rptr; 3968 mp->b_wptr = (uchar_t *)tudi + udi_size; 3969 tudi->PRIM_type = T_UNITDATA_IND; 3970 tudi->SRC_length = sizeof (sin6_t); 3971 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 3972 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + 3973 sizeof (sin6_t); 3974 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin6_t)); 3975 tudi->OPT_length = udi_size; 3976 sin6 = (sin6_t *)&tudi[1]; 3977 if (ipversion == IPV4_VERSION) { 3978 in6_addr_t v6dst; 3979 3980 IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_src, 3981 &sin6->sin6_addr); 3982 IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_dst, 3983 &v6dst); 3984 sin6->sin6_flowinfo = 0; 3985 sin6->sin6_scope_id = 0; 3986 sin6->__sin6_src_id = ip_srcid_find_addr(&v6dst, 3987 udp->udp_zoneid); 3988 } else { 3989 sin6->sin6_addr = ip6h->ip6_src; 3990 /* No sin6_flowinfo per API */ 3991 sin6->sin6_flowinfo = 0; 3992 /* For link-scope source pass up scope id */ 3993 if ((ipp.ipp_fields & IPPF_IFINDEX) && 3994 IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) 3995 sin6->sin6_scope_id = ipp.ipp_ifindex; 3996 else 3997 sin6->sin6_scope_id = 0; 3998 sin6->__sin6_src_id = 3999 ip_srcid_find_addr(&ip6h->ip6_dst, udp->udp_zoneid); 4000 } 4001 sin6->sin6_port = udpha->uha_src_port; 4002 sin6->sin6_family = udp->udp_family; 4003 4004 if (udi_size != 0) { 4005 uchar_t *dstopt; 4006 4007 dstopt = (uchar_t *)&sin6[1]; 4008 if (udp->udp_ipv6_recvpktinfo && 4009 (ipp.ipp_fields & IPPF_IFINDEX)) { 4010 struct T_opthdr *toh; 4011 struct in6_pktinfo *pkti; 4012 4013 toh = (struct T_opthdr *)dstopt; 4014 toh->level = IPPROTO_IPV6; 4015 toh->name = IPV6_PKTINFO; 4016 toh->len = sizeof (struct T_opthdr) + 4017 sizeof (*pkti); 4018 toh->status = 0; 4019 dstopt += sizeof (struct T_opthdr); 4020 pkti = (struct in6_pktinfo *)dstopt; 4021 if (ipversion == IPV6_VERSION) 4022 pkti->ipi6_addr = ip6h->ip6_dst; 4023 else 4024 IN6_IPADDR_TO_V4MAPPED( 4025 ((ipha_t *)rptr)->ipha_dst, 4026 &pkti->ipi6_addr); 4027 pkti->ipi6_ifindex = ipp.ipp_ifindex; 4028 dstopt += sizeof (*pkti); 4029 udi_size -= toh->len; 4030 } 4031 if (udp->udp_ipv6_recvhoplimit) { 4032 struct T_opthdr *toh; 4033 4034 toh = (struct T_opthdr *)dstopt; 4035 toh->level = IPPROTO_IPV6; 4036 toh->name = IPV6_HOPLIMIT; 4037 toh->len = sizeof (struct T_opthdr) + 4038 sizeof (uint_t); 4039 toh->status = 0; 4040 dstopt += sizeof (struct T_opthdr); 4041 if (ipversion == IPV6_VERSION) 4042 *(uint_t *)dstopt = ip6h->ip6_hops; 4043 else 4044 *(uint_t *)dstopt = 4045 ((ipha_t *)rptr)->ipha_ttl; 4046 dstopt += sizeof (uint_t); 4047 udi_size -= toh->len; 4048 } 4049 if (udp->udp_ipv6_recvtclass) { 4050 struct T_opthdr *toh; 4051 4052 toh = (struct T_opthdr *)dstopt; 4053 toh->level = IPPROTO_IPV6; 4054 toh->name = IPV6_TCLASS; 4055 toh->len = sizeof (struct T_opthdr) + 4056 sizeof (uint_t); 4057 toh->status = 0; 4058 dstopt += sizeof (struct T_opthdr); 4059 if (ipversion == IPV6_VERSION) { 4060 *(uint_t *)dstopt = 4061 IPV6_FLOW_TCLASS(ip6h->ip6_flow); 4062 } else { 4063 ipha_t *ipha = (ipha_t *)rptr; 4064 *(uint_t *)dstopt = 4065 ipha->ipha_type_of_service; 4066 } 4067 dstopt += sizeof (uint_t); 4068 udi_size -= toh->len; 4069 } 4070 if (udp->udp_ipv6_recvhopopts && 4071 (ipp.ipp_fields & IPPF_HOPOPTS)) { 4072 struct T_opthdr *toh; 4073 4074 toh = (struct T_opthdr *)dstopt; 4075 toh->level = IPPROTO_IPV6; 4076 toh->name = IPV6_HOPOPTS; 4077 toh->len = sizeof (struct T_opthdr) + 4078 ipp.ipp_hopoptslen; 4079 toh->status = 0; 4080 dstopt += sizeof (struct T_opthdr); 4081 bcopy(ipp.ipp_hopopts, dstopt, 4082 ipp.ipp_hopoptslen); 4083 dstopt += ipp.ipp_hopoptslen; 4084 udi_size -= toh->len; 4085 } 4086 if (udp->udp_ipv6_recvdstopts && 4087 udp->udp_ipv6_recvrthdr && 4088 (ipp.ipp_fields & IPPF_RTHDR) && 4089 (ipp.ipp_fields & IPPF_RTDSTOPTS)) { 4090 struct T_opthdr *toh; 4091 4092 toh = (struct T_opthdr *)dstopt; 4093 toh->level = IPPROTO_IPV6; 4094 toh->name = IPV6_DSTOPTS; 4095 toh->len = sizeof (struct T_opthdr) + 4096 ipp.ipp_rtdstoptslen; 4097 toh->status = 0; 4098 dstopt += sizeof (struct T_opthdr); 4099 bcopy(ipp.ipp_rtdstopts, dstopt, 4100 ipp.ipp_rtdstoptslen); 4101 dstopt += ipp.ipp_rtdstoptslen; 4102 udi_size -= toh->len; 4103 } 4104 if (udp->udp_ipv6_recvrthdr && 4105 (ipp.ipp_fields & IPPF_RTHDR)) { 4106 struct T_opthdr *toh; 4107 4108 toh = (struct T_opthdr *)dstopt; 4109 toh->level = IPPROTO_IPV6; 4110 toh->name = IPV6_RTHDR; 4111 toh->len = sizeof (struct T_opthdr) + 4112 ipp.ipp_rthdrlen; 4113 toh->status = 0; 4114 dstopt += sizeof (struct T_opthdr); 4115 bcopy(ipp.ipp_rthdr, dstopt, ipp.ipp_rthdrlen); 4116 dstopt += ipp.ipp_rthdrlen; 4117 udi_size -= toh->len; 4118 } 4119 if (udp->udp_ipv6_recvdstopts && 4120 (ipp.ipp_fields & IPPF_DSTOPTS)) { 4121 struct T_opthdr *toh; 4122 4123 toh = (struct T_opthdr *)dstopt; 4124 toh->level = IPPROTO_IPV6; 4125 toh->name = IPV6_DSTOPTS; 4126 toh->len = sizeof (struct T_opthdr) + 4127 ipp.ipp_dstoptslen; 4128 toh->status = 0; 4129 dstopt += sizeof (struct T_opthdr); 4130 bcopy(ipp.ipp_dstopts, dstopt, 4131 ipp.ipp_dstoptslen); 4132 dstopt += ipp.ipp_dstoptslen; 4133 udi_size -= toh->len; 4134 } 4135 4136 if (cr != NULL) { 4137 struct T_opthdr *toh; 4138 4139 toh = (struct T_opthdr *)dstopt; 4140 toh->level = SOL_SOCKET; 4141 toh->name = SCM_UCRED; 4142 toh->len = sizeof (struct T_opthdr) + ucredsize; 4143 toh->status = 0; 4144 (void) cred2ucred(cr, cpid, &toh[1]); 4145 dstopt += toh->len; 4146 udi_size -= toh->len; 4147 } 4148 /* Consumed all of allocated space */ 4149 ASSERT(udi_size == 0); 4150 } 4151 #undef sin6 4152 /* No IP_RECVDSTADDR for IPv6. */ 4153 } 4154 4155 BUMP_MIB(&udp_mib, udpInDatagrams); 4156 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4157 "udp_rput_end: q %p (%S)", q, "end"); 4158 if (options_mp != NULL) 4159 freeb(options_mp); 4160 putnext(q, mp); 4161 } 4162 4163 /* 4164 * Process non-M_DATA messages as well as M_DATA messages that requires 4165 * modifications to udp_ip_rcv_options i.e. IPv4 packets with IP options. 4166 */ 4167 static void 4168 udp_rput_other(queue_t *q, mblk_t *mp) 4169 { 4170 struct T_unitdata_ind *tudi; 4171 mblk_t *mp1; 4172 uchar_t *rptr; 4173 uchar_t *new_rptr; 4174 int hdr_length; 4175 int udi_size; /* Size of T_unitdata_ind */ 4176 int opt_len; /* Length of IP options */ 4177 sin_t *sin; 4178 struct T_error_ack *tea; 4179 udp_t *udp; 4180 mblk_t *options_mp = NULL; 4181 in_pktinfo_t *pinfo; 4182 boolean_t recv_on = B_FALSE; 4183 cred_t *cr = NULL; 4184 pid_t cpid; 4185 4186 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START, 4187 "udp_rput_other: q %p mp %p", q, mp); 4188 4189 ASSERT(OK_32PTR(mp->b_rptr)); 4190 udp = (udp_t *)q->q_ptr; 4191 rptr = mp->b_rptr; 4192 4193 switch (mp->b_datap->db_type) { 4194 case M_CTL: 4195 /* 4196 * We are here only if IP_RECVSLLA and/or IP_RECVIF are set 4197 */ 4198 recv_on = B_TRUE; 4199 options_mp = mp; 4200 pinfo = (in_pktinfo_t *)options_mp->b_rptr; 4201 4202 /* 4203 * The actual data is in mp->b_cont 4204 */ 4205 mp = mp->b_cont; 4206 ASSERT(OK_32PTR(mp->b_rptr)); 4207 rptr = mp->b_rptr; 4208 break; 4209 case M_DATA: 4210 /* 4211 * M_DATA messages contain IPv4 datagrams. They are handled 4212 * after this switch. 4213 */ 4214 break; 4215 case M_PROTO: 4216 case M_PCPROTO: 4217 /* M_PROTO messages contain some type of TPI message. */ 4218 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 4219 if (mp->b_wptr - rptr < sizeof (t_scalar_t)) { 4220 freemsg(mp); 4221 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4222 "udp_rput_other_end: q %p (%S)", q, "protoshort"); 4223 return; 4224 } 4225 tea = (struct T_error_ack *)rptr; 4226 4227 switch (tea->PRIM_type) { 4228 case T_ERROR_ACK: 4229 switch (tea->ERROR_prim) { 4230 case O_T_BIND_REQ: 4231 case T_BIND_REQ: { 4232 /* 4233 * If our O_T_BIND_REQ/T_BIND_REQ fails, 4234 * clear out the associated port and source 4235 * address before passing the message 4236 * upstream. If this was caused by a T_CONN_REQ 4237 * revert back to bound state. 4238 */ 4239 udp_fanout_t *udpf; 4240 4241 udpf = &udp_bind_fanout[ 4242 UDP_BIND_HASH(udp->udp_port)]; 4243 mutex_enter(&udpf->uf_lock); 4244 if (udp->udp_state == TS_DATA_XFER) { 4245 /* Connect failed */ 4246 tea->ERROR_prim = T_CONN_REQ; 4247 /* Revert back to the bound source */ 4248 udp->udp_v6src = udp->udp_bound_v6src; 4249 udp->udp_state = TS_IDLE; 4250 mutex_exit(&udpf->uf_lock); 4251 if (udp->udp_family == AF_INET6) 4252 (void) udp_build_hdrs(q, udp); 4253 break; 4254 } 4255 4256 if (udp->udp_discon_pending) { 4257 tea->ERROR_prim = T_DISCON_REQ; 4258 udp->udp_discon_pending = 0; 4259 } 4260 V6_SET_ZERO(udp->udp_v6src); 4261 V6_SET_ZERO(udp->udp_bound_v6src); 4262 udp->udp_state = TS_UNBND; 4263 udp_bind_hash_remove(udp, B_TRUE); 4264 udp->udp_port = 0; 4265 mutex_exit(&udpf->uf_lock); 4266 if (udp->udp_family == AF_INET6) 4267 (void) udp_build_hdrs(q, udp); 4268 break; 4269 } 4270 default: 4271 break; 4272 } 4273 break; 4274 case T_BIND_ACK: 4275 udp_rput_bind_ack(q, mp); 4276 return; 4277 4278 case T_OPTMGMT_ACK: 4279 case T_OK_ACK: 4280 break; 4281 default: 4282 freemsg(mp); 4283 return; 4284 } 4285 putnext(q, mp); 4286 return; 4287 } 4288 4289 /* 4290 * This is the inbound data path. 4291 * First, we make sure the data contains both IP and UDP headers. 4292 * 4293 * This handle IPv4 packets for only AF_INET sockets. 4294 * AF_INET6 sockets can never access udp_ip_rcv_options thus there 4295 * is no need saving the options. 4296 */ 4297 ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION); 4298 hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE; 4299 if (mp->b_wptr - rptr < hdr_length) { 4300 if (!pullupmsg(mp, hdr_length)) { 4301 freemsg(mp); 4302 if (options_mp != NULL) 4303 freeb(options_mp); 4304 BUMP_MIB(&udp_mib, udpInErrors); 4305 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4306 "udp_rput_other_end: q %p (%S)", q, "hdrshort"); 4307 BUMP_MIB(&udp_mib, udpInErrors); 4308 return; 4309 } 4310 rptr = mp->b_rptr; 4311 } 4312 /* Walk past the headers. */ 4313 new_rptr = rptr + hdr_length; 4314 if (!udp->udp_rcvhdr) 4315 mp->b_rptr = new_rptr; 4316 4317 /* Save the options if any */ 4318 opt_len = hdr_length - (IP_SIMPLE_HDR_LENGTH + UDPH_SIZE); 4319 if (opt_len > 0) { 4320 if (opt_len > udp->udp_ip_rcv_options_len) { 4321 if (udp->udp_ip_rcv_options_len) 4322 mi_free((char *)udp->udp_ip_rcv_options); 4323 udp->udp_ip_rcv_options_len = 0; 4324 udp->udp_ip_rcv_options = 4325 (uchar_t *)mi_alloc(opt_len, BPRI_HI); 4326 if (udp->udp_ip_rcv_options) 4327 udp->udp_ip_rcv_options_len = opt_len; 4328 } 4329 if (udp->udp_ip_rcv_options_len) { 4330 bcopy(rptr + IP_SIMPLE_HDR_LENGTH, 4331 udp->udp_ip_rcv_options, opt_len); 4332 /* Adjust length if we are resusing the space */ 4333 udp->udp_ip_rcv_options_len = opt_len; 4334 } 4335 } else if (udp->udp_ip_rcv_options_len) { 4336 mi_free((char *)udp->udp_ip_rcv_options); 4337 udp->udp_ip_rcv_options = NULL; 4338 udp->udp_ip_rcv_options_len = 0; 4339 } 4340 4341 /* 4342 * Normally only send up the address. 4343 * If IP_RECVDSTADDR is set we include the destination IP 4344 * address as an option. With IP_RECVOPTS we include all 4345 * the IP options. 4346 */ 4347 udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 4348 if (udp->udp_recvdstaddr) { 4349 udi_size += sizeof (struct T_opthdr) + sizeof (struct in_addr); 4350 } 4351 if (udp->udp_recvopts && opt_len > 0) 4352 udi_size += sizeof (struct T_opthdr) + opt_len; 4353 4354 /* 4355 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate 4356 * space accordingly 4357 */ 4358 if (udp->udp_recvif && recv_on && 4359 (pinfo->in_pkt_flags & IPF_RECVIF)) { 4360 udi_size += sizeof (struct T_opthdr) + 4361 sizeof (uint_t); 4362 } 4363 4364 if (udp->udp_recvslla && recv_on && 4365 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 4366 udi_size += sizeof (struct T_opthdr) + 4367 sizeof (struct sockaddr_dl); 4368 } 4369 4370 if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) { 4371 udi_size += sizeof (struct T_opthdr) + ucredsize; 4372 cpid = DB_CPID(mp); 4373 } 4374 /* 4375 * If IP_RECVTTL is set allocate the appropriate sized buffer 4376 */ 4377 if (udp->udp_recvttl) { 4378 udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t); 4379 } 4380 4381 /* Allocate a message block for the T_UNITDATA_IND structure. */ 4382 mp1 = allocb(udi_size, BPRI_MED); 4383 if (mp1 == NULL) { 4384 freemsg(mp); 4385 if (options_mp != NULL) 4386 freeb(options_mp); 4387 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4388 "udp_rput_other_end: q %p (%S)", q, "allocbfail"); 4389 BUMP_MIB(&udp_mib, udpInErrors); 4390 return; 4391 } 4392 mp1->b_cont = mp; 4393 mp = mp1; 4394 mp->b_datap->db_type = M_PROTO; 4395 tudi = (struct T_unitdata_ind *)mp->b_rptr; 4396 mp->b_wptr = (uchar_t *)tudi + udi_size; 4397 tudi->PRIM_type = T_UNITDATA_IND; 4398 tudi->SRC_length = sizeof (sin_t); 4399 tudi->SRC_offset = sizeof (struct T_unitdata_ind); 4400 tudi->OPT_offset = sizeof (struct T_unitdata_ind) + sizeof (sin_t); 4401 udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t)); 4402 tudi->OPT_length = udi_size; 4403 4404 sin = (sin_t *)&tudi[1]; 4405 sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src; 4406 sin->sin_port = ((in_port_t *) 4407 new_rptr)[-(UDPH_SIZE/sizeof (in_port_t))]; 4408 sin->sin_family = AF_INET; 4409 *(uint32_t *)&sin->sin_zero[0] = 0; 4410 *(uint32_t *)&sin->sin_zero[4] = 0; 4411 4412 /* 4413 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or 4414 * IP_RECVTTL has been set. 4415 */ 4416 if (udi_size != 0) { 4417 /* 4418 * Copy in destination address before options to avoid any 4419 * padding issues. 4420 */ 4421 char *dstopt; 4422 4423 dstopt = (char *)&sin[1]; 4424 if (udp->udp_recvdstaddr) { 4425 struct T_opthdr *toh; 4426 ipaddr_t *dstptr; 4427 4428 toh = (struct T_opthdr *)dstopt; 4429 toh->level = IPPROTO_IP; 4430 toh->name = IP_RECVDSTADDR; 4431 toh->len = sizeof (struct T_opthdr) + sizeof (ipaddr_t); 4432 toh->status = 0; 4433 dstopt += sizeof (struct T_opthdr); 4434 dstptr = (ipaddr_t *)dstopt; 4435 *dstptr = (((ipaddr_t *)rptr)[4]); 4436 dstopt += sizeof (ipaddr_t); 4437 udi_size -= toh->len; 4438 } 4439 if (udp->udp_recvopts && udi_size != 0) { 4440 struct T_opthdr *toh; 4441 4442 toh = (struct T_opthdr *)dstopt; 4443 toh->level = IPPROTO_IP; 4444 toh->name = IP_RECVOPTS; 4445 toh->len = sizeof (struct T_opthdr) + opt_len; 4446 toh->status = 0; 4447 dstopt += sizeof (struct T_opthdr); 4448 bcopy(rptr + IP_SIMPLE_HDR_LENGTH, dstopt, opt_len); 4449 dstopt += opt_len; 4450 udi_size -= toh->len; 4451 } 4452 4453 if (udp->udp_recvslla && recv_on && 4454 (pinfo->in_pkt_flags & IPF_RECVSLLA)) { 4455 4456 struct T_opthdr *toh; 4457 struct sockaddr_dl *dstptr; 4458 4459 toh = (struct T_opthdr *)dstopt; 4460 toh->level = IPPROTO_IP; 4461 toh->name = IP_RECVSLLA; 4462 toh->len = sizeof (struct T_opthdr) + 4463 sizeof (struct sockaddr_dl); 4464 toh->status = 0; 4465 dstopt += sizeof (struct T_opthdr); 4466 dstptr = (struct sockaddr_dl *)dstopt; 4467 bcopy(&pinfo->in_pkt_slla, dstptr, 4468 sizeof (struct sockaddr_dl)); 4469 dstopt += sizeof (struct sockaddr_dl); 4470 udi_size -= toh->len; 4471 } 4472 4473 if (udp->udp_recvif && recv_on && 4474 (pinfo->in_pkt_flags & IPF_RECVIF)) { 4475 4476 struct T_opthdr *toh; 4477 uint_t *dstptr; 4478 4479 toh = (struct T_opthdr *)dstopt; 4480 toh->level = IPPROTO_IP; 4481 toh->name = IP_RECVIF; 4482 toh->len = sizeof (struct T_opthdr) + 4483 sizeof (uint_t); 4484 toh->status = 0; 4485 dstopt += sizeof (struct T_opthdr); 4486 dstptr = (uint_t *)dstopt; 4487 *dstptr = pinfo->in_pkt_ifindex; 4488 dstopt += sizeof (uint_t); 4489 udi_size -= toh->len; 4490 } 4491 4492 if (cr != NULL) { 4493 struct T_opthdr *toh; 4494 4495 toh = (struct T_opthdr *)dstopt; 4496 toh->level = SOL_SOCKET; 4497 toh->name = SCM_UCRED; 4498 toh->len = sizeof (struct T_opthdr) + ucredsize; 4499 toh->status = 0; 4500 (void) cred2ucred(cr, cpid, &toh[1]); 4501 dstopt += toh->len; 4502 udi_size -= toh->len; 4503 } 4504 4505 if (udp->udp_recvttl) { 4506 struct T_opthdr *toh; 4507 uint8_t *dstptr; 4508 4509 toh = (struct T_opthdr *)dstopt; 4510 toh->level = IPPROTO_IP; 4511 toh->name = IP_RECVTTL; 4512 toh->len = sizeof (struct T_opthdr) + 4513 sizeof (uint8_t); 4514 toh->status = 0; 4515 dstopt += sizeof (struct T_opthdr); 4516 dstptr = (uint8_t *)dstopt; 4517 *dstptr = ((ipha_t *)rptr)->ipha_ttl; 4518 dstopt += sizeof (uint8_t); 4519 udi_size -= toh->len; 4520 } 4521 4522 ASSERT(udi_size == 0); /* "Consumed" all of allocated space */ 4523 } 4524 BUMP_MIB(&udp_mib, udpInDatagrams); 4525 TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END, 4526 "udp_rput_other_end: q %p (%S)", q, "end"); 4527 if (options_mp != NULL) 4528 freeb(options_mp); 4529 putnext(q, mp); 4530 } 4531 4532 /* 4533 * Process a T_BIND_ACK 4534 */ 4535 static void 4536 udp_rput_bind_ack(queue_t *q, mblk_t *mp) 4537 { 4538 udp_t *udp = (udp_t *)q->q_ptr; 4539 mblk_t *mp1; 4540 ire_t *ire; 4541 struct T_bind_ack *tba; 4542 uchar_t *addrp; 4543 ipa_conn_t *ac; 4544 ipa6_conn_t *ac6; 4545 4546 if (udp->udp_discon_pending) 4547 udp->udp_discon_pending = 0; 4548 4549 /* 4550 * If a broadcast/multicast address was bound set 4551 * the source address to 0. 4552 * This ensures no datagrams with broadcast address 4553 * as source address are emitted (which would violate 4554 * RFC1122 - Hosts requirements) 4555 * 4556 * Note that when connecting the returned IRE is 4557 * for the destination address and we only perform 4558 * the broadcast check for the source address (it 4559 * is OK to connect to a broadcast/multicast address.) 4560 */ 4561 mp1 = mp->b_cont; 4562 if (mp1 != NULL && mp1->b_datap->db_type == IRE_DB_TYPE) { 4563 ire = (ire_t *)mp1->b_rptr; 4564 4565 /* 4566 * Note: we get IRE_BROADCAST for IPv6 to "mark" a multicast 4567 * local address. 4568 */ 4569 if (ire->ire_type == IRE_BROADCAST && 4570 udp->udp_state != TS_DATA_XFER) { 4571 /* This was just a local bind to a broadcast addr */ 4572 V6_SET_ZERO(udp->udp_v6src); 4573 if (udp->udp_family == AF_INET6) 4574 (void) udp_build_hdrs(q, udp); 4575 } else if (V6_OR_V4_INADDR_ANY(udp->udp_v6src)) { 4576 /* 4577 * Local address not yet set - pick it from the 4578 * T_bind_ack 4579 */ 4580 tba = (struct T_bind_ack *)mp->b_rptr; 4581 addrp = &mp->b_rptr[tba->ADDR_offset]; 4582 switch (udp->udp_family) { 4583 case AF_INET: 4584 if (tba->ADDR_length == sizeof (ipa_conn_t)) { 4585 ac = (ipa_conn_t *)addrp; 4586 } else { 4587 ASSERT(tba->ADDR_length == 4588 sizeof (ipa_conn_x_t)); 4589 ac = &((ipa_conn_x_t *)addrp)->acx_conn; 4590 } 4591 IN6_IPADDR_TO_V4MAPPED(ac->ac_laddr, 4592 &udp->udp_v6src); 4593 break; 4594 case AF_INET6: 4595 if (tba->ADDR_length == sizeof (ipa6_conn_t)) { 4596 ac6 = (ipa6_conn_t *)addrp; 4597 } else { 4598 ASSERT(tba->ADDR_length == 4599 sizeof (ipa6_conn_x_t)); 4600 ac6 = &((ipa6_conn_x_t *) 4601 addrp)->ac6x_conn; 4602 } 4603 udp->udp_v6src = ac6->ac6_laddr; 4604 (void) udp_build_hdrs(q, udp); 4605 break; 4606 } 4607 } 4608 mp1 = mp1->b_cont; 4609 } 4610 /* 4611 * Look for one or more appended ACK message added by 4612 * udp_connect or udp_disconnect. 4613 * If none found just send up the T_BIND_ACK. 4614 * udp_connect has appended a T_OK_ACK and a T_CONN_CON. 4615 * udp_disconnect has appended a T_OK_ACK. 4616 */ 4617 if (mp1 != NULL) { 4618 if (mp->b_cont == mp1) 4619 mp->b_cont = NULL; 4620 else { 4621 ASSERT(mp->b_cont->b_cont == mp1); 4622 mp->b_cont->b_cont = NULL; 4623 } 4624 freemsg(mp); 4625 mp = mp1; 4626 while (mp != NULL) { 4627 mp1 = mp->b_cont; 4628 mp->b_cont = NULL; 4629 putnext(q, mp); 4630 mp = mp1; 4631 } 4632 return; 4633 } 4634 freemsg(mp->b_cont); 4635 mp->b_cont = NULL; 4636 putnext(q, mp); 4637 } 4638 4639 /* 4640 * return SNMP stuff in buffer in mpdata 4641 */ 4642 static int 4643 udp_snmp_get(queue_t *q, mblk_t *mpctl) 4644 { 4645 mblk_t *mpdata; 4646 mblk_t *mp_conn_ctl; 4647 mblk_t *mp6_conn_ctl; 4648 mblk_t *mp_conn_data; 4649 mblk_t *mp6_conn_data; 4650 mblk_t *mp_conn_tail = NULL; 4651 mblk_t *mp6_conn_tail = NULL; 4652 struct opthdr *optp; 4653 IDP idp; 4654 udp_t *udp; 4655 mib2_udpEntry_t ude; 4656 mib2_udp6Entry_t ude6; 4657 int state; 4658 zoneid_t zoneid; 4659 4660 if (mpctl == NULL || 4661 (mpdata = mpctl->b_cont) == NULL || 4662 (mp_conn_ctl = copymsg(mpctl)) == NULL || 4663 (mp6_conn_ctl = copymsg(mpctl)) == NULL) { 4664 freemsg(mp_conn_ctl); 4665 return (0); 4666 } 4667 4668 mp_conn_data = mp_conn_ctl->b_cont; 4669 mp6_conn_data = mp6_conn_ctl->b_cont; 4670 4671 udp = (udp_t *)q->q_ptr; 4672 zoneid = udp->udp_zoneid; 4673 4674 /* fixed length structure for IPv4 and IPv6 counters */ 4675 SET_MIB(udp_mib.udpEntrySize, sizeof (mib2_udpEntry_t)); 4676 SET_MIB(udp_mib.udp6EntrySize, sizeof (mib2_udp6Entry_t)); 4677 optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 4678 optp->level = MIB2_UDP; 4679 optp->name = 0; 4680 (void) snmp_append_data(mpdata, (char *)&udp_mib, sizeof (udp_mib)); 4681 optp->len = msgdsize(mpdata); 4682 qreply(q, mpctl); 4683 4684 mutex_enter(&udp_g_lock); 4685 for (idp = mi_first_ptr(&udp_g_head); 4686 (udp = (udp_t *)idp) != 0; 4687 idp = mi_next_ptr(&udp_g_head, idp)) { 4688 4689 if (zoneid != udp->udp_zoneid) 4690 continue; 4691 4692 /* Note that the port numbers are sent in host byte order */ 4693 4694 if (udp->udp_state == TS_UNBND) 4695 state = MIB2_UDP_unbound; 4696 else if (udp->udp_state == TS_IDLE) 4697 state = MIB2_UDP_idle; 4698 else if (udp->udp_state == TS_DATA_XFER) 4699 state = MIB2_UDP_connected; 4700 else 4701 state = MIB2_UDP_unknown; 4702 4703 /* 4704 * Create an IPv4 table entry for IPv4 entries and also 4705 * any IPv6 entries which are bound to in6addr_any 4706 * (i.e. anything a IPv4 peer could connect/send to). 4707 */ 4708 if (udp->udp_ipversion == IPV4_VERSION || 4709 (udp->udp_state <= TS_IDLE && 4710 IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src))) { 4711 ude.udpEntryInfo.ue_state = state; 4712 /* If in6addr_any this will set it to INADDR_ANY */ 4713 ude.udpLocalAddress = V4_PART_OF_V6(udp->udp_v6src); 4714 ude.udpLocalPort = ntohs(udp->udp_port); 4715 if (udp->udp_state == TS_DATA_XFER) { 4716 /* 4717 * Can potentially get here for v6 socket 4718 * if another process (say, ping) has just 4719 * done a sendto(), changing the state 4720 * from the TS_IDLE above to TS_DATA_XFER 4721 * by the time we hit this part of the code. 4722 */ 4723 ude.udpEntryInfo.ue_RemoteAddress = 4724 V4_PART_OF_V6(udp->udp_v6dst); 4725 ude.udpEntryInfo.ue_RemotePort = 4726 ntohs(udp->udp_dstport); 4727 } else { 4728 ude.udpEntryInfo.ue_RemoteAddress = 0; 4729 ude.udpEntryInfo.ue_RemotePort = 0; 4730 } 4731 (void) snmp_append_data2(mp_conn_data, &mp_conn_tail, 4732 (char *)&ude, sizeof (ude)); 4733 } 4734 if (udp->udp_ipversion == IPV6_VERSION) { 4735 ude6.udp6EntryInfo.ue_state = state; 4736 ude6.udp6LocalAddress = udp->udp_v6src; 4737 ude6.udp6LocalPort = ntohs(udp->udp_port); 4738 ude6.udp6IfIndex = udp->udp_bound_if; 4739 if (udp->udp_state == TS_DATA_XFER) { 4740 ude6.udp6EntryInfo.ue_RemoteAddress = 4741 udp->udp_v6dst; 4742 ude6.udp6EntryInfo.ue_RemotePort = 4743 ntohs(udp->udp_dstport); 4744 } else { 4745 ude6.udp6EntryInfo.ue_RemoteAddress = 4746 sin6_null.sin6_addr; 4747 ude6.udp6EntryInfo.ue_RemotePort = 0; 4748 } 4749 (void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail, 4750 (char *)&ude6, sizeof (ude6)); 4751 } 4752 } 4753 mutex_exit(&udp_g_lock); 4754 4755 /* IPv4 UDP endpoints */ 4756 optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 4757 sizeof (struct T_optmgmt_ack)]; 4758 optp->level = MIB2_UDP; 4759 optp->name = MIB2_UDP_ENTRY; 4760 optp->len = msgdsize(mp_conn_data); 4761 qreply(q, mp_conn_ctl); 4762 4763 /* IPv6 UDP endpoints */ 4764 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 4765 sizeof (struct T_optmgmt_ack)]; 4766 optp->level = MIB2_UDP6; 4767 optp->name = MIB2_UDP6_ENTRY; 4768 optp->len = msgdsize(mp6_conn_data); 4769 qreply(q, mp6_conn_ctl); 4770 4771 return (1); 4772 } 4773 4774 /* 4775 * Return 0 if invalid set request, 1 otherwise, including non-udp requests. 4776 * NOTE: Per MIB-II, UDP has no writable data. 4777 * TODO: If this ever actually tries to set anything, it needs to be 4778 * to do the appropriate locking. 4779 */ 4780 /* ARGSUSED */ 4781 static int 4782 udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name, 4783 uchar_t *ptr, int len) 4784 { 4785 switch (level) { 4786 case MIB2_UDP: 4787 return (0); 4788 default: 4789 return (1); 4790 } 4791 } 4792 4793 static void 4794 udp_report_item(mblk_t *mp, udp_t *udp) 4795 { 4796 char *state; 4797 char addrbuf1[INET6_ADDRSTRLEN]; 4798 char addrbuf2[INET6_ADDRSTRLEN]; 4799 uint_t print_len, buf_len; 4800 4801 buf_len = mp->b_datap->db_lim - mp->b_wptr; 4802 ASSERT(buf_len >= 0); 4803 if (buf_len == 0) 4804 return; 4805 4806 if (udp->udp_state == TS_UNBND) 4807 state = "UNBOUND"; 4808 else if (udp->udp_state == TS_IDLE) 4809 state = "IDLE"; 4810 else if (udp->udp_state == TS_DATA_XFER) 4811 state = "CONNECTED"; 4812 else 4813 state = "UnkState"; 4814 print_len = snprintf((char *)mp->b_wptr, buf_len, 4815 MI_COL_PTRFMT_STR "%4d %5u %s %s %5u %s\n", 4816 (void *)udp, udp->udp_zoneid, ntohs(udp->udp_port), 4817 inet_ntop(AF_INET6, &udp->udp_v6src, 4818 addrbuf1, sizeof (addrbuf1)), 4819 inet_ntop(AF_INET6, &udp->udp_v6dst, 4820 addrbuf2, sizeof (addrbuf2)), 4821 ntohs(udp->udp_dstport), state); 4822 if (print_len < buf_len) { 4823 mp->b_wptr += print_len; 4824 } else { 4825 mp->b_wptr += buf_len; 4826 } 4827 } 4828 4829 /* Report for ndd "udp_status" */ 4830 /* ARGSUSED */ 4831 static int 4832 udp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) 4833 { 4834 IDP idp; 4835 udp_t *udp; 4836 zoneid_t zoneid; 4837 4838 /* 4839 * Because of the ndd constraint, at most we can have 64K buffer 4840 * to put in all UDP info. So to be more efficient, just 4841 * allocate a 64K buffer here, assuming we need that large buffer. 4842 * This may be a problem as any user can read udp_status. Therefore 4843 * we limit the rate of doing this using udp_ndd_get_info_interval. 4844 * This should be OK as normal users should not do this too often. 4845 */ 4846 if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) { 4847 if (ddi_get_lbolt() - udp_last_ndd_get_info_time < 4848 drv_usectohz(udp_ndd_get_info_interval * 1000)) { 4849 (void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG); 4850 return (0); 4851 } 4852 } 4853 if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) { 4854 /* The following may work even if we cannot get a large buf. */ 4855 (void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG); 4856 return (0); 4857 } 4858 (void) mi_mpprintf(mp, 4859 "UDP " MI_COL_HDRPAD_STR 4860 /* 12345678[89ABCDEF] */ 4861 " zone lport src addr dest addr port state"); 4862 /* 1234 12345 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx 12345 UNBOUND */ 4863 4864 udp = (udp_t *)q->q_ptr; 4865 zoneid = udp->udp_zoneid; 4866 4867 mutex_enter(&udp_g_lock); 4868 for (idp = mi_first_ptr(&udp_g_head); 4869 (udp = (udp_t *)idp) != 0; 4870 idp = mi_next_ptr(&udp_g_head, idp)) { 4871 4872 if (zoneid != GLOBAL_ZONEID && 4873 zoneid != udp->udp_zoneid) 4874 continue; 4875 4876 udp_report_item(mp->b_cont, udp); 4877 } 4878 mutex_exit(&udp_g_lock); 4879 udp_last_ndd_get_info_time = ddi_get_lbolt(); 4880 return (0); 4881 } 4882 4883 /* 4884 * This routine creates a T_UDERROR_IND message and passes it upstream. 4885 * The address and options are copied from the T_UNITDATA_REQ message 4886 * passed in mp. This message is freed. 4887 */ 4888 static void 4889 udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err) 4890 { 4891 mblk_t *mp1; 4892 struct T_unitdata_req *tudr = (struct T_unitdata_req *)mp->b_rptr; 4893 uchar_t *destaddr, *optaddr; 4894 4895 if ((mp->b_wptr < mp->b_rptr) || 4896 (mp->b_wptr - mp->b_rptr) < sizeof (struct T_unitdata_req)) { 4897 goto done; 4898 } 4899 destaddr = mp->b_rptr + tudr->DEST_offset; 4900 if (destaddr < mp->b_rptr || destaddr >= mp->b_wptr || 4901 destaddr + tudr->DEST_length < mp->b_rptr || 4902 destaddr + tudr->DEST_length > mp->b_wptr) { 4903 goto done; 4904 } 4905 optaddr = mp->b_rptr + tudr->OPT_offset; 4906 if (optaddr < mp->b_rptr || optaddr >= mp->b_wptr || 4907 optaddr + tudr->OPT_length < mp->b_rptr || 4908 optaddr + tudr->OPT_length > mp->b_wptr) { 4909 goto done; 4910 } 4911 mp1 = mi_tpi_uderror_ind((char *)destaddr, tudr->DEST_length, 4912 (char *)optaddr, tudr->OPT_length, err); 4913 if (mp1) 4914 qreply(q, mp1); 4915 4916 done: 4917 freemsg(mp); 4918 } 4919 4920 /* 4921 * This routine removes a port number association from a stream. It 4922 * is called by udp_wput to handle T_UNBIND_REQ messages. 4923 */ 4924 static void 4925 udp_unbind(queue_t *q, mblk_t *mp) 4926 { 4927 udp_t *udp; 4928 4929 udp = (udp_t *)q->q_ptr; 4930 /* If a bind has not been done, we can't unbind. */ 4931 if (udp->udp_state == TS_UNBND) { 4932 udp_err_ack(q, mp, TOUTSTATE, 0); 4933 return; 4934 } 4935 if (cl_inet_unbind != NULL) { 4936 /* 4937 * Running in cluster mode - register unbind information 4938 */ 4939 if (udp->udp_ipversion == IPV4_VERSION) { 4940 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET, 4941 (uint8_t *)(&V4_PART_OF_V6(udp->udp_v6src)), 4942 (in_port_t)udp->udp_port); 4943 } else { 4944 (*cl_inet_unbind)(IPPROTO_UDP, AF_INET6, 4945 (uint8_t *)&(udp->udp_v6src), 4946 (in_port_t)udp->udp_port); 4947 } 4948 } 4949 4950 udp_bind_hash_remove(udp, B_FALSE); 4951 V6_SET_ZERO(udp->udp_v6src); 4952 V6_SET_ZERO(udp->udp_bound_v6src); 4953 udp->udp_port = 0; 4954 udp->udp_state = TS_UNBND; 4955 4956 if (udp->udp_family == AF_INET6) { 4957 int error; 4958 4959 /* Rebuild the header template */ 4960 error = udp_build_hdrs(q, udp); 4961 if (error != 0) { 4962 udp_err_ack(q, mp, TSYSERR, error); 4963 return; 4964 } 4965 } 4966 /* Pass the unbind to IP */ 4967 putnext(q, mp); 4968 } 4969 4970 /* 4971 * Don't let port fall into the privileged range. 4972 * Since the extra priviledged ports can be arbitrary we also 4973 * ensure that we exclude those from consideration. 4974 * udp_g_epriv_ports is not sorted thus we loop over it until 4975 * there are no changes. 4976 */ 4977 static in_port_t 4978 udp_update_next_port(in_port_t port, boolean_t random) 4979 { 4980 int i; 4981 4982 if (random && udp_random_anon_port != 0) { 4983 (void) random_get_pseudo_bytes((uint8_t *)&port, 4984 sizeof (in_port_t)); 4985 /* 4986 * Unless changed by a sys admin, the smallest anon port 4987 * is 32768 and the largest anon port is 65535. It is 4988 * very likely (50%) for the random port to be smaller 4989 * than the smallest anon port. When that happens, 4990 * add port % (anon port range) to the smallest anon 4991 * port to get the random port. It should fall into the 4992 * valid anon port range. 4993 */ 4994 if (port < udp_smallest_anon_port) { 4995 port = udp_smallest_anon_port + 4996 port % (udp_largest_anon_port - 4997 udp_smallest_anon_port); 4998 } 4999 } 5000 5001 retry: 5002 if (port < udp_smallest_anon_port || port > udp_largest_anon_port) 5003 port = udp_smallest_anon_port; 5004 5005 if (port < udp_smallest_nonpriv_port) 5006 port = udp_smallest_nonpriv_port; 5007 5008 for (i = 0; i < udp_g_num_epriv_ports; i++) { 5009 if (port == udp_g_epriv_ports[i]) { 5010 port++; 5011 /* 5012 * Make sure that the port is in the 5013 * valid range. 5014 */ 5015 goto retry; 5016 } 5017 } 5018 return (port); 5019 } 5020 5021 /* 5022 * This routine handles all messages passed downstream. It either 5023 * consumes the message or passes it downstream; it never queues a 5024 * a message. 5025 */ 5026 static void 5027 udp_wput(queue_t *q, mblk_t *mp) 5028 { 5029 uchar_t *rptr = mp->b_rptr; 5030 struct datab *db; 5031 ipha_t *ipha; 5032 udpha_t *udpha; 5033 mblk_t *mp1; 5034 int ip_hdr_length; 5035 #define tudr ((struct T_unitdata_req *)rptr) 5036 uint32_t ip_len; 5037 udp_t *udp; 5038 sin6_t *sin6; 5039 sin_t *sin; 5040 ipaddr_t v4dst; 5041 uint16_t port; 5042 uint_t srcid; 5043 5044 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_START, 5045 "udp_wput_start: q %p mp %p", q, mp); 5046 5047 db = mp->b_datap; 5048 switch (db->db_type) { 5049 case M_PROTO: 5050 case M_PCPROTO: 5051 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 5052 if (mp->b_wptr - rptr >= sizeof (struct T_unitdata_req)) { 5053 /* Detect valid T_UNITDATA_REQ here */ 5054 if (((union T_primitives *)rptr)->type 5055 == T_UNITDATA_REQ) 5056 break; 5057 } 5058 /* FALLTHRU */ 5059 default: 5060 qwriter(q, mp, udp_wput_other, PERIM_INNER); 5061 return; 5062 } 5063 5064 udp = (udp_t *)q->q_ptr; 5065 5066 /* Handle UNITDATA_REQ messages here */ 5067 if (udp->udp_state == TS_UNBND) { 5068 /* If a port has not been bound to the stream, fail. */ 5069 BUMP_MIB(&udp_mib, udpOutErrors); 5070 udp_ud_err(q, mp, EPROTO); 5071 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5072 "udp_wput_end: q %p (%S)", q, "outstate"); 5073 return; 5074 } 5075 mp1 = mp->b_cont; 5076 if (mp1 == NULL) { 5077 BUMP_MIB(&udp_mib, udpOutErrors); 5078 udp_ud_err(q, mp, EPROTO); 5079 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5080 "udp_wput_end: q %p (%S)", q, "badaddr"); 5081 return; 5082 } 5083 5084 if ((rptr + tudr->DEST_offset + tudr->DEST_length) > mp->b_wptr) { 5085 BUMP_MIB(&udp_mib, udpOutErrors); 5086 udp_ud_err(q, mp, EADDRNOTAVAIL); 5087 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5088 "udp_wput_end: q %p (%S)", q, "badaddr"); 5089 return; 5090 } 5091 5092 switch (udp->udp_family) { 5093 case AF_INET6: 5094 sin6 = (sin6_t *)&rptr[tudr->DEST_offset]; 5095 if (!OK_32PTR((char *)sin6) || 5096 tudr->DEST_length != sizeof (sin6_t) || 5097 sin6->sin6_family != AF_INET6) { 5098 BUMP_MIB(&udp_mib, udpOutErrors); 5099 udp_ud_err(q, mp, EADDRNOTAVAIL); 5100 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5101 "udp_wput_end: q %p (%S)", q, "badaddr"); 5102 return; 5103 } 5104 5105 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 5106 /* 5107 * Destination is a non-IPv4-compatible IPv6 address. 5108 * Send out an IPv6 format packet. 5109 */ 5110 udp_wput_ipv6(q, mp, sin6, tudr->OPT_length); 5111 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5112 "udp_wput_end: q %p (%S)", q, "udp_wput_ipv6"); 5113 return; 5114 } 5115 /* 5116 * If the local address is not zero or a mapped address return 5117 * an error. 5118 * I would be possible to send an IPv4 packet but the 5119 * response would never make it back to the application 5120 * since it is bound to a non-mapped address. 5121 */ 5122 if (!IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src) && 5123 !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 5124 BUMP_MIB(&udp_mib, udpOutErrors); 5125 udp_ud_err(q, mp, EADDRNOTAVAIL); 5126 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5127 "udp_wput_end: q %p (%S)", q, "badaddr"); 5128 return; 5129 } 5130 /* Send IPv4 packet without modifying udp_ipversion */ 5131 /* Extract port and ipaddr */ 5132 port = sin6->sin6_port; 5133 IN6_V4MAPPED_TO_IPADDR(&sin6->sin6_addr, v4dst); 5134 srcid = sin6->__sin6_src_id; 5135 break; 5136 5137 case AF_INET: 5138 sin = (sin_t *)&rptr[tudr->DEST_offset]; 5139 if (!OK_32PTR((char *)sin) || 5140 tudr->DEST_length != sizeof (sin_t) || 5141 sin->sin_family != AF_INET) { 5142 BUMP_MIB(&udp_mib, udpOutErrors); 5143 udp_ud_err(q, mp, EADDRNOTAVAIL); 5144 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5145 "udp_wput_end: q %p (%S)", q, "badaddr"); 5146 return; 5147 } 5148 /* Extract port and ipaddr */ 5149 port = sin->sin_port; 5150 v4dst = sin->sin_addr.s_addr; 5151 srcid = 0; 5152 break; 5153 } 5154 5155 5156 /* 5157 * If options passed in, feed it for verification and handling 5158 */ 5159 if (tudr->OPT_length != 0) { 5160 int error; 5161 5162 if (udp_unitdata_opt_process(q, mp, &error, NULL) < 0) { 5163 /* failure */ 5164 BUMP_MIB(&udp_mib, udpOutErrors); 5165 udp_ud_err(q, mp, error); 5166 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5167 "udp_wput_end: q %p (%S)", q, 5168 "udp_unitdata_opt_process"); 5169 return; 5170 } 5171 ASSERT(error == 0); 5172 /* 5173 * Note: success in processing options. 5174 * mp option buffer represented by 5175 * OPT_length/offset now potentially modified 5176 * and contain option setting results 5177 */ 5178 } 5179 5180 /* Add an IP header */ 5181 ip_hdr_length = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE + 5182 udp->udp_ip_snd_options_len; 5183 ipha = (ipha_t *)&mp1->b_rptr[-ip_hdr_length]; 5184 if ((mp1->b_datap->db_ref != 1) || 5185 ((uchar_t *)ipha < mp1->b_datap->db_base) || 5186 !OK_32PTR(ipha)) { 5187 uchar_t *wptr; 5188 5189 mp1 = allocb(ip_hdr_length + udp_wroff_extra, BPRI_LO); 5190 if (!mp1) { 5191 BUMP_MIB(&udp_mib, udpOutErrors); 5192 udp_ud_err(q, mp, ENOMEM); 5193 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5194 "udp_wput_end: q %p (%S)", q, "allocbfail2"); 5195 return; 5196 } 5197 mp1->b_cont = mp->b_cont; 5198 mp->b_cont = mp1; 5199 wptr = mp1->b_datap->db_lim; 5200 mp1->b_wptr = wptr; 5201 ipha = (ipha_t *)(wptr - ip_hdr_length); 5202 } 5203 mp1->b_rptr = (uchar_t *)ipha; 5204 5205 ASSERT((uintptr_t)(mp1->b_wptr - (uchar_t *)ipha) <= 5206 (uintptr_t)UINT_MAX); 5207 5208 ip_hdr_length -= UDPH_SIZE; 5209 #ifdef _BIG_ENDIAN 5210 /* Set version, header length, and tos */ 5211 *(uint16_t *)&ipha->ipha_version_and_hdr_length = 5212 ((((IP_VERSION << 4) | (ip_hdr_length>>2)) << 8) | 5213 udp->udp_type_of_service); 5214 /* Set ttl and protocol */ 5215 *(uint16_t *)&ipha->ipha_ttl = (udp->udp_ttl << 8) | IPPROTO_UDP; 5216 #else 5217 /* Set version, header length, and tos */ 5218 *(uint16_t *)&ipha->ipha_version_and_hdr_length = 5219 ((udp->udp_type_of_service << 8) | 5220 ((IP_VERSION << 4) | (ip_hdr_length>>2))); 5221 /* Set ttl and protocol */ 5222 *(uint16_t *)&ipha->ipha_ttl = (IPPROTO_UDP << 8) | udp->udp_ttl; 5223 #endif 5224 /* 5225 * Copy our address into the packet. If this is zero, 5226 * first look at __sin6_src_id for a hint. If we leave the source 5227 * as INADDR_ANY then ip will fill in the real source address. 5228 */ 5229 IN6_V4MAPPED_TO_IPADDR(&udp->udp_v6src, ipha->ipha_src); 5230 if (srcid != 0 && ipha->ipha_src == INADDR_ANY) { 5231 in6_addr_t v6src; 5232 5233 ip_srcid_find_id(srcid, &v6src, udp->udp_zoneid); 5234 IN6_V4MAPPED_TO_IPADDR(&v6src, ipha->ipha_src); 5235 } 5236 5237 ipha->ipha_fragment_offset_and_flags = 0; 5238 ipha->ipha_ident = 0; 5239 5240 /* Determine length of packet */ 5241 ip_len = (uint32_t)(mp1->b_wptr - (uchar_t *)ipha); 5242 { 5243 mblk_t *mp2; 5244 if ((mp2 = mp1->b_cont) != NULL) { 5245 do { 5246 ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) 5247 <= (uintptr_t)UINT_MAX); 5248 ip_len += (uint32_t)(mp2->b_wptr - mp2->b_rptr); 5249 } while ((mp2 = mp2->b_cont) != NULL); 5250 } 5251 } 5252 /* 5253 * If the size of the packet is greater than the maximum allowed by 5254 * ip, return an error. Passing this down could cause panics because 5255 * the size will have wrapped and be inconsistent with the msg size. 5256 */ 5257 if (ip_len > IP_MAXPACKET) { 5258 BUMP_MIB(&udp_mib, udpOutErrors); 5259 udp_ud_err(q, mp, EMSGSIZE); 5260 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5261 "udp_wput_end: q %p (%S)", q, "IP length exceeded"); 5262 return; 5263 } 5264 ipha->ipha_length = htons((uint16_t)ip_len); 5265 ip_len -= ip_hdr_length; 5266 ip_len = htons((uint16_t)ip_len); 5267 udpha = (udpha_t *)(((uchar_t *)ipha) + ip_hdr_length); 5268 /* 5269 * Copy in the destination address and port from the T_UNITDATA 5270 * request 5271 */ 5272 if (v4dst == INADDR_ANY) 5273 ipha->ipha_dst = htonl(INADDR_LOOPBACK); 5274 else 5275 ipha->ipha_dst = v4dst; 5276 5277 /* 5278 * Set ttl based on IP_MULTICAST_TTL to match IPv6 logic. 5279 */ 5280 if (CLASSD(v4dst)) 5281 ipha->ipha_ttl = udp->udp_multicast_ttl; 5282 5283 udpha->uha_dst_port = port; 5284 udpha->uha_src_port = udp->udp_port; 5285 5286 if (ip_hdr_length > IP_SIMPLE_HDR_LENGTH) { 5287 uint32_t cksum; 5288 5289 bcopy(udp->udp_ip_snd_options, &ipha[1], 5290 udp->udp_ip_snd_options_len); 5291 /* 5292 * Massage source route putting first source route in ipha_dst. 5293 * Ignore the destination in T_unitdata_req. 5294 * Create a checksum adjustment for a source route, if any. 5295 */ 5296 cksum = ip_massage_options(ipha); 5297 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5298 cksum -= ((ipha->ipha_dst >> 16) & 0xFFFF) + 5299 (ipha->ipha_dst & 0xFFFF); 5300 if ((int)cksum < 0) 5301 cksum--; 5302 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5303 /* 5304 * IP does the checksum if uha_checksum is non-zero, 5305 * We make it easy for IP to include our pseudo header 5306 * by putting our length in uha_checksum. 5307 */ 5308 cksum += ip_len; 5309 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5310 /* There might be a carry. */ 5311 cksum = (cksum & 0xFFFF) + (cksum >> 16); 5312 #ifdef _LITTLE_ENDIAN 5313 if (udp_do_checksum) 5314 ip_len = (cksum << 16) | ip_len; 5315 #else 5316 if (udp_do_checksum) 5317 ip_len = (ip_len << 16) | cksum; 5318 else 5319 ip_len <<= 16; 5320 #endif 5321 } else { 5322 /* 5323 * IP does the checksum if uha_checksum is non-zero, 5324 * We make it easy for IP to include our pseudo header 5325 * by putting our length in uha_checksum. 5326 */ 5327 if (udp_do_checksum) 5328 ip_len |= (ip_len << 16); 5329 #ifndef _LITTLE_ENDIAN 5330 else 5331 ip_len <<= 16; 5332 #endif 5333 } 5334 /* Set UDP length and checksum */ 5335 *((uint32_t *)&udpha->uha_length) = ip_len; 5336 5337 freeb(mp); 5338 5339 /* We're done. Pass the packet to ip. */ 5340 BUMP_MIB(&udp_mib, udpOutDatagrams); 5341 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END, 5342 "udp_wput_end: q %p (%S)", q, "end"); 5343 putnext(q, mp1); 5344 #undef tudr 5345 } 5346 5347 /* 5348 * udp_wput_ipv6(): 5349 * Assumes that udp_wput did some sanity checking on the destination 5350 * address. 5351 */ 5352 static void 5353 udp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6, t_scalar_t tudr_optlen) 5354 { 5355 ip6_t *ip6h; 5356 ip6i_t *ip6i; /* mp1->b_rptr even if no ip6i_t */ 5357 mblk_t *mp1; 5358 int udp_ip_hdr_len = IPV6_HDR_LEN + UDPH_SIZE; 5359 size_t ip_len; 5360 udpha_t *udph; 5361 udp_t *udp; 5362 ip6_pkt_t ipp_s; /* For ancillary data options */ 5363 ip6_pkt_t *ipp = &ipp_s; 5364 ip6_pkt_t *tipp; /* temporary ipp */ 5365 uint32_t csum = 0; 5366 uint_t ignore = 0; 5367 uint_t option_exists = 0, is_sticky = 0; 5368 uint8_t *cp; 5369 uint8_t *nxthdr_ptr; 5370 5371 udp = (udp_t *)q->q_ptr; 5372 5373 /* 5374 * If the local address is a mapped address return 5375 * an error. 5376 * It would be possible to send an IPv6 packet but the 5377 * response would never make it back to the application 5378 * since it is bound to a mapped address. 5379 */ 5380 if (IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src)) { 5381 BUMP_MIB(&udp_mib, udpOutErrors); 5382 udp_ud_err(q, mp, EADDRNOTAVAIL); 5383 return; 5384 } 5385 5386 ipp->ipp_fields = 0; 5387 ipp->ipp_sticky_ignored = 0; 5388 5389 /* 5390 * If TPI options passed in, feed it for verification and handling 5391 */ 5392 if (tudr_optlen != 0) { 5393 int error; 5394 5395 if (udp_unitdata_opt_process(q, mp, &error, 5396 (void *)ipp) < 0) { 5397 /* failure */ 5398 BUMP_MIB(&udp_mib, udpOutErrors); 5399 udp_ud_err(q, mp, error); 5400 return; 5401 } 5402 ignore = ipp->ipp_sticky_ignored; 5403 ASSERT(error == 0); 5404 } 5405 5406 if (sin6->sin6_scope_id != 0 && 5407 IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5408 /* 5409 * IPPF_SCOPE_ID is special. It's neither a sticky 5410 * option nor ancillary data. It needs to be 5411 * explicitly set in options_exists. 5412 */ 5413 option_exists |= IPPF_SCOPE_ID; 5414 } 5415 5416 if ((udp->udp_sticky_ipp.ipp_fields == 0) && 5417 (ipp->ipp_fields == 0)) { 5418 /* No sticky options nor ancillary data. */ 5419 goto no_options; 5420 } 5421 5422 /* 5423 * Go through the options figuring out where each is going to 5424 * come from and build two masks. The first mask indicates if 5425 * the option exists at all. The second mask indicates if the 5426 * option is sticky or ancillary. 5427 */ 5428 if (!(ignore & IPPF_HOPOPTS)) { 5429 if (ipp->ipp_fields & IPPF_HOPOPTS) { 5430 option_exists |= IPPF_HOPOPTS; 5431 udp_ip_hdr_len += ipp->ipp_hopoptslen; 5432 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) { 5433 option_exists |= IPPF_HOPOPTS; 5434 is_sticky |= IPPF_HOPOPTS; 5435 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_hopoptslen; 5436 } 5437 } 5438 5439 if (!(ignore & IPPF_RTHDR)) { 5440 if (ipp->ipp_fields & IPPF_RTHDR) { 5441 option_exists |= IPPF_RTHDR; 5442 udp_ip_hdr_len += ipp->ipp_rthdrlen; 5443 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) { 5444 option_exists |= IPPF_RTHDR; 5445 is_sticky |= IPPF_RTHDR; 5446 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rthdrlen; 5447 } 5448 } 5449 5450 if (!(ignore & IPPF_RTDSTOPTS) && (option_exists & IPPF_RTHDR)) { 5451 if (ipp->ipp_fields & IPPF_RTDSTOPTS) { 5452 option_exists |= IPPF_RTDSTOPTS; 5453 udp_ip_hdr_len += ipp->ipp_rtdstoptslen; 5454 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) { 5455 option_exists |= IPPF_RTDSTOPTS; 5456 is_sticky |= IPPF_RTDSTOPTS; 5457 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rtdstoptslen; 5458 } 5459 } 5460 5461 if (!(ignore & IPPF_DSTOPTS)) { 5462 if (ipp->ipp_fields & IPPF_DSTOPTS) { 5463 option_exists |= IPPF_DSTOPTS; 5464 udp_ip_hdr_len += ipp->ipp_dstoptslen; 5465 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) { 5466 option_exists |= IPPF_DSTOPTS; 5467 is_sticky |= IPPF_DSTOPTS; 5468 udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_dstoptslen; 5469 } 5470 } 5471 5472 if (!(ignore & IPPF_IFINDEX)) { 5473 if (ipp->ipp_fields & IPPF_IFINDEX) { 5474 option_exists |= IPPF_IFINDEX; 5475 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_IFINDEX) { 5476 option_exists |= IPPF_IFINDEX; 5477 is_sticky |= IPPF_IFINDEX; 5478 } 5479 } 5480 5481 if (!(ignore & IPPF_ADDR)) { 5482 if (ipp->ipp_fields & IPPF_ADDR) { 5483 option_exists |= IPPF_ADDR; 5484 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_ADDR) { 5485 option_exists |= IPPF_ADDR; 5486 is_sticky |= IPPF_ADDR; 5487 } 5488 } 5489 5490 if (!(ignore & IPPF_DONTFRAG)) { 5491 if (ipp->ipp_fields & IPPF_DONTFRAG) { 5492 option_exists |= IPPF_DONTFRAG; 5493 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DONTFRAG) { 5494 option_exists |= IPPF_DONTFRAG; 5495 is_sticky |= IPPF_DONTFRAG; 5496 } 5497 } 5498 5499 if (!(ignore & IPPF_USE_MIN_MTU)) { 5500 if (ipp->ipp_fields & IPPF_USE_MIN_MTU) { 5501 option_exists |= IPPF_USE_MIN_MTU; 5502 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_USE_MIN_MTU) { 5503 option_exists |= IPPF_USE_MIN_MTU; 5504 is_sticky |= IPPF_USE_MIN_MTU; 5505 } 5506 } 5507 5508 if (!(ignore & IPPF_HOPLIMIT)) { 5509 if (ipp->ipp_fields & IPPF_HOPLIMIT) { 5510 option_exists |= IPPF_HOPLIMIT; 5511 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPLIMIT) { 5512 option_exists |= IPPF_HOPLIMIT; 5513 is_sticky |= IPPF_HOPLIMIT; 5514 } 5515 } 5516 5517 if (!(ignore & IPPF_TCLASS)) { 5518 if (ipp->ipp_fields & IPPF_TCLASS) { 5519 option_exists |= IPPF_TCLASS; 5520 } else if (udp->udp_sticky_ipp.ipp_fields & IPPF_TCLASS) { 5521 option_exists |= IPPF_TCLASS; 5522 is_sticky |= IPPF_TCLASS; 5523 } 5524 } 5525 5526 no_options: 5527 5528 /* 5529 * If any options carried in the ip6i_t were specified, we 5530 * need to account for the ip6i_t in the data we'll be sending 5531 * down. 5532 */ 5533 if (option_exists & IPPF_HAS_IP6I) 5534 udp_ip_hdr_len += sizeof (ip6i_t); 5535 5536 /* check/fix buffer config, setup pointers into it */ 5537 mp1 = mp->b_cont; 5538 ip6h = (ip6_t *)&mp1->b_rptr[-udp_ip_hdr_len]; 5539 if ((mp1->b_datap->db_ref != 1) || 5540 ((unsigned char *)ip6h < mp1->b_datap->db_base) || 5541 !OK_32PTR(ip6h)) { 5542 /* Try to get everything in a single mblk next time */ 5543 if (udp_ip_hdr_len > udp->udp_max_hdr_len) { 5544 udp->udp_max_hdr_len = udp_ip_hdr_len; 5545 (void) mi_set_sth_wroff(RD(q), 5546 udp->udp_max_hdr_len + udp_wroff_extra); 5547 } 5548 mp1 = allocb(udp_ip_hdr_len + udp_wroff_extra, BPRI_LO); 5549 if (!mp1) { 5550 BUMP_MIB(&udp_mib, udpOutErrors); 5551 udp_ud_err(q, mp, ENOMEM); 5552 return; 5553 } 5554 mp1->b_cont = mp->b_cont; 5555 mp->b_cont = mp1; 5556 mp1->b_wptr = mp1->b_datap->db_lim; 5557 ip6h = (ip6_t *)(mp1->b_wptr - udp_ip_hdr_len); 5558 } 5559 mp1->b_rptr = (unsigned char *)ip6h; 5560 ip6i = (ip6i_t *)ip6h; 5561 5562 #define ANCIL_OR_STICKY_PTR(f) ((is_sticky & f) ? &udp->udp_sticky_ipp : ipp) 5563 if (option_exists & IPPF_HAS_IP6I) { 5564 ip6h = (ip6_t *)&ip6i[1]; 5565 ip6i->ip6i_flags = 0; 5566 ip6i->ip6i_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 5567 5568 /* sin6_scope_id takes precendence over IPPF_IFINDEX */ 5569 if (option_exists & IPPF_SCOPE_ID) { 5570 ip6i->ip6i_flags |= IP6I_IFINDEX; 5571 ip6i->ip6i_ifindex = sin6->sin6_scope_id; 5572 } else if (option_exists & IPPF_IFINDEX) { 5573 tipp = ANCIL_OR_STICKY_PTR(IPPF_IFINDEX); 5574 ASSERT(tipp->ipp_ifindex != 0); 5575 ip6i->ip6i_flags |= IP6I_IFINDEX; 5576 ip6i->ip6i_ifindex = tipp->ipp_ifindex; 5577 } 5578 5579 if (option_exists & IPPF_ADDR) { 5580 /* 5581 * Enable per-packet source address verification if 5582 * IPV6_PKTINFO specified the source address. 5583 * ip6_src is set in the transport's _wput function. 5584 */ 5585 ip6i->ip6i_flags |= IP6I_VERIFY_SRC; 5586 } 5587 5588 if (option_exists & IPPF_DONTFRAG) { 5589 ip6i->ip6i_flags |= IP6I_DONTFRAG; 5590 } 5591 5592 if (option_exists & IPPF_USE_MIN_MTU) { 5593 ip6i->ip6i_flags = IP6I_API_USE_MIN_MTU( 5594 ip6i->ip6i_flags, ipp->ipp_use_min_mtu); 5595 } 5596 5597 if (option_exists & IPPF_NEXTHOP) { 5598 tipp = ANCIL_OR_STICKY_PTR(IPPF_NEXTHOP); 5599 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_nexthop)); 5600 ip6i->ip6i_flags |= IP6I_NEXTHOP; 5601 ip6i->ip6i_nexthop = tipp->ipp_nexthop; 5602 } 5603 5604 /* 5605 * tell IP this is an ip6i_t private header 5606 */ 5607 ip6i->ip6i_nxt = IPPROTO_RAW; 5608 } 5609 5610 /* Initialize IPv6 header */ 5611 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 5612 bzero(&ip6h->ip6_src, sizeof (ip6h->ip6_src)); 5613 5614 if (option_exists & IPPF_HOPLIMIT) { 5615 tipp = ANCIL_OR_STICKY_PTR(IPPF_HOPLIMIT); 5616 ip6h->ip6_hops = tipp->ipp_hoplimit; 5617 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && 5618 (udp->udp_sticky_ipp.ipp_fields & IPPF_MULTI_HOPLIMIT)) { 5619 ip6h->ip6_hops = udp->udp_multicast_ttl; 5620 ip6i->ip6i_flags |= IP6I_HOPLIMIT; 5621 } else { 5622 ip6h->ip6_hops = udp->udp_ttl; 5623 } 5624 5625 if (option_exists & IPPF_ADDR) { 5626 tipp = ANCIL_OR_STICKY_PTR(IPPF_ADDR); 5627 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_addr)); 5628 ip6h->ip6_src = tipp->ipp_addr; 5629 } else { 5630 /* 5631 * The source address was not set using IPV6_PKTINFO. 5632 * First look at the bound source. 5633 * If unspecified fallback to __sin6_src_id. 5634 */ 5635 ip6h->ip6_src = udp->udp_v6src; 5636 if (sin6->__sin6_src_id != 0 && 5637 IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) { 5638 ip_srcid_find_id(sin6->__sin6_src_id, 5639 &ip6h->ip6_src, udp->udp_zoneid); 5640 } 5641 } 5642 5643 nxthdr_ptr = (uint8_t *)&ip6h->ip6_nxt; 5644 cp = (uint8_t *)&ip6h[1]; 5645 5646 /* 5647 * Here's where we have to start stringing together 5648 * any extension headers in the right order: 5649 * Hop-by-hop, destination, routing, and final destination opts. 5650 */ 5651 if (option_exists & IPPF_HOPOPTS) { 5652 /* Hop-by-hop options */ 5653 ip6_hbh_t *hbh = (ip6_hbh_t *)cp; 5654 tipp = ANCIL_OR_STICKY_PTR(IPPF_HOPOPTS); 5655 5656 *nxthdr_ptr = IPPROTO_HOPOPTS; 5657 nxthdr_ptr = &hbh->ip6h_nxt; 5658 5659 bcopy(tipp->ipp_hopopts, cp, tipp->ipp_hopoptslen); 5660 cp += tipp->ipp_hopoptslen; 5661 } 5662 /* 5663 * En-route destination options 5664 * Only do them if there's a routing header as well 5665 */ 5666 if (option_exists & IPPF_RTDSTOPTS) { 5667 ip6_dest_t *dst = (ip6_dest_t *)cp; 5668 tipp = ANCIL_OR_STICKY_PTR(IPPF_RTDSTOPTS); 5669 5670 *nxthdr_ptr = IPPROTO_DSTOPTS; 5671 nxthdr_ptr = &dst->ip6d_nxt; 5672 5673 bcopy(tipp->ipp_rtdstopts, cp, tipp->ipp_rtdstoptslen); 5674 cp += tipp->ipp_rtdstoptslen; 5675 } 5676 /* 5677 * Routing header next 5678 */ 5679 if (option_exists & IPPF_RTHDR) { 5680 ip6_rthdr_t *rt = (ip6_rthdr_t *)cp; 5681 tipp = ANCIL_OR_STICKY_PTR(IPPF_RTHDR); 5682 5683 *nxthdr_ptr = IPPROTO_ROUTING; 5684 nxthdr_ptr = &rt->ip6r_nxt; 5685 5686 bcopy(tipp->ipp_rthdr, cp, tipp->ipp_rthdrlen); 5687 cp += tipp->ipp_rthdrlen; 5688 } 5689 /* 5690 * Do ultimate destination options 5691 */ 5692 if (option_exists & IPPF_DSTOPTS) { 5693 ip6_dest_t *dest = (ip6_dest_t *)cp; 5694 tipp = ANCIL_OR_STICKY_PTR(IPPF_DSTOPTS); 5695 5696 *nxthdr_ptr = IPPROTO_DSTOPTS; 5697 nxthdr_ptr = &dest->ip6d_nxt; 5698 5699 bcopy(tipp->ipp_dstopts, cp, tipp->ipp_dstoptslen); 5700 cp += tipp->ipp_dstoptslen; 5701 } 5702 /* 5703 * Now set the last header pointer to the proto passed in 5704 */ 5705 ASSERT((int)(cp - (uint8_t *)ip6i) == (udp_ip_hdr_len - UDPH_SIZE)); 5706 *nxthdr_ptr = IPPROTO_UDP; 5707 5708 /* Update UDP header */ 5709 udph = (udpha_t *)((uchar_t *)ip6i + udp_ip_hdr_len - UDPH_SIZE); 5710 udph->uha_dst_port = sin6->sin6_port; 5711 udph->uha_src_port = udp->udp_port; 5712 5713 /* 5714 * Copy in the destination address 5715 */ 5716 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 5717 ip6h->ip6_dst = ipv6_loopback; 5718 else 5719 ip6h->ip6_dst = sin6->sin6_addr; 5720 5721 ip6h->ip6_vcf = 5722 (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) | 5723 (sin6->sin6_flowinfo & ~IPV6_VERS_AND_FLOW_MASK); 5724 5725 if (option_exists & IPPF_TCLASS) { 5726 tipp = ANCIL_OR_STICKY_PTR(IPPF_TCLASS); 5727 ip6h->ip6_vcf = IPV6_TCLASS_FLOW(ip6h->ip6_vcf, 5728 tipp->ipp_tclass); 5729 } 5730 5731 if (option_exists & IPPF_RTHDR) { 5732 ip6_rthdr_t *rth; 5733 5734 /* 5735 * Perform any processing needed for source routing. 5736 * We know that all extension headers will be in the same mblk 5737 * as the IPv6 header. 5738 */ 5739 rth = ip_find_rthdr_v6(ip6h, mp1->b_wptr); 5740 if (rth != NULL && rth->ip6r_segleft != 0) { 5741 if (rth->ip6r_type != IPV6_RTHDR_TYPE_0) { 5742 /* 5743 * Drop packet - only support Type 0 routing. 5744 * Notify the application as well. 5745 */ 5746 udp_ud_err(q, mp, EPROTO); 5747 BUMP_MIB(&udp_mib, udpOutErrors); 5748 return; 5749 } 5750 5751 /* 5752 * rth->ip6r_len is twice the number of 5753 * addresses in the header. Thus it must be even. 5754 */ 5755 if (rth->ip6r_len & 0x1) { 5756 udp_ud_err(q, mp, EPROTO); 5757 BUMP_MIB(&udp_mib, udpOutErrors); 5758 return; 5759 } 5760 /* 5761 * Shuffle the routing header and ip6_dst 5762 * addresses, and get the checksum difference 5763 * between the first hop (in ip6_dst) and 5764 * the destination (in the last routing hdr entry). 5765 */ 5766 csum = ip_massage_options_v6(ip6h, rth); 5767 /* 5768 * Verify that the first hop isn't a mapped address. 5769 * Routers along the path need to do this verification 5770 * for subsequent hops. 5771 */ 5772 if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst)) { 5773 udp_ud_err(q, mp, EADDRNOTAVAIL); 5774 BUMP_MIB(&udp_mib, udpOutErrors); 5775 return; 5776 } 5777 5778 cp += (rth->ip6r_len + 1)*8; 5779 } 5780 } 5781 5782 /* count up length of UDP packet */ 5783 ip_len = (mp1->b_wptr - (unsigned char *)ip6h) - IPV6_HDR_LEN; 5784 { 5785 mblk_t *mp2; 5786 5787 if ((mp2 = mp1->b_cont) != NULL) { 5788 do { 5789 ip_len += mp2->b_wptr - mp2->b_rptr; 5790 } while ((mp2 = mp2->b_cont) != NULL); 5791 } 5792 } 5793 5794 /* 5795 * If the size of the packet is greater than the maximum allowed by 5796 * ip, return an error. Passing this down could cause panics because 5797 * the size will have wrapped and be inconsistent with the msg size. 5798 */ 5799 if (ip_len > IP_MAXPACKET) { 5800 BUMP_MIB(&udp_mib, udpOutErrors); 5801 udp_ud_err(q, mp, EMSGSIZE); 5802 return; 5803 } 5804 5805 /* Store the UDP length. Subtract length of extension hdrs */ 5806 udph->uha_length = htons(ip_len + IPV6_HDR_LEN - 5807 (int)((uchar_t *)udph - (uchar_t *)ip6h)); 5808 5809 /* 5810 * We make it easy for IP to include our pseudo header 5811 * by putting our length in uh_checksum, modified (if 5812 * we have a routing header) by the checksum difference 5813 * between the ultimate destination and first hop addresses. 5814 * Note: UDP over IPv6 must always checksum the packet. 5815 */ 5816 csum += udph->uha_length; 5817 csum = (csum & 0xFFFF) + (csum >> 16); 5818 udph->uha_checksum = (uint16_t)csum; 5819 5820 #ifdef _LITTLE_ENDIAN 5821 ip_len = htons(ip_len); 5822 #endif 5823 ip6h->ip6_plen = ip_len; 5824 5825 freeb(mp); 5826 5827 /* We're done. Pass the packet to IP */ 5828 BUMP_MIB(&udp_mib, udpOutDatagrams); 5829 putnext(q, mp1); 5830 } 5831 5832 static void 5833 udp_wput_other(queue_t *q, mblk_t *mp) 5834 { 5835 uchar_t *rptr = mp->b_rptr; 5836 struct datab *db; 5837 struct iocblk *iocp; 5838 udp_t *udp; 5839 cred_t *cr; 5840 5841 TRACE_1(TR_FAC_UDP, TR_UDP_WPUT_OTHER_START, 5842 "udp_wput_other_start: q %p", q); 5843 5844 udp = (udp_t *)q->q_ptr; 5845 db = mp->b_datap; 5846 5847 cr = DB_CREDDEF(mp, udp->udp_credp); 5848 5849 switch (db->db_type) { 5850 case M_DATA: 5851 /* Not connected */ 5852 BUMP_MIB(&udp_mib, udpOutErrors); 5853 freemsg(mp); 5854 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5855 "udp_wput_other_end: q %p (%S)", 5856 q, "not-connected"); 5857 return; 5858 case M_PROTO: 5859 case M_PCPROTO: 5860 if (mp->b_wptr - rptr < sizeof (t_scalar_t)) { 5861 freemsg(mp); 5862 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5863 "udp_wput_other_end: q %p (%S)", 5864 q, "protoshort"); 5865 return; 5866 } 5867 switch (((union T_primitives *)rptr)->type) { 5868 case T_ADDR_REQ: 5869 udp_addr_req(q, mp); 5870 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5871 "udp_wput_other_end: q %p (%S)", q, "addrreq"); 5872 return; 5873 case O_T_BIND_REQ: 5874 case T_BIND_REQ: 5875 udp_bind(q, mp); 5876 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5877 "udp_wput_other_end: q %p (%S)", q, "bindreq"); 5878 return; 5879 case T_CONN_REQ: 5880 udp_connect(q, mp); 5881 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5882 "udp_wput_other_end: q %p (%S)", q, "connreq"); 5883 return; 5884 case T_CAPABILITY_REQ: 5885 udp_capability_req(q, mp); 5886 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5887 "udp_wput_other_end: q %p (%S)", q, "capabreq"); 5888 return; 5889 case T_INFO_REQ: 5890 udp_info_req(q, mp); 5891 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5892 "udp_wput_other_end: q %p (%S)", q, "inforeq"); 5893 return; 5894 case T_UNITDATA_REQ: 5895 /* 5896 * If a T_UNITDATA_REQ gets here, the address must 5897 * be bad. Valid T_UNITDATA_REQs are handled 5898 * in udp_wput. 5899 */ 5900 udp_ud_err(q, mp, EADDRNOTAVAIL); 5901 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5902 "udp_wput_other_end: q %p (%S)", 5903 q, "unitdatareq"); 5904 return; 5905 case T_UNBIND_REQ: 5906 udp_unbind(q, mp); 5907 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5908 "udp_wput_other_end: q %p (%S)", q, "unbindreq"); 5909 return; 5910 case T_SVR4_OPTMGMT_REQ: 5911 if (!snmpcom_req(q, mp, udp_snmp_set, udp_snmp_get, cr)) 5912 (void) svr4_optcom_req(q, mp, cr, &udp_opt_obj); 5913 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5914 "udp_wput_other_end: q %p (%S)", 5915 q, "optmgmtreq"); 5916 return; 5917 5918 case T_OPTMGMT_REQ: 5919 (void) tpi_optcom_req(q, mp, cr, &udp_opt_obj); 5920 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5921 "udp_wput_other_end: q %p (%S)", 5922 q, "optmgmtreq"); 5923 return; 5924 5925 case T_DISCON_REQ: 5926 udp_disconnect(q, mp); 5927 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5928 "udp_wput_other_end: q %p (%S)", 5929 q, "disconreq"); 5930 return; 5931 5932 /* The following TPI message is not supported by udp. */ 5933 case O_T_CONN_RES: 5934 case T_CONN_RES: 5935 udp_err_ack(q, mp, TNOTSUPPORT, 0); 5936 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5937 "udp_wput_other_end: q %p (%S)", 5938 q, "connres/disconreq"); 5939 return; 5940 5941 /* The following 3 TPI messages are illegal for udp. */ 5942 case T_DATA_REQ: 5943 case T_EXDATA_REQ: 5944 case T_ORDREL_REQ: 5945 udp_err_ack(q, mp, TNOTSUPPORT, 0); 5946 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5947 "udp_wput_other_end: q %p (%S)", 5948 q, "data/exdata/ordrel"); 5949 return; 5950 default: 5951 break; 5952 } 5953 break; 5954 case M_FLUSH: 5955 if (*rptr & FLUSHW) 5956 flushq(q, FLUSHDATA); 5957 break; 5958 case M_IOCTL: 5959 iocp = (struct iocblk *)mp->b_rptr; 5960 switch (iocp->ioc_cmd) { 5961 case TI_GETPEERNAME: 5962 if (udp->udp_state != TS_DATA_XFER) { 5963 /* 5964 * If a default destination address has not 5965 * been associated with the stream, then we 5966 * don't know the peer's name. 5967 */ 5968 iocp->ioc_error = ENOTCONN; 5969 err_ret:; 5970 iocp->ioc_count = 0; 5971 mp->b_datap->db_type = M_IOCACK; 5972 qreply(q, mp); 5973 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5974 "udp_wput_other_end: q %p (%S)", 5975 q, "getpeername"); 5976 return; 5977 } 5978 /* FALLTHRU */ 5979 case TI_GETMYNAME: { 5980 /* 5981 * For TI_GETPEERNAME and TI_GETMYNAME, we first 5982 * need to copyin the user's strbuf structure. 5983 * Processing will continue in the M_IOCDATA case 5984 * below. 5985 */ 5986 mi_copyin(q, mp, NULL, 5987 SIZEOF_STRUCT(strbuf, iocp->ioc_flag)); 5988 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5989 "udp_wput_other_end: q %p (%S)", 5990 q, "getmyname"); 5991 return; 5992 } 5993 case ND_SET: 5994 /* nd_getset performs the necessary checking */ 5995 case ND_GET: 5996 if (nd_getset(q, udp_g_nd, mp)) { 5997 qreply(q, mp); 5998 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 5999 "udp_wput_other_end: q %p (%S)", 6000 q, "get"); 6001 return; 6002 } 6003 break; 6004 default: 6005 break; 6006 } 6007 break; 6008 case M_IOCDATA: 6009 udp_wput_iocdata(q, mp); 6010 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 6011 "udp_wput_other_end: q %p (%S)", q, "iocdata"); 6012 return; 6013 default: 6014 /* Unrecognized messages are passed through without change. */ 6015 break; 6016 } 6017 TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END, 6018 "udp_wput_other_end: q %p (%S)", q, "end"); 6019 putnext(q, mp); 6020 } 6021 6022 /* 6023 * udp_wput_iocdata is called by udp_wput_other to handle all M_IOCDATA 6024 * messages. 6025 */ 6026 static void 6027 udp_wput_iocdata(queue_t *q, mblk_t *mp) 6028 { 6029 mblk_t *mp1; 6030 STRUCT_HANDLE(strbuf, sb); 6031 uint16_t port; 6032 udp_t *udp; 6033 in6_addr_t v6addr; 6034 ipaddr_t v4addr; 6035 uint32_t flowinfo = 0; 6036 int addrlen; 6037 6038 /* Make sure it is one of ours. */ 6039 switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { 6040 case TI_GETMYNAME: 6041 case TI_GETPEERNAME: 6042 break; 6043 default: 6044 putnext(q, mp); 6045 return; 6046 } 6047 switch (mi_copy_state(q, mp, &mp1)) { 6048 case -1: 6049 return; 6050 case MI_COPY_CASE(MI_COPY_IN, 1): 6051 break; 6052 case MI_COPY_CASE(MI_COPY_OUT, 1): 6053 /* 6054 * The address has been copied out, so now 6055 * copyout the strbuf. 6056 */ 6057 mi_copyout(q, mp); 6058 return; 6059 case MI_COPY_CASE(MI_COPY_OUT, 2): 6060 /* 6061 * The address and strbuf have been copied out. 6062 * We're done, so just acknowledge the original 6063 * M_IOCTL. 6064 */ 6065 mi_copy_done(q, mp, 0); 6066 return; 6067 default: 6068 /* 6069 * Something strange has happened, so acknowledge 6070 * the original M_IOCTL with an EPROTO error. 6071 */ 6072 mi_copy_done(q, mp, EPROTO); 6073 return; 6074 } 6075 6076 /* 6077 * Now we have the strbuf structure for TI_GETMYNAME 6078 * and TI_GETPEERNAME. Next we copyout the requested 6079 * address and then we'll copyout the strbuf. 6080 */ 6081 STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag, 6082 (void *)mp1->b_rptr); 6083 udp = (udp_t *)q->q_ptr; 6084 if (udp->udp_family == AF_INET) 6085 addrlen = sizeof (sin_t); 6086 else 6087 addrlen = sizeof (sin6_t); 6088 6089 if (STRUCT_FGET(sb, maxlen) < addrlen) { 6090 mi_copy_done(q, mp, EINVAL); 6091 return; 6092 } 6093 switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { 6094 case TI_GETMYNAME: 6095 if (udp->udp_family == AF_INET) { 6096 ASSERT(udp->udp_ipversion == IPV4_VERSION); 6097 if (!IN6_IS_ADDR_V4MAPPED_ANY(&udp->udp_v6src) && 6098 !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 6099 v4addr = V4_PART_OF_V6(udp->udp_v6src); 6100 } else { 6101 /* 6102 * INADDR_ANY 6103 * udp_v6src is not set, we might be bound to 6104 * broadcast/multicast. Use udp_bound_v6src as 6105 * local address instead (that could 6106 * also still be INADDR_ANY) 6107 */ 6108 v4addr = V4_PART_OF_V6(udp->udp_bound_v6src); 6109 } 6110 } else { 6111 /* udp->udp_family == AF_INET6 */ 6112 if (!IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) { 6113 v6addr = udp->udp_v6src; 6114 } else { 6115 /* 6116 * UNSPECIFIED 6117 * udp_v6src is not set, we might be bound to 6118 * broadcast/multicast. Use udp_bound_v6src as 6119 * local address instead (that could 6120 * also still be UNSPECIFIED) 6121 */ 6122 v6addr = udp->udp_bound_v6src; 6123 } 6124 } 6125 port = udp->udp_port; 6126 break; 6127 case TI_GETPEERNAME: 6128 if (udp->udp_family == AF_INET) { 6129 ASSERT(udp->udp_ipversion == IPV4_VERSION); 6130 v4addr = V4_PART_OF_V6(udp->udp_v6dst); 6131 } else { 6132 /* udp->udp_family == AF_INET6) */ 6133 v6addr = udp->udp_v6dst; 6134 flowinfo = udp->udp_flowinfo; 6135 } 6136 port = udp->udp_dstport; 6137 break; 6138 default: 6139 mi_copy_done(q, mp, EPROTO); 6140 return; 6141 } 6142 mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE); 6143 if (!mp1) 6144 return; 6145 6146 if (udp->udp_family == AF_INET) { 6147 sin_t *sin; 6148 6149 STRUCT_FSET(sb, len, (int)sizeof (sin_t)); 6150 sin = (sin_t *)mp1->b_rptr; 6151 mp1->b_wptr = (uchar_t *)&sin[1]; 6152 *sin = sin_null; 6153 sin->sin_family = AF_INET; 6154 sin->sin_addr.s_addr = v4addr; 6155 sin->sin_port = port; 6156 } else { 6157 /* udp->udp_family == AF_INET6 */ 6158 sin6_t *sin6; 6159 6160 STRUCT_FSET(sb, len, (int)sizeof (sin6_t)); 6161 sin6 = (sin6_t *)mp1->b_rptr; 6162 mp1->b_wptr = (uchar_t *)&sin6[1]; 6163 *sin6 = sin6_null; 6164 sin6->sin6_family = AF_INET6; 6165 sin6->sin6_flowinfo = flowinfo; 6166 sin6->sin6_addr = v6addr; 6167 sin6->sin6_port = port; 6168 } 6169 /* Copy out the address */ 6170 mi_copyout(q, mp); 6171 } 6172 6173 6174 static int 6175 udp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp, 6176 void *thisdg_attrs) 6177 { 6178 udp_t *udp; 6179 struct T_unitdata_req *udreqp; 6180 int is_absreq_failure; 6181 cred_t *cr; 6182 6183 ASSERT(((union T_primitives *)mp->b_rptr)->type); 6184 6185 udp = (udp_t *)q->q_ptr; 6186 6187 cr = DB_CREDDEF(mp, udp->udp_credp); 6188 6189 udreqp = (struct T_unitdata_req *)mp->b_rptr; 6190 *errorp = 0; 6191 6192 *errorp = tpi_optcom_buf(q, mp, &udreqp->OPT_length, 6193 udreqp->OPT_offset, cr, &udp_opt_obj, 6194 thisdg_attrs, &is_absreq_failure); 6195 6196 if (*errorp != 0) { 6197 /* 6198 * Note: No special action needed in this 6199 * module for "is_absreq_failure" 6200 */ 6201 return (-1); /* failure */ 6202 } 6203 ASSERT(is_absreq_failure == 0); 6204 return (0); /* success */ 6205 } 6206 6207 void 6208 udp_ddi_init(void) 6209 { 6210 int i; 6211 6212 UDP6_MAJ = ddi_name_to_major(UDP6); 6213 mutex_init(&udp_g_lock, NULL, MUTEX_DEFAULT, NULL); 6214 6215 udp_max_optsize = optcom_max_optsize(udp_opt_obj.odb_opt_des_arr, 6216 udp_opt_obj.odb_opt_arr_cnt); 6217 6218 if (udp_bind_fanout_size & (udp_bind_fanout_size - 1)) { 6219 /* Not a power of two. Round up to nearest power of two */ 6220 for (i = 0; i < 31; i++) { 6221 if (udp_bind_fanout_size < (1 << i)) 6222 break; 6223 } 6224 udp_bind_fanout_size = 1 << i; 6225 } 6226 udp_bind_fanout = kmem_zalloc(udp_bind_fanout_size * 6227 sizeof (udp_fanout_t), KM_SLEEP); 6228 for (i = 0; i < udp_bind_fanout_size; i++) { 6229 mutex_init(&udp_bind_fanout[i].uf_lock, NULL, MUTEX_DEFAULT, 6230 NULL); 6231 } 6232 (void) udp_param_register(udp_param_arr, A_CNT(udp_param_arr)); 6233 udp_kstat_init(); 6234 } 6235 6236 void 6237 udp_ddi_destroy(void) 6238 { 6239 int i; 6240 6241 nd_free(&udp_g_nd); 6242 6243 mutex_destroy(&udp_g_lock); 6244 for (i = 0; i < udp_bind_fanout_size; i++) { 6245 mutex_destroy(&udp_bind_fanout[i].uf_lock); 6246 } 6247 kmem_free(udp_bind_fanout, udp_bind_fanout_size * 6248 sizeof (udp_fanout_t)); 6249 udp_kstat_fini(); 6250 6251 } 6252 6253 static void 6254 udp_kstat_init(void) 6255 { 6256 udp_named_kstat_t template = { 6257 { "inDatagrams", KSTAT_DATA_UINT32, 0 }, 6258 { "inErrors", KSTAT_DATA_UINT32, 0 }, 6259 { "outDatagrams", KSTAT_DATA_UINT32, 0 }, 6260 { "entrySize", KSTAT_DATA_INT32, 0 }, 6261 { "entry6Size", KSTAT_DATA_INT32, 0 }, 6262 { "outErrors", KSTAT_DATA_UINT32, 0 }, 6263 }; 6264 6265 udp_mibkp = kstat_create("udp", 0, "udp", "mib2", KSTAT_TYPE_NAMED, 6266 NUM_OF_FIELDS(udp_named_kstat_t), 6267 0); 6268 if (udp_mibkp == NULL) 6269 return; 6270 6271 template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t); 6272 template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t); 6273 6274 bcopy(&template, udp_mibkp->ks_data, sizeof (template)); 6275 6276 udp_mibkp->ks_update = udp_kstat_update; 6277 6278 kstat_install(udp_mibkp); 6279 } 6280 6281 static void 6282 udp_kstat_fini(void) 6283 { 6284 if (udp_mibkp) { 6285 kstat_delete(udp_mibkp); 6286 udp_mibkp = NULL; 6287 } 6288 } 6289 6290 static int 6291 udp_kstat_update(kstat_t *kp, int rw) 6292 { 6293 udp_named_kstat_t *udpkp; 6294 6295 if ((kp == NULL) || (kp->ks_data == NULL)) 6296 return (EIO); 6297 6298 if (rw == KSTAT_WRITE) 6299 return (EACCES); 6300 6301 udpkp = (udp_named_kstat_t *)kp->ks_data; 6302 6303 udpkp->inDatagrams.value.ui32 = udp_mib.udpInDatagrams; 6304 udpkp->inErrors.value.ui32 = udp_mib.udpInErrors; 6305 udpkp->outDatagrams.value.ui32 = udp_mib.udpOutDatagrams; 6306 udpkp->outErrors.value.ui32 = udp_mib.udpOutErrors; 6307 6308 return (0); 6309 } 6310 6311 /* 6312 * Little helper for IPsec's NAT-T processing. 6313 */ 6314 boolean_t 6315 udp_compute_checksum(void) 6316 { 6317 return (udp_do_checksum); 6318 } 6319