1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/types.h>
27#include <sys/conf.h>
28#include <sys/modctl.h>
29#include <sys/stream.h>
30#include <sys/strsubr.h>
31#include <sys/stropts.h>
32#define	_SUN_TPI_VERSION 2
33#include <sys/ddi.h>
34#include <sys/sunddi.h>
35#include <sys/cmn_err.h>
36#include <sys/debug.h>
37#include <sys/vtrace.h>
38#include <sys/errno.h>
39#include <inet/common.h>
40#include <inet/led.h>
41#include <inet/mi.h>
42#include <inet/nd.h>
43#include <sys/strsun.h>
44
45#include <fs/sockfs/nl7c.h>
46#include <fs/sockfs/nl7curi.h>
47
48#include <inet/nca/nca.h>
49#include <inet/nca/ncalogd.h>
50
51/*
52 * This file is for NCA compatability, specifically it provides ndd
53 * support for existing NCA ndd ...
54 */
55
56extern boolean_t	nl7c_logd_enabled;
57extern nca_fio_t	*nl7c_logd_fio;
58extern clock_t		nl7c_uri_ttl;
59extern boolean_t	nl7c_use_kmem;
60extern uint64_t		nl7c_file_prefetch;
61extern uint64_t		nl7c_uri_max;
62extern uint64_t		nl7c_uri_bytes;
63
64extern void		nl7c_mi_report_addr(mblk_t *);
65
66#define	MS	1L
67#define	SECONDS	(1000 * MS)
68#define	MINUTES	(60 * SECONDS)
69#define	HOURS	(60 * MINUTES)
70#define	DAYS	(24 * HOURS)
71
72#define	PARAM_MAX UINT_MAX
73#define	PARAML_MAX ULONG_MAX
74
75#include <inet/nca/ncandd.h>
76
77uint32_t nca_major_version = 1;
78uint32_t nca_minor_version = 3;
79uint32_t nca_httpd_version = NCA_HTTP_VERSION1;
80uint32_t nca_logd_version = NCA_LOG_VERSION1;
81
82caddr_t	nca_g_nd;	/* Head of 'named dispatch' variable list */
83
84/*
85 * min, max, and value are int64_t's, addr is the optional address of an
86 * external int64_t to be updated at init/set, name is the ndd name used
87 * to access. Note, if min == max then only get is allowed, i.e. RO.
88 */
89
90/* BEGIN CSTYLED */
91ncaparam_t	nca_param_arr[] = {
92 /*min	max		value		name */
93 { 0,	1,		1,		"nca_log_cycle"},
94 { 0,	1,		0,		"no_caching"},
95 { 0,	PARAML_MAX,    	0,		"nca_log_size"},
96 { 0,	PARAM_MAX,     	10000000,	"nca_max_cache_size"},
97 { 0,	PARAM_MAX,	300*SECONDS,	"nca_http_timeout"},
98 { 0,	PARAM_MAX,	15*SECONDS,	"nca_http_keep_alive_timeout"},
99 { 0,	PARAM_MAX,	100,		"nca_http_keep_alive_max"},
100 { 0,	1,		1,		"nca_inq_nointr"},
101 { 0,	1,		1,		"nca_use_hwcksum"},
102 { 0,	PARAM_MAX,	0,		"nca_segmap_min_size"},
103};
104
105/*
106 * Obsolete ip variables, use "/dev/ip" instead.
107 */
108
109ncaparam_t	nca_ip_obsolete_arr[] = {
110 { 0, 0, 0, "ip_forwarding"},
111 { 0, 0, 0, "ip_respond_to_address_mask_broadcast"},
112 { 0, 0, 0, "ip_respond_to_echo_broadcast"},
113 { 0, 0, 0, "ip_respond_to_timestamp"},
114 { 0, 0, 0, "ip_respond_to_timestamp_broadcast"},
115 { 0, 0, 0, "ip_send_redirects"},
116 { 0, 0, 0, "ip_forward_directed_broadcasts"},
117 { 0, 0, 0, "ip_debug"},
118 { 0, 0, 0, "ip_mrtdebug"},
119 { 0, 0, 0, "ip_ire_cleanup_interval" },
120 { 0, 0, 0, "ip_ire_flush_interval" },
121 { 0, 0, 0, "ip_ire_redirect_interval" },
122 { 0, 0, 0, "ip_def_ttl" },
123 { 0, 0, 0, "ip_forward_src_routed"},
124 { 0, 0, 0, "ip_wroff_extra" },
125 { 0, 0, 0, "ip_ire_pathmtu_interval" },
126 { 0, 0, 0, "ip_icmp_return_data_bytes" },
127 { 0, 0, 0, "ip_send_source_quench" },
128 { 0, 0, 0, "ip_path_mtu_discovery" },
129 { 0, 0, 0, "ip_ignore_delete_time" },
130 { 0, 0, 0, "ip_ignore_redirect" },
131 { 0, 0, 0, "ip_output_queue" },
132 { 0, 0, 0, "ip_broadcast_ttl" },
133 { 0, 0, 0, "ip_icmp_err_interval" },
134 { 0, 0, 0, "ip_reass_queue_bytes" },
135 { 0, 0, 0, "ip_strict_dst_multihoming" },
136 { 0, 0, 0, "ip_addrs_per_if"},
137};
138
139/*
140 * Obsolete tcp variables, use "/dev/tcp" instead.
141 */
142
143ncaparam_t	nca_tcp_obsolete_arr[] = {
144 { 0, 0, 0, "tcp_time_wait_interval"},
145 { 0, 0, 0, "tcp_conn_req_max_q" },
146 { 0, 0, 0, "tcp_conn_req_max_q0" },
147 { 0, 0, 0, "tcp_conn_req_min" },
148 { 0, 0, 0, "tcp_conn_grace_period" },
149 { 0, 0, 0, "tcp_cwnd_max" },
150 { 0, 0, 0, "tcp_debug" },
151 { 0, 0, 0, "tcp_smallest_nonpriv_port"},
152 { 0, 0, 0, "tcp_ip_abort_cinterval"},
153 { 0, 0, 0, "tcp_ip_abort_linterval"},
154 { 0, 0, 0, "tcp_ip_abort_interval"},
155 { 0, 0, 0, "tcp_ip_notify_cinterval"},
156 { 0, 0, 0, "tcp_ip_notify_interval"},
157 { 0, 0, 0, "tcp_ip_ttl"},
158 { 0, 0, 0, "tcp_keepalive_interval"},
159 { 0, 0, 0, "tcp_maxpsz_multiplier" },
160 { 0, 0, 0, "tcp_mss_def"},
161 { 0, 0, 0, "tcp_mss_max"},
162 { 0, 0, 0, "tcp_mss_min"},
163 { 0, 0, 0, "tcp_naglim_def"},
164 { 0, 0, 0, "tcp_rexmit_interval_initial"},
165 { 0, 0, 0, "tcp_rexmit_interval_max"},
166 { 0, 0, 0, "tcp_rexmit_interval_min"},
167 { 0, 0, 0, "tcp_wroff_xtra" },
168 { 0, 0, 0, "tcp_deferred_ack_interval" },
169 { 0, 0, 0, "tcp_snd_lowat_fraction" },
170 { 0, 0, 0, "tcp_sth_rcv_hiwat" },
171 { 0, 0, 0, "tcp_sth_rcv_lowat" },
172 { 0, 0, 0, "tcp_dupack_fast_retransmit" },
173 { 0, 0, 0, "tcp_ignore_path_mtu" },
174 { 0, 0, 0, "tcp_rcv_push_wait" },
175 { 0, 0, 0, "tcp_smallest_anon_port"},
176 { 0, 0, 0, "tcp_largest_anon_port"},
177 { 0, 0, 0, "tcp_xmit_hiwat"},
178 { 0, 0, 0, "tcp_xmit_lowat"},
179 { 0, 0, 0, "tcp_recv_hiwat"},
180 { 0, 0, 0, "tcp_recv_hiwat_minmss"},
181 { 0, 0, 0, "tcp_fin_wait_2_flush_interval"},
182 { 0, 0, 0, "tcp_max_buf"},
183 { 0, 0, 0, "tcp_strong_iss"},
184 { 0, 0, 0, "tcp_rtt_updates"},
185 { 0, 0, 0, "tcp_wscale_always"},
186 { 0, 0, 0, "tcp_tstamp_always"},
187 { 0, 0, 0, "tcp_tstamp_if_wscale"},
188 { 0, 0, 0, "tcp_rexmit_interval_extra"},
189 { 0, 0, 0, "tcp_deferred_acks_max"},
190 { 0, 0, 0, "tcp_slow_start_after_idle"},
191 { 0, 0, 0, "tcp_slow_start_initial"},
192 { 0, 0, 0, "tcp_sack_permitted"},
193#ifdef DEBUG
194 { 0, 0, 0, "tcp_drop_oob"},
195#endif
196};
197
198/*
199 * Obsolete nca variables, just warn.
200 */
201
202ncaparam_t	nca_nca_obsolete_arr[] = {
203 { 0, 0, 0, "nca_ipport_table_bucket"},
204 { 0, 0, 0, "nca_ipport_table_size"},
205 { 0, 0, 0, "nca_ipport_table_expand"},
206 { 0, 0, 0, "nca_ipport_table_shrink"},
207 { 0, 0, 0, "nca_ip_virtual_hosting"},
208 { 0, 0, 0, "httpd_door_address"},
209 { 0, 0, 0, "httpd_door_path"},
210 { 0, 0, 0, "httpd_downdoor_path"},
211 { 0, 0, 0, "nca_ppmax"},
212 { 0, 0, 0, "nca_vpmax"},
213 { 0, 0, 0, "nca_use_segmap"},
214 { 0, 0, 0, "nca_availrmem"},
215 { 0, 0, 0, "nca_maxkmem"},
216 { 0, 0, 0, "nca_log_file"},
217 { 0, 0, 0, "conn_status"},
218 { 0, 0, 0, "conn_status_all"},
219 { 0, 0, 0, "nca_conn_req_max_q"},
220 { 0, 0, 0, "nca_conn_req_max_q0"},
221 { 0, 0, 0, "cache_clear"},
222 { 0, 0, 0, "nca_node_hash"},
223 { 0, 0, 0, "node_status"},
224#ifdef DEBUG
225 { 0, 0, 0, "nca_debug_counter"},
226#endif
227};
228/* END CSTYLED */
229
230static int
231/*ARGSUSED*/
232nl7c_uri_ttl_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
233{
234	(void) mi_mpprintf(mp, "%ld", nl7c_uri_ttl);
235	return (0);
236}
237
238static int
239/*ARGSUSED*/
240nl7c_uri_ttl_set(queue_t *q, mblk_t *mp, char *value, caddr_t nu, cred_t *cr)
241{
242	if (ddi_strtol(value, NULL, 10, &nl7c_uri_ttl) != 0)
243		return (EINVAL);
244	return (0);
245}
246
247static int
248/*ARGSUSED*/
249nca_logging_on_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
250{
251	(void) mi_mpprintf(mp, "%d", nl7c_logd_enabled);
252	return (0);
253}
254
255static int
256/*ARGSUSED*/
257nca_logging_on_set(queue_t *q, mblk_t *mp, char *value, caddr_t nu, cred_t *cr)
258{
259	long new_value;
260
261	if (ddi_strtol(value, NULL, 10, &new_value) != 0 || new_value < 0 ||
262	    new_value > 1) {
263		return (EINVAL);
264	}
265	if (nca_fio_cnt(nl7c_logd_fio) == 0)
266		return (EINVAL);
267	nl7c_logd_enabled = new_value;
268
269	return (0);
270}
271
272static int
273/*ARGSUSED*/
274nca_version_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
275{
276	(void) mi_mpprintf(mp, "%d.%d", nca_major_version, nca_minor_version);
277	return (0);
278}
279
280static int
281/*ARGSUSED*/
282nca_httpd_version_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
283{
284	(void) mi_mpprintf(mp, "%d", nca_httpd_version);
285	return (0);
286}
287
288static int
289/*ARGSUSED*/
290nca_logd_version_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
291{
292	(void) mi_mpprintf(mp, "%d", nca_logd_version);
293	return (0);
294}
295
296static int
297/*ARGSUSED*/
298nca_httpd_door_inst_get(queue_t *q, mblk_t *mp, caddr_t nu, cred_t *cr)
299{
300	nl7c_mi_report_addr(mp);
301	return (0);
302}
303
304static int
305/*ARGSUSED*/
306nca_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
307{
308	ncaparam_t	*ncapa = (ncaparam_t *)cp;
309
310	(void) mi_mpprintf(mp, "%ld", ncapa->param_val);
311	return (0);
312}
313
314static int
315/*ARGSUSED*/
316nca_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
317{
318	ulong_t		new_value;
319	ncaparam_t	*ncapa = (ncaparam_t *)cp;
320
321	if (ddi_strtoul(value, NULL, 10, &new_value) != 0 ||
322	    new_value < ncapa->param_min || new_value > ncapa->param_max) {
323		return (EINVAL);
324	}
325	ncapa->param_val = new_value;
326	return (0);
327}
328
329static int
330/*ARGSUSED*/
331nca_obsolete(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
332{
333	(void) mi_mpprintf(mp, "obsolete");
334	return (0);
335}
336
337static int
338/*ARGSUSED*/
339nca_ip_obsolete(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
340{
341	(void) mi_mpprintf(mp, "obsolete for /dev/nca, use /dev/ip");
342	return (0);
343}
344
345static int
346/*ARGSUSED*/
347nca_tcp_obsolete(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
348{
349	(void) mi_mpprintf(mp, "obsolete for /dev/nca, use /dev/tcp");
350	return (0);
351}
352
353static int
354/*ARGSUSED*/
355nca_nca_obsolete(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
356{
357	(void) mi_mpprintf(mp, "obsolete for /dev/nca");
358	return (0);
359}
360
361static boolean_t
362nca_param_register(ncaparam_t *ncapa, int cnt)
363{
364	for (; cnt-- > 0; ncapa++) {
365		if (ncapa->param_name && ncapa->param_name[0]) {
366			if (!nd_load(&nca_g_nd, ncapa->param_name,
367			    nca_param_get, nca_param_set,
368			    (caddr_t)ncapa)) {
369				goto error;
370			}
371		}
372
373	}
374	if (!nd_load(&nca_g_nd, "nca_version", nca_version_get, nil(pfi_t),
375	    nil(caddr_t))) {
376		goto error;
377	}
378	if (!nd_load(&nca_g_nd, "nca_logd_version", nca_logd_version_get,
379	    nil(pfi_t), nil(caddr_t))) {
380		goto error;
381	}
382	if (!nd_load(&nca_g_nd, "nca_logging_on", nca_logging_on_get,
383	    nca_logging_on_set, nil(caddr_t))) {
384		goto error;
385	}
386
387	if (!nd_load(&nca_g_nd, "uri_time_to_live", nl7c_uri_ttl_get,
388	    nl7c_uri_ttl_set, nil(caddr_t))) {
389		goto error;
390	}
391	if (!nd_load(&nca_g_nd, "nca_httpd_version", nca_httpd_version_get,
392	    nil(pfi_t), nil(caddr_t))) {
393		goto error;
394	}
395	if (!nd_load(&nca_g_nd, "httpd_door_instance", nca_httpd_door_inst_get,
396	    nil(pfi_t), nil(caddr_t))) {
397		nd_free(&nca_g_nd);
398		return (B_FALSE);
399	}
400
401	ncapa = nca_ip_obsolete_arr;
402	cnt = A_CNT(nca_ip_obsolete_arr);
403	for (; cnt-- > 0; ncapa++) {
404		if (ncapa->param_name && ncapa->param_name[0]) {
405			if (!nd_load(&nca_g_nd, ncapa->param_name,
406			    nca_ip_obsolete, NULL, (caddr_t)ncapa)) {
407				goto error;
408			}
409		}
410
411	}
412
413	ncapa = nca_tcp_obsolete_arr;
414	cnt = A_CNT(nca_tcp_obsolete_arr);
415	for (; cnt-- > 0; ncapa++) {
416		if (ncapa->param_name && ncapa->param_name[0]) {
417			if (!nd_load(&nca_g_nd, ncapa->param_name,
418			    nca_tcp_obsolete, NULL, (caddr_t)ncapa)) {
419				goto error;
420			}
421		}
422
423	}
424
425	ncapa = nca_nca_obsolete_arr;
426	cnt = A_CNT(nca_nca_obsolete_arr);
427	for (; cnt-- > 0; ncapa++) {
428		if (ncapa->param_name && ncapa->param_name[0]) {
429			if (!nd_load(&nca_g_nd, ncapa->param_name,
430			    nca_nca_obsolete, NULL, (caddr_t)ncapa)) {
431				goto error;
432			}
433		}
434
435	}
436
437	return (B_TRUE);
438
439error:
440	nd_free(&nca_g_nd);
441	return (B_FALSE);
442}
443
444void
445nl7c_nca_init(void)
446{
447	if (! nca_g_nd) {
448		if (! nca_param_register(nca_param_arr, A_CNT(nca_param_arr)))
449			cmn_err(CE_WARN,
450			    "nl7c: /dev/nca ndd initialization failed.");
451	}
452}
453