udp_impl.h revision f4b3ec61df05330d25f55a36b975b4d7519fdeb1
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _UDP_IMPL_H
#define _UDP_IMPL_H
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* UDP implementation private declarations. These interfaces are
* used to build the IP module and are not meant to be accessed
* by any modules except IP itself. They are undocumented and are
* subject to change without notice.
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _KERNEL
#include <sys/int_types.h>
#include <sys/netstack.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <inet/common.h>
#include <inet/ip.h>
#include <inet/optcom.h>
#define UDP_MOD_ID 5607
/* udp_mode. UDP_MT_HOT and UDP_SQUEUE are stable modes. Rest are transient */
typedef enum {
UDP_MT_HOT = 0, /* UDP endpoint is MT HOT */
UDP_MT_QUEUED = 1, /* Messages enqueued in udp_mphead */
UDP_QUEUED_SQUEUE = 2, /* Messages enqueued in conn_sqp */
UDP_SQUEUE = 3 /* Single threaded using squeues */
} udp_mode_t;
/*
* Bind hash list size and hash function. It has to be a power of 2 for
* hashing.
*/
#define UDP_BIND_FANOUT_SIZE 512
#define UDP_BIND_HASH(lport, size) \
((ntohs((uint16_t)lport)) & (size - 1))
/* UDP bind fanout hash structure. */
typedef struct udp_fanout_s {
struct udp_s *uf_udp;
kmutex_t uf_lock;
#if defined(_LP64) || defined(_I32LPx)
char uf_pad[48];
#else
char uf_pad[56];
#endif
} udp_fanout_t;
/* Kstats */
typedef struct udp_stat { /* Class "net" kstats */
kstat_named_t udp_ip_send;
kstat_named_t udp_ip_ire_send;
kstat_named_t udp_ire_null;
kstat_named_t udp_drain;
kstat_named_t udp_sock_fallback;
kstat_named_t udp_rrw_busy;
kstat_named_t udp_rrw_msgcnt;
kstat_named_t udp_out_sw_cksum;
kstat_named_t udp_out_sw_cksum_bytes;
kstat_named_t udp_out_opt;
kstat_named_t udp_out_err_notconn;
kstat_named_t udp_out_err_output;
kstat_named_t udp_out_err_tudr;
kstat_named_t udp_in_pktinfo;
kstat_named_t udp_in_recvdstaddr;
kstat_named_t udp_in_recvopts;
kstat_named_t udp_in_recvif;
kstat_named_t udp_in_recvslla;
kstat_named_t udp_in_recvucred;
kstat_named_t udp_in_recvttl;
kstat_named_t udp_in_recvhopopts;
kstat_named_t udp_in_recvhoplimit;
kstat_named_t udp_in_recvdstopts;
kstat_named_t udp_in_recvrtdstopts;
kstat_named_t udp_in_recvrthdr;
kstat_named_t udp_in_recvpktinfo;
kstat_named_t udp_in_recvtclass;
kstat_named_t udp_in_timestamp;
kstat_named_t udp_ip_recvpktinfo;
#ifdef DEBUG
kstat_named_t udp_data_conn;
kstat_named_t udp_data_notconn;
#endif
} udp_stat_t;
/* Named Dispatch Parameter Management Structure */
typedef struct udpparam_s {
uint32_t udp_param_min;
uint32_t udp_param_max;
uint32_t udp_param_value;
char *udp_param_name;
} udpparam_t;
#define UDP_NUM_EPRIV_PORTS 64
/*
* UDP stack instances
*/
struct udp_stack {
netstack_t *us_netstack; /* Common netstack */
uint_t us_bind_fanout_size;
udp_fanout_t *us_bind_fanout;
int us_num_epriv_ports;
in_port_t us_epriv_ports[UDP_NUM_EPRIV_PORTS];
/* Hint not protected by any lock */
in_port_t us_next_port_to_try;
IDP us_nd; /* Points to table of UDP ND variables. */
udpparam_t *us_param_arr; /* ndd variable table */
kstat_t *us_mibkp; /* kstats exporting mib data */
kstat_t *us_kstat;
udp_stat_t us_statistics;
mib2_udp_t us_udp_mib; /* SNMP fixed size info */
/*
* This controls the rate some ndd info report functions can be used
* by non-priviledged users. It stores the last time such info is
* requested. When those report functions are called again, this
* is checked with the current time and compare with the ndd param
* udp_ndd_get_info_interval.
*/
clock_t us_last_ndd_get_info_time;
/*
* The smallest anonymous port in the priviledged port range which UDP
* looks for free port. Use in the option UDP_ANONPRIVBIND.
*/
in_port_t us_min_anonpriv_port;
};
typedef struct udp_stack udp_stack_t;
/* Internal udp control structure, one per open stream */
typedef struct udp_s {
uint32_t udp_state; /* TPI state */
in_port_t udp_port; /* Port bound to this stream */
in_port_t udp_dstport; /* Connected port */
in6_addr_t udp_v6src; /* Source address of this stream */
in6_addr_t udp_bound_v6src; /* Explicitly bound address */
in6_addr_t udp_v6dst; /* Connected destination */
uint32_t udp_flowinfo; /* Connected flow id and tclass */
uint32_t udp_max_hdr_len; /* For write offset in stream head */
sa_family_t udp_family; /* Family from socket() call */
/*
* IP format that packets transmitted from this struct should use.
* Value can be IP4_VERSION or IPV6_VERSION.
*/
ushort_t udp_ipversion;
uint32_t udp_ip_snd_options_len; /* Len of IPv4 options */
uchar_t *udp_ip_snd_options; /* Ptr to IPv4 options */
uint32_t udp_ip_rcv_options_len; /* Len of IPv4 options recvd */
uchar_t *udp_ip_rcv_options; /* Ptr to IPv4 options recvd */
uchar_t udp_multicast_ttl; /* IP*_MULTICAST_TTL/HOPS */
ipaddr_t udp_multicast_if_addr; /* IP_MULTICAST_IF option */
uint_t udp_multicast_if_index; /* IPV6_MULTICAST_IF option */
int udp_bound_if; /* IP*_BOUND_IF option */
int udp_xmit_if; /* IP_XMIT_IF option */
conn_t *udp_connp;
uint32_t
udp_debug : 1, /* SO_DEBUG "socket" option. */
udp_dontroute : 1, /* SO_DONTROUTE "socket" option. */
udp_broadcast : 1, /* SO_BROADCAST "socket" option. */
udp_useloopback : 1, /* SO_USELOOPBACK "socket" option */
udp_reuseaddr : 1, /* SO_REUSEADDR "socket" option. */
udp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */
udp_recvdstaddr : 1, /* IP_RECVDSTADDR option */
udp_recvopts : 1, /* IP_RECVOPTS option */
udp_discon_pending : 1, /* T_DISCON_REQ in progress */
udp_unspec_source : 1, /* IP*_UNSPEC_SRC option */
udp_ip_recvpktinfo : 1, /* IPV[4,6]_RECVPKTINFO option */
udp_ipv6_recvhoplimit : 1, /* IPV6_RECVHOPLIMIT option */
udp_ipv6_recvhopopts : 1, /* IPV6_RECVHOPOPTS option */
udp_ipv6_recvdstopts : 1, /* IPV6_RECVDSTOPTS option */
udp_ipv6_recvrthdr : 1, /* IPV6_RECVRTHDR option */
udp_ipv6_recvtclass : 1, /* IPV6_RECVTCLASS */
udp_ipv6_recvpathmtu : 1, /* IPV6_RECVPATHMTU */
udp_anon_priv_bind : 1,
udp_exclbind : 1, /* ``exclusive'' binding */
udp_recvif : 1, /* IP_RECVIF option */
udp_recvslla : 1, /* IP_RECVSLLA option */
udp_recvttl : 1, /* IP_RECVTTL option */
udp_recvucred : 1, /* IP_RECVUCRED option */
udp_old_ipv6_recvdstopts : 1, /* old form of IPV6_DSTOPTS */
udp_ipv6_recvrthdrdstopts : 1, /* IPV6_RECVRTHDRDSTOPTS */
udp_rcvhdr : 1, /* UDP_RCVHDR option */
udp_issocket : 1, /* socket mode */
udp_direct_sockfs : 1, /* direct calls to/from sockfs */
udp_timestamp : 1, /* SO_TIMESTAMP "socket" option */
udp_anon_mlp : 1, /* SO_ANON_MLP */
udp_mac_exempt : 1, /* SO_MAC_EXEMPT */
udp_pad_to_bit_31 : 1;
uint8_t udp_type_of_service; /* IP_TOS option */
uint8_t udp_ttl; /* TTL or hoplimit */
ip6_pkt_t udp_sticky_ipp; /* Sticky options */
uint8_t *udp_sticky_hdrs; /* Prebuilt IPv6 hdrs */
uint_t udp_sticky_hdrs_len; /* Incl. ip6h and any ip6i */
struct udp_s *udp_bind_hash; /* Bind hash chain */
struct udp_s **udp_ptpbhn; /* Pointer to previous bind hash next. */
udp_mode_t udp_mode; /* Current mode of operation */
mblk_t *udp_mphead; /* Head of the queued operations */
mblk_t *udp_mptail; /* Tail of the queued operations */
uint_t udp_mpcount; /* Number of messages in the queue */
uint_t udp_reader_count; /* Number of reader threads */
uint_t udp_squeue_count; /* Number of messages in conn_sqp */
kmutex_t udp_drain_lock; /* lock for udp_rcv_list */
boolean_t udp_drain_qfull; /* drain queue is full */
mblk_t *udp_rcv_list_head; /* b_next chain of mblks */
mblk_t *udp_rcv_list_tail; /* last mblk in chain */
uint_t udp_rcv_cnt; /* total data in rcv_list */
uint_t udp_rcv_msgcnt; /* total messages in rcv_list */
size_t udp_rcv_hiwat; /* receive high watermark */
uint_t udp_label_len; /* length of security label */
uint_t udp_label_len_v6; /* len of v6 security label */
in6_addr_t udp_v6lastdst; /* most recent destination */
uint64_t udp_open_time; /* time when this was opened */
pid_t udp_open_pid; /* process id when this was opened */
udp_stack_t *udp_us; /* Stack instance for zone */
} udp_t;
#define udp_mib udp_us->us_udp_mib
/* UDP Protocol header */
/* UDP Protocol header aligned */
typedef struct udpahdr_s {
in_port_t uha_src_port; /* Source port */
in_port_t uha_dst_port; /* Destination port */
uint16_t uha_length; /* UDP length */
uint16_t uha_checksum; /* UDP checksum */
} udpha_t;
#define us_wroff_extra us_param_arr[0].udp_param_value
#define us_ipv4_ttl us_param_arr[1].udp_param_value
#define us_ipv6_hoplimit us_param_arr[2].udp_param_value
#define us_smallest_nonpriv_port us_param_arr[3].udp_param_value
#define us_do_checksum us_param_arr[4].udp_param_value
#define us_smallest_anon_port us_param_arr[5].udp_param_value
#define us_largest_anon_port us_param_arr[6].udp_param_value
#define us_xmit_hiwat us_param_arr[7].udp_param_value
#define us_xmit_lowat us_param_arr[8].udp_param_value
#define us_recv_hiwat us_param_arr[9].udp_param_value
#define us_max_buf us_param_arr[10].udp_param_value
#define us_ndd_get_info_interval us_param_arr[11].udp_param_value
#define UDP_STAT(us, x) ((us)->us_statistics.x.value.ui64++)
#define UDP_STAT_UPDATE(us, x, n) \
((us)->us_statistics.x.value.ui64 += (n))
#ifdef DEBUG
#define UDP_DBGSTAT(us, x) UDP_STAT(us, x)
#else
#define UDP_DBGSTAT(us, x)
#endif /* DEBUG */
extern major_t UDP6_MAJ;
extern int udp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
extern int udp_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
extern int udp_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *,
uint_t *, uchar_t *, void *, cred_t *, mblk_t *);
extern int udp_snmp_get(queue_t *, mblk_t *);
extern int udp_snmp_set(queue_t *, t_scalar_t, t_scalar_t, uchar_t *, int);
extern void udp_close_free(conn_t *);
extern void udp_quiesce_conn(conn_t *);
extern void udp_ddi_init(void);
extern void udp_ddi_destroy(void);
extern void udp_resume_bind(conn_t *, mblk_t *);
extern void udp_conn_recv(conn_t *, mblk_t *);
extern boolean_t udp_compute_checksum(netstack_t *);
extern void udp_wput_data(queue_t *, mblk_t *, struct sockaddr *,
socklen_t);
extern int udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name,
uchar_t *ptr);
extern int udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name,
uchar_t *ptr);
extern int udp_opt_set(queue_t *q, uint_t optset_context,
int level, int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk);
/*
* Object to represent database of options to search passed to
* {sock,tpi}optcom_req() interface routine to take care of option
* management and associated methods.
*/
extern optdb_obj_t udp_opt_obj;
extern uint_t udp_max_optsize;
#endif /* _KERNEL */
#ifdef __cplusplus
}
#endif
#endif /* _UDP_IMPL_H */