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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #ifndef _UDP_IMPL_H
  26 #define _UDP_IMPL_H
  27 
  28 /*
  29  * UDP implementation private declarations.  These interfaces are
  30  * used to build the IP module and are not meant to be accessed
  31  * by any modules except IP itself.  They are undocumented and are
  32  * subject to change without notice.
  33  */
  34 
  35 #ifdef  __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 #ifdef _KERNEL
  40 
  41 #include <sys/int_types.h>
  42 #include <sys/netstack.h>
  43 
  44 #include <netinet/in.h>
  45 #include <netinet/ip6.h>
  46 
  47 #include <inet/common.h>
  48 #include <inet/ip.h>
  49 #include <inet/optcom.h>
  50 #include <inet/tunables.h>
  51 
  52 #define UDP_MOD_ID              5607
  53 
  54 /*
  55  * Bind hash list size and hash function.  It has to be a power of 2 for
  56  * hashing.
  57  */
  58 #define UDP_BIND_FANOUT_SIZE    512
  59 #define UDP_BIND_HASH(lport, size) \
  60         ((ntohs((uint16_t)lport)) & (size - 1))
  61 
  62 /* UDP bind fanout hash structure. */
  63 typedef struct udp_fanout_s {
  64         struct udp_s *uf_udp;
  65         kmutex_t uf_lock;
  66 #if defined(_LP64) || defined(_I32LPx)
  67         char    uf_pad[48];
  68 #else
  69         char    uf_pad[56];
  70 #endif
  71 } udp_fanout_t;
  72 
  73 /* Kstats */
  74 typedef struct udp_stat {                       /* Class "net" kstats */
  75         kstat_named_t   udp_sock_fallback;
  76         kstat_named_t   udp_out_opt;
  77         kstat_named_t   udp_out_err_notconn;
  78         kstat_named_t   udp_out_err_output;
  79         kstat_named_t   udp_out_err_tudr;
  80 #ifdef DEBUG
  81         kstat_named_t   udp_data_conn;
  82         kstat_named_t   udp_data_notconn;
  83         kstat_named_t   udp_out_lastdst;
  84         kstat_named_t   udp_out_diffdst;
  85         kstat_named_t   udp_out_ipv6;
  86         kstat_named_t   udp_out_mapped;
  87         kstat_named_t   udp_out_ipv4;
  88 #endif
  89 } udp_stat_t;
  90 
  91 /*
  92  * This struct contains only the counter part of udp_stat_t.  It is used
  93  * in udp_stats_cpu_t instead of udp_stat_t to save memory space.
  94  */
  95 typedef struct {
  96         uint64_t        udp_sock_fallback;
  97         uint64_t        udp_out_opt;
  98         uint64_t        udp_out_err_notconn;
  99         uint64_t        udp_out_err_output;
 100         uint64_t        udp_out_err_tudr;
 101 #ifdef DEBUG
 102         uint64_t        udp_data_conn;
 103         uint64_t        udp_data_notconn;
 104         uint64_t        udp_out_lastdst;
 105         uint64_t        udp_out_diffdst;
 106         uint64_t        udp_out_ipv6;
 107         uint64_t        udp_out_mapped;
 108         uint64_t        udp_out_ipv4;
 109 #endif
 110 } udp_stat_counter_t;
 111 
 112 /* Per CPU stats: UDP MIB2 and UDP kstat. */
 113 typedef struct {
 114         mib2_udp_t              udp_sc_mib;
 115         udp_stat_counter_t      udp_sc_stats;
 116 } udp_stats_cpu_t;
 117 
 118 #define UDP_NUM_EPRIV_PORTS     64
 119 
 120 /* Default buffer size and flow control wake up threshold. */
 121 #define UDP_RECV_HIWATER        (56 * 1024)
 122 #define UDP_RECV_LOWATER        128
 123 #define UDP_XMIT_HIWATER        (56 * 1024)
 124 #define UDP_XMIT_LOWATER        1024
 125 
 126 /*
 127  * UDP stack instances
 128  */
 129 struct udp_stack {
 130         netstack_t      *us_netstack;   /* Common netstack */
 131 
 132         uint_t          us_bind_fanout_size;
 133         udp_fanout_t    *us_bind_fanout;
 134 
 135         int             us_num_epriv_ports;
 136         in_port_t       us_epriv_ports[UDP_NUM_EPRIV_PORTS];
 137         kmutex_t        us_epriv_port_lock;
 138 
 139         /* Hint not protected by any lock */
 140         in_port_t       us_next_port_to_try;
 141 
 142         /* UDP tunables table */
 143         struct mod_prop_info_s  *us_propinfo_tbl;
 144 
 145         kstat_t         *us_mibkp;      /* kstats exporting mib data */
 146         kstat_t         *us_kstat;
 147 
 148 /*
 149  * The smallest anonymous port in the priviledged port range which UDP
 150  * looks for free port.  Use in the option UDP_ANONPRIVBIND.
 151  */
 152         in_port_t       us_min_anonpriv_port;
 153 
 154         ldi_ident_t     us_ldi_ident;
 155 
 156         udp_stats_cpu_t **us_sc;
 157         int             us_sc_cnt;
 158 };
 159 
 160 typedef struct udp_stack udp_stack_t;
 161 
 162 /* Internal udp control structure, one per open stream */
 163 typedef struct udp_s {
 164         /*
 165          * The addresses and ports in the conn_t and udp_state are protected by
 166          * conn_lock and the fanout lock i.e. uf_lock. Need both locks to change
 167          * the fields, either lock is sufficient for reading the field.
 168          * conn_lock also protects the content of udp_t.
 169          */
 170         uint32_t        udp_state;      /* TPI state */
 171 
 172         ip_pkt_t        udp_recv_ipp;   /* Used for IPv4 options received */
 173 
 174         /* Written to only once at the time of opening the endpoint */
 175         conn_t          *udp_connp;
 176 
 177         uint32_t
 178                 udp_issocket : 1,       /* socket mode; sockfs is on top */
 179                 udp_nat_t_endpoint : 1, /* UDP_NAT_T_ENDPOINT option */
 180                 udp_rcvhdr : 1,         /* UDP_RCVHDR option */
 181                 udp_snd_to_conn: 1,     /* UDP_SND_TO_CONNECTED option */
 182 
 183                 udp_pad_to_bit_31 : 28;
 184 
 185         /* Following 2 fields protected by the uf_lock */
 186         struct udp_s    *udp_bind_hash; /* Bind hash chain */
 187         struct udp_s    **udp_ptpbhn; /* Pointer to previous bind hash next. */
 188 
 189         kmutex_t        udp_recv_lock;          /* recv lock */
 190         size_t          udp_rcv_disply_hiwat;   /* user's view of rcvbuf */
 191         size_t          udp_rcv_hiwat;          /* receive high watermark */
 192 
 193         /* Set at open time and never changed */
 194         udp_stack_t     *udp_us;                /* Stack instance for zone */
 195 
 196         int             udp_delayed_error;
 197         mblk_t          *udp_fallback_queue_head;
 198         mblk_t          *udp_fallback_queue_tail;
 199         struct sockaddr_storage udp_delayed_addr;
 200 } udp_t;
 201 
 202 /* UDP Protocol header aligned */
 203 typedef struct udpahdr_s {
 204         in_port_t       uha_src_port;           /* Source port */
 205         in_port_t       uha_dst_port;           /* Destination port */
 206         uint16_t        uha_length;             /* UDP length */
 207         uint16_t        uha_checksum;           /* UDP checksum */
 208 } udpha_t;
 209 
 210 #define us_wroff_extra                  us_propinfo_tbl[0].prop_cur_uval
 211 #define us_ipv4_ttl                     us_propinfo_tbl[1].prop_cur_uval
 212 #define us_ipv6_hoplimit                us_propinfo_tbl[2].prop_cur_uval
 213 #define us_smallest_nonpriv_port        us_propinfo_tbl[3].prop_cur_uval
 214 #define us_do_checksum                  us_propinfo_tbl[4].prop_cur_bval
 215 #define us_smallest_anon_port           us_propinfo_tbl[5].prop_cur_uval
 216 #define us_largest_anon_port            us_propinfo_tbl[6].prop_cur_uval
 217 #define us_xmit_hiwat                   us_propinfo_tbl[7].prop_cur_uval
 218 #define us_xmit_lowat                   us_propinfo_tbl[8].prop_cur_uval
 219 #define us_recv_hiwat                   us_propinfo_tbl[9].prop_cur_uval
 220 #define us_max_buf                      us_propinfo_tbl[10].prop_cur_uval
 221 #define us_pmtu_discovery               us_propinfo_tbl[11].prop_cur_bval
 222 #define us_sendto_ignerr                us_propinfo_tbl[12].prop_cur_bval
 223 
 224 #define UDPS_BUMP_MIB(us, x)    \
 225         BUMP_MIB(&(us)->us_sc[CPU->cpu_seqid]->udp_sc_mib, x)
 226 
 227 #define UDP_STAT(us, x)         ((us)->us_sc[CPU->cpu_seqid]->udp_sc_stats.x++)
 228 #define UDP_STAT_UPDATE(us, x, n)       \
 229         ((us)->us->sc[CPU->cpu_seqid]->udp_sc_stats.x.value.ui64 += (n))
 230 #ifdef DEBUG
 231 #define UDP_DBGSTAT(us, x)      UDP_STAT(us, x)
 232 #else
 233 #define UDP_DBGSTAT(us, x)
 234 #endif /* DEBUG */
 235 
 236 extern int      udp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
 237 extern int      udp_tpi_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
 238 extern int      udp_tpi_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *,
 239                     uint_t *, uchar_t *, void *, cred_t *);
 240 extern mblk_t   *udp_snmp_get(queue_t *, mblk_t *, boolean_t);
 241 extern int      udp_snmp_set(queue_t *, t_scalar_t, t_scalar_t, uchar_t *, int);
 242 extern void     udp_ddi_g_init(void);
 243 extern void     udp_ddi_g_destroy(void);
 244 extern void     udp_output(conn_t *connp, mblk_t *mp, struct sockaddr *addr,
 245                     socklen_t addrlen);
 246 extern void     udp_wput(queue_t *, mblk_t *);
 247 
 248 extern void     *udp_kstat_init(netstackid_t stackid);
 249 extern void     udp_kstat_fini(netstackid_t stackid, kstat_t *ksp);
 250 extern void     *udp_kstat2_init(netstackid_t stackid);
 251 extern void     udp_kstat2_fini(netstackid_t, kstat_t *);
 252 
 253 extern void     udp_stack_cpu_add(udp_stack_t *, processorid_t);
 254 
 255 /*
 256  * Object to represent database of options to search passed to
 257  * {sock,tpi}optcom_req() interface routine to take care of option
 258  * management and associated methods.
 259  */
 260 extern optdb_obj_t      udp_opt_obj;
 261 extern uint_t           udp_max_optsize;
 262 
 263 extern sock_lower_handle_t udp_create(int, int, int, sock_downcalls_t **,
 264     uint_t *, int *, int, cred_t *);
 265 extern int udp_fallback(sock_lower_handle_t, queue_t *, boolean_t,
 266     so_proto_quiesced_cb_t, sock_quiesce_arg_t *);
 267 
 268 extern sock_downcalls_t sock_udp_downcalls;
 269 
 270 #endif  /*  _KERNEL */
 271 
 272 #ifdef  __cplusplus
 273 }
 274 #endif
 275 
 276 #endif  /* _UDP_IMPL_H */