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