udp_impl.h revision 3448:aaf16568054b
1203954Srdivacky/* 2203954Srdivacky * CDDL HEADER START 3203954Srdivacky * 4203954Srdivacky * The contents of this file are subject to the terms of the 5203954Srdivacky * Common Development and Distribution License (the "License"). 6203954Srdivacky * You may not use this file except in compliance with the License. 7203954Srdivacky * 8203954Srdivacky * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9203954Srdivacky * or http://www.opensolaris.org/os/licensing. 10203954Srdivacky * See the License for the specific language governing permissions 11203954Srdivacky * and limitations under the License. 12221345Sdim * 13203954Srdivacky * When distributing Covered Code, include this CDDL HEADER in each 14221345Sdim * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15204642Srdivacky * If applicable, add the following below this CDDL HEADER, with the 16203954Srdivacky * fields enclosed by brackets "[]" replaced with your own identifying 17204642Srdivacky * information: Portions Copyright [yyyy] [name of copyright owner] 18203954Srdivacky * 19203954Srdivacky * CDDL HEADER END 20204642Srdivacky */ 21204642Srdivacky/* 22204642Srdivacky * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23204642Srdivacky * Use is subject to license terms. 24204642Srdivacky */ 25204642Srdivacky 26204642Srdivacky#ifndef _UDP_IMPL_H 27204642Srdivacky#define _UDP_IMPL_H 28204642Srdivacky 29204642Srdivacky#pragma ident "%Z%%M% %I% %E% SMI" 30218893Sdim 31204642Srdivacky/* 32204642Srdivacky * UDP implementation private declarations. These interfaces are 33204642Srdivacky * used to build the IP module and are not meant to be accessed 34204642Srdivacky * by any modules except IP itself. They are undocumented and are 35218893Sdim * subject to change without notice. 36204642Srdivacky */ 37204642Srdivacky 38204642Srdivacky#ifdef __cplusplus 39204642Srdivackyextern "C" { 40204642Srdivacky#endif 41204642Srdivacky 42204642Srdivacky#ifdef _KERNEL 43204642Srdivacky 44204642Srdivacky#include <sys/int_types.h> 45204642Srdivacky#include <sys/netstack.h> 46204642Srdivacky 47204642Srdivacky#include <netinet/in.h> 48204642Srdivacky#include <netinet/ip6.h> 49203954Srdivacky 50203954Srdivacky#include <inet/common.h> 51203954Srdivacky#include <inet/ip.h> 52203954Srdivacky#include <inet/optcom.h> 53218893Sdim 54203954Srdivacky#define UDP_MOD_ID 5607 55203954Srdivacky 56203954Srdivacky/* udp_mode. UDP_MT_HOT and UDP_SQUEUE are stable modes. Rest are transient */ 57203954Srdivackytypedef enum { 58218893Sdim UDP_MT_HOT = 0, /* UDP endpoint is MT HOT */ 59203954Srdivacky UDP_MT_QUEUED = 1, /* Messages enqueued in udp_mphead */ 60203954Srdivacky UDP_QUEUED_SQUEUE = 2, /* Messages enqueued in conn_sqp */ 61203954Srdivacky UDP_SQUEUE = 3 /* Single threaded using squeues */ 62203954Srdivacky} udp_mode_t; 63218893Sdim 64204642Srdivacky/* 65204642Srdivacky * Bind hash list size and hash function. It has to be a power of 2 for 66204642Srdivacky * hashing. 67203954Srdivacky */ 68218893Sdim#define UDP_BIND_FANOUT_SIZE 512 69204642Srdivacky#define UDP_BIND_HASH(lport, size) \ 70204642Srdivacky ((ntohs((uint16_t)lport)) & (size - 1)) 71204642Srdivacky 72204642Srdivacky/* UDP bind fanout hash structure. */ 73218893Sdimtypedef struct udp_fanout_s { 74218893Sdim struct udp_s *uf_udp; 75218893Sdim kmutex_t uf_lock; 76218893Sdim#if defined(_LP64) || defined(_I32LPx) 77204792Srdivacky char uf_pad[48]; 78204792Srdivacky#else 79204792Srdivacky char uf_pad[56]; 80204792Srdivacky#endif 81204792Srdivacky} udp_fanout_t; 82204792Srdivacky 83204792Srdivacky 84218893Sdim/* Kstats */ 85204642Srdivackytypedef struct udp_stat { /* Class "net" kstats */ 86204642Srdivacky kstat_named_t udp_ip_send; 87204642Srdivacky kstat_named_t udp_ip_ire_send; 88204642Srdivacky kstat_named_t udp_ire_null; 89218893Sdim kstat_named_t udp_drain; 90204642Srdivacky kstat_named_t udp_sock_fallback; 91204642Srdivacky kstat_named_t udp_rrw_busy; 92218893Sdim kstat_named_t udp_rrw_msgcnt; 93204642Srdivacky kstat_named_t udp_out_sw_cksum; 94204642Srdivacky kstat_named_t udp_out_sw_cksum_bytes; 95204642Srdivacky kstat_named_t udp_out_opt; 96221345Sdim kstat_named_t udp_out_err_notconn; 97221345Sdim kstat_named_t udp_out_err_output; 98221345Sdim kstat_named_t udp_out_err_tudr; 99221345Sdim kstat_named_t udp_in_pktinfo; 100203954Srdivacky kstat_named_t udp_in_recvdstaddr; 101203954Srdivacky kstat_named_t udp_in_recvopts; 102218893Sdim kstat_named_t udp_in_recvif; 103203954Srdivacky kstat_named_t udp_in_recvslla; 104203954Srdivacky kstat_named_t udp_in_recvucred; 105203954Srdivacky kstat_named_t udp_in_recvttl; 106218893Sdim kstat_named_t udp_in_recvhopopts; 107204642Srdivacky kstat_named_t udp_in_recvhoplimit; 108204642Srdivacky kstat_named_t udp_in_recvdstopts; 109218893Sdim kstat_named_t udp_in_recvrtdstopts; 110204642Srdivacky kstat_named_t udp_in_recvrthdr; 111203954Srdivacky kstat_named_t udp_in_recvpktinfo; 112204642Srdivacky kstat_named_t udp_in_recvtclass; 113203954Srdivacky kstat_named_t udp_in_timestamp; 114218893Sdim kstat_named_t udp_ip_recvpktinfo; 115204642Srdivacky#ifdef DEBUG 116203954Srdivacky kstat_named_t udp_data_conn; 117203954Srdivacky kstat_named_t udp_data_notconn; 118203954Srdivacky#endif 119203954Srdivacky 120218893Sdim} udp_stat_t; 121204642Srdivacky 122204642Srdivacky/* Named Dispatch Parameter Management Structure */ 123204642Srdivackytypedef struct udpparam_s { 124204642Srdivacky uint32_t udp_param_min; 125204642Srdivacky uint32_t udp_param_max; 126204642Srdivacky uint32_t udp_param_value; 127204642Srdivacky char *udp_param_name; 128204642Srdivacky} udpparam_t; 129204642Srdivacky 130204642Srdivacky#define UDP_NUM_EPRIV_PORTS 64 131204642Srdivacky 132218893Sdim/* 133204642Srdivacky * UDP stack instances 134204642Srdivacky */ 135204642Srdivackystruct udp_stack { 136204642Srdivacky netstack_t *us_netstack; /* Common netstack */ 137204642Srdivacky 138204642Srdivacky uint_t us_bind_fanout_size; 139204642Srdivacky udp_fanout_t *us_bind_fanout; 140204642Srdivacky 141204642Srdivacky int us_num_epriv_ports; 142204642Srdivacky in_port_t us_epriv_ports[UDP_NUM_EPRIV_PORTS]; 143204642Srdivacky 144218893Sdim /* Hint not protected by any lock */ 145203954Srdivacky in_port_t us_next_port_to_try; 146203954Srdivacky 147203954Srdivacky IDP us_nd; /* Points to table of UDP ND variables. */ 148203954Srdivacky udpparam_t *us_param_arr; /* ndd variable table */ 149203954Srdivacky 150204642Srdivacky kstat_t *us_mibkp; /* kstats exporting mib data */ 151203954Srdivacky kstat_t *us_kstat; 152203954Srdivacky udp_stat_t us_statistics; 153203954Srdivacky 154203954Srdivacky mib2_udp_t us_udp_mib; /* SNMP fixed size info */ 155203954Srdivacky 156203954Srdivacky/* 157203954Srdivacky * This controls the rate some ndd info report functions can be used 158203954Srdivacky * by non-priviledged users. It stores the last time such info is 159203954Srdivacky * requested. When those report functions are called again, this 160203954Srdivacky * is checked with the current time and compare with the ndd param 161203954Srdivacky * udp_ndd_get_info_interval. 162203954Srdivacky */ 163203954Srdivacky clock_t us_last_ndd_get_info_time; 164203954Srdivacky 165218893Sdim/* 166203954Srdivacky * The smallest anonymous port in the priviledged port range which UDP 167203954Srdivacky * looks for free port. Use in the option UDP_ANONPRIVBIND. 168221345Sdim */ 169221345Sdim in_port_t us_min_anonpriv_port; 170221345Sdim 171221345Sdim}; 172221345Sdimtypedef struct udp_stack udp_stack_t; 173221345Sdim 174203954Srdivacky/* Internal udp control structure, one per open stream */ 175203954Srdivackytypedef struct udp_s { 176203954Srdivacky uint32_t udp_state; /* TPI state */ 177203954Srdivacky in_port_t udp_port; /* Port bound to this stream */ 178203954Srdivacky in_port_t udp_dstport; /* Connected port */ 179203954Srdivacky in6_addr_t udp_v6src; /* Source address of this stream */ 180203954Srdivacky in6_addr_t udp_bound_v6src; /* Explicitly bound address */ 181203954Srdivacky in6_addr_t udp_v6dst; /* Connected destination */ 182203954Srdivacky uint32_t udp_flowinfo; /* Connected flow id and tclass */ 183203954Srdivacky uint32_t udp_max_hdr_len; /* For write offset in stream head */ 184218893Sdim sa_family_t udp_family; /* Family from socket() call */ 185203954Srdivacky /* 186203954Srdivacky * IP format that packets transmitted from this struct should use. 187203954Srdivacky * Value can be IP4_VERSION or IPV6_VERSION. 188203954Srdivacky */ 189203954Srdivacky ushort_t udp_ipversion; 190203954Srdivacky uint32_t udp_ip_snd_options_len; /* Len of IPv4 options */ 191203954Srdivacky uchar_t *udp_ip_snd_options; /* Ptr to IPv4 options */ 192203954Srdivacky uint32_t udp_ip_rcv_options_len; /* Len of IPv4 options recvd */ 193203954Srdivacky uchar_t *udp_ip_rcv_options; /* Ptr to IPv4 options recvd */ 194203954Srdivacky uchar_t udp_multicast_ttl; /* IP*_MULTICAST_TTL/HOPS */ 195203954Srdivacky ipaddr_t udp_multicast_if_addr; /* IP_MULTICAST_IF option */ 196203954Srdivacky uint_t udp_multicast_if_index; /* IPV6_MULTICAST_IF option */ 197218893Sdim int udp_bound_if; /* IP*_BOUND_IF option */ 198204642Srdivacky int udp_xmit_if; /* IP_XMIT_IF option */ 199203954Srdivacky conn_t *udp_connp; 200204642Srdivacky uint32_t 201203954Srdivacky udp_debug : 1, /* SO_DEBUG "socket" option. */ 202204642Srdivacky udp_dontroute : 1, /* SO_DONTROUTE "socket" option. */ 203203954Srdivacky udp_broadcast : 1, /* SO_BROADCAST "socket" option. */ 204203954Srdivacky udp_useloopback : 1, /* SO_USELOOPBACK "socket" option */ 205203954Srdivacky 206203954Srdivacky udp_reuseaddr : 1, /* SO_REUSEADDR "socket" option. */ 207204642Srdivacky udp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */ 208204642Srdivacky udp_recvdstaddr : 1, /* IP_RECVDSTADDR option */ 209204642Srdivacky udp_recvopts : 1, /* IP_RECVOPTS option */ 210203954Srdivacky 211203954Srdivacky udp_discon_pending : 1, /* T_DISCON_REQ in progress */ 212203954Srdivacky udp_unspec_source : 1, /* IP*_UNSPEC_SRC option */ 213203954Srdivacky udp_ip_recvpktinfo : 1, /* IPV[4,6]_RECVPKTINFO option */ 214218893Sdim udp_ipv6_recvhoplimit : 1, /* IPV6_RECVHOPLIMIT option */ 215203954Srdivacky 216204642Srdivacky udp_ipv6_recvhopopts : 1, /* IPV6_RECVHOPOPTS option */ 217204642Srdivacky udp_ipv6_recvdstopts : 1, /* IPV6_RECVDSTOPTS option */ 218204642Srdivacky udp_ipv6_recvrthdr : 1, /* IPV6_RECVRTHDR option */ 219204642Srdivacky udp_ipv6_recvtclass : 1, /* IPV6_RECVTCLASS */ 220204642Srdivacky 221204642Srdivacky udp_ipv6_recvpathmtu : 1, /* IPV6_RECVPATHMTU */ 222204642Srdivacky udp_anon_priv_bind : 1, 223204642Srdivacky udp_exclbind : 1, /* ``exclusive'' binding */ 224204642Srdivacky udp_recvif : 1, /* IP_RECVIF option */ 225204642Srdivacky 226204642Srdivacky udp_recvslla : 1, /* IP_RECVSLLA option */ 227218893Sdim udp_recvttl : 1, /* IP_RECVTTL option */ 228203954Srdivacky udp_recvucred : 1, /* IP_RECVUCRED option */ 229203954Srdivacky udp_old_ipv6_recvdstopts : 1, /* old form of IPV6_DSTOPTS */ 230203954Srdivacky 231203954Srdivacky udp_ipv6_recvrthdrdstopts : 1, /* IPV6_RECVRTHDRDSTOPTS */ 232203954Srdivacky udp_rcvhdr : 1, /* UDP_RCVHDR option */ 233218893Sdim udp_issocket : 1, /* socket mode */ 234203954Srdivacky udp_direct_sockfs : 1, /* direct calls to/from sockfs */ 235203954Srdivacky 236218893Sdim udp_timestamp : 1, /* SO_TIMESTAMP "socket" option */ 237203954Srdivacky udp_anon_mlp : 1, /* SO_ANON_MLP */ 238208599Srdivacky udp_mac_exempt : 1, /* SO_MAC_EXEMPT */ 239203954Srdivacky udp_pad_to_bit_31 : 1; 240203954Srdivacky 241203954Srdivacky uint8_t udp_type_of_service; /* IP_TOS option */ 242204642Srdivacky uint8_t udp_ttl; /* TTL or hoplimit */ 243204642Srdivacky 244218893Sdim ip6_pkt_t udp_sticky_ipp; /* Sticky options */ 245204642Srdivacky uint8_t *udp_sticky_hdrs; /* Prebuilt IPv6 hdrs */ 246204642Srdivacky uint_t udp_sticky_hdrs_len; /* Incl. ip6h and any ip6i */ 247204642Srdivacky struct udp_s *udp_bind_hash; /* Bind hash chain */ 248204642Srdivacky struct udp_s **udp_ptpbhn; /* Pointer to previous bind hash next. */ 249204642Srdivacky udp_mode_t udp_mode; /* Current mode of operation */ 250204642Srdivacky mblk_t *udp_mphead; /* Head of the queued operations */ 251218893Sdim mblk_t *udp_mptail; /* Tail of the queued operations */ 252203954Srdivacky uint_t udp_mpcount; /* Number of messages in the queue */ 253204642Srdivacky uint_t udp_reader_count; /* Number of reader threads */ 254218893Sdim uint_t udp_squeue_count; /* Number of messages in conn_sqp */ 255203954Srdivacky 256204642Srdivacky kmutex_t udp_drain_lock; /* lock for udp_rcv_list */ 257218893Sdim boolean_t udp_drain_qfull; /* drain queue is full */ 258203954Srdivacky mblk_t *udp_rcv_list_head; /* b_next chain of mblks */ 259204642Srdivacky mblk_t *udp_rcv_list_tail; /* last mblk in chain */ 260204642Srdivacky uint_t udp_rcv_cnt; /* total data in rcv_list */ 261204642Srdivacky uint_t udp_rcv_msgcnt; /* total messages in rcv_list */ 262204642Srdivacky size_t udp_rcv_hiwat; /* receive high watermark */ 263204642Srdivacky uint_t udp_label_len; /* length of security label */ 264204642Srdivacky uint_t udp_label_len_v6; /* len of v6 security label */ 265204642Srdivacky in6_addr_t udp_v6lastdst; /* most recent destination */ 266204792Srdivacky 267204792Srdivacky uint64_t udp_open_time; /* time when this was opened */ 268204792Srdivacky pid_t udp_open_pid; /* process id when this was opened */ 269204642Srdivacky udp_stack_t *udp_us; /* Stack instance for zone */ 270203954Srdivacky} udp_t; 271218893Sdim#define udp_mib udp_us->us_udp_mib 272203954Srdivacky 273203954Srdivacky/* UDP Protocol header */ 274203954Srdivacky/* UDP Protocol header aligned */ 275203954Srdivackytypedef struct udpahdr_s { 276203954Srdivacky in_port_t uha_src_port; /* Source port */ 277203954Srdivacky in_port_t uha_dst_port; /* Destination port */ 278203954Srdivacky uint16_t uha_length; /* UDP length */ 279203954Srdivacky uint16_t uha_checksum; /* UDP checksum */ 280218893Sdim} udpha_t; 281203954Srdivacky 282203954Srdivacky#define us_wroff_extra us_param_arr[0].udp_param_value 283203954Srdivacky#define us_ipv4_ttl us_param_arr[1].udp_param_value 284203954Srdivacky#define us_ipv6_hoplimit us_param_arr[2].udp_param_value 285203954Srdivacky#define us_smallest_nonpriv_port us_param_arr[3].udp_param_value 286203954Srdivacky#define us_do_checksum us_param_arr[4].udp_param_value 287203954Srdivacky#define us_smallest_anon_port us_param_arr[5].udp_param_value 288203954Srdivacky#define us_largest_anon_port us_param_arr[6].udp_param_value 289203954Srdivacky#define us_xmit_hiwat us_param_arr[7].udp_param_value 290203954Srdivacky#define us_xmit_lowat us_param_arr[8].udp_param_value 291218893Sdim#define us_recv_hiwat us_param_arr[9].udp_param_value 292203954Srdivacky#define us_max_buf us_param_arr[10].udp_param_value 293204642Srdivacky#define us_ndd_get_info_interval us_param_arr[11].udp_param_value 294204642Srdivacky 295203954Srdivacky 296203954Srdivacky#define UDP_STAT(us, x) ((us)->us_statistics.x.value.ui64++) 297204642Srdivacky#define UDP_STAT_UPDATE(us, x, n) \ 298204642Srdivacky ((us)->us_statistics.x.value.ui64 += (n)) 299204642Srdivacky 300204642Srdivacky#ifdef DEBUG 301204642Srdivacky#define UDP_DBGSTAT(us, x) UDP_STAT(us, x) 302204642Srdivacky#else 303204642Srdivacky#define UDP_DBGSTAT(us, x) 304203954Srdivacky#endif /* DEBUG */ 305204642Srdivacky 306203954Srdivackyextern major_t UDP6_MAJ; 307204642Srdivacky 308203954Srdivackyextern int udp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *); 309203954Srdivackyextern int udp_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *); 310204642Srdivackyextern int udp_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *, 311203954Srdivacky uint_t *, uchar_t *, void *, cred_t *, mblk_t *); 312204642Srdivackyextern int udp_snmp_get(queue_t *, mblk_t *); 313203954Srdivackyextern int udp_snmp_set(queue_t *, t_scalar_t, t_scalar_t, uchar_t *, int); 314203954Srdivackyextern void udp_close_free(conn_t *); 315203954Srdivackyextern void udp_quiesce_conn(conn_t *); 316203954Srdivackyextern void udp_ddi_init(void); 317218893Sdimextern void udp_ddi_destroy(void); 318203954Srdivackyextern void udp_resume_bind(conn_t *, mblk_t *); 319204642Srdivackyextern void udp_conn_recv(conn_t *, mblk_t *); 320218893Sdimextern boolean_t udp_compute_checksum(netstack_t *); 321204642Srdivackyextern void udp_wput_data(queue_t *, mblk_t *, struct sockaddr *, 322204642Srdivacky socklen_t); 323204642Srdivacky 324204642Srdivackyextern int udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, 325218893Sdim uchar_t *ptr); 326203954Srdivackyextern int udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, 327203954Srdivacky uchar_t *ptr); 328203954Srdivackyextern int udp_opt_set(queue_t *q, uint_t optset_context, 329204642Srdivacky int level, int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 330204642Srdivacky uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk); 331204642Srdivacky 332204642Srdivacky/* 333204642Srdivacky * Object to represent database of options to search passed to 334204642Srdivacky * {sock,tpi}optcom_req() interface routine to take care of option 335204642Srdivacky * management and associated methods. 336218893Sdim */ 337204642Srdivackyextern optdb_obj_t udp_opt_obj; 338204642Srdivackyextern uint_t udp_max_optsize; 339203954Srdivacky 340203954Srdivacky#endif /* _KERNEL */ 341204642Srdivacky 342204642Srdivacky#ifdef __cplusplus 343204642Srdivacky} 344204642Srdivacky#endif 345204642Srdivacky 346204642Srdivacky#endif /* _UDP_IMPL_H */ 347204642Srdivacky