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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/tihdr.h>
29 #include <sys/policy.h>
30 #include <sys/tsol/tnet.h>
31 #include <sys/kstat.h>
32
33 #include <inet/common.h>
34 #include <inet/ip.h>
35 #include <inet/tcp.h>
36 #include <inet/tcp_impl.h>
37 #include <inet/tcp_stats.h>
38 #include <inet/kstatcom.h>
39 #include <inet/snmpcom.h>
40
41 static int tcp_kstat_update(kstat_t *, int);
42 static int tcp_kstat2_update(kstat_t *, int);
43 static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
44
45 static void tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *);
46 static void tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *);
47 static void tcp_clr_stats(tcp_stat_t *);
48
49 tcp_g_stat_t tcp_g_statistics;
50 kstat_t *tcp_g_kstat;
51
52 /* Translate TCP state to MIB2 TCP state. */
80 case TCPS_FIN_WAIT_2:
81 return (MIB2_TCP_finWait2);
82 case TCPS_TIME_WAIT:
83 return (MIB2_TCP_timeWait);
84 default:
85 return (0);
86 }
87 }
88
89 /*
90 * Return SNMP stuff in buffer in mpdata.
91 */
92 mblk_t *
93 tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
94 {
95 mblk_t *mpdata;
96 mblk_t *mp_conn_ctl = NULL;
97 mblk_t *mp_conn_tail;
98 mblk_t *mp_attr_ctl = NULL;
99 mblk_t *mp_attr_tail;
100 mblk_t *mp6_conn_ctl = NULL;
101 mblk_t *mp6_conn_tail;
102 mblk_t *mp6_attr_ctl = NULL;
103 mblk_t *mp6_attr_tail;
104 struct opthdr *optp;
105 mib2_tcpConnEntry_t tce;
106 mib2_tcp6ConnEntry_t tce6;
107 mib2_transportMLPEntry_t mlp;
108 connf_t *connfp;
109 int i;
110 boolean_t ispriv;
111 zoneid_t zoneid;
112 int v4_conn_idx;
113 int v6_conn_idx;
114 conn_t *connp = Q_TO_CONN(q);
115 tcp_stack_t *tcps;
116 ip_stack_t *ipst;
117 mblk_t *mp2ctl;
118 mib2_tcp_t tcp_mib;
119 size_t tcp_mib_size, tce_size, tce6_size;
120
121 /*
122 * make a copy of the original message
123 */
124 mp2ctl = copymsg(mpctl);
125
126 if (mpctl == NULL ||
127 (mpdata = mpctl->b_cont) == NULL ||
128 (mp_conn_ctl = copymsg(mpctl)) == NULL ||
129 (mp_attr_ctl = copymsg(mpctl)) == NULL ||
130 (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
131 (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
132 freemsg(mp_conn_ctl);
133 freemsg(mp_attr_ctl);
134 freemsg(mp6_conn_ctl);
135 freemsg(mp6_attr_ctl);
136 freemsg(mpctl);
137 freemsg(mp2ctl);
138 return (NULL);
139 }
140
141 ipst = connp->conn_netstack->netstack_ip;
142 tcps = connp->conn_netstack->netstack_tcp;
143
144 if (legacy_req) {
145 tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t);
146 tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t);
147 tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t);
148 } else {
149 tcp_mib_size = sizeof (mib2_tcp_t);
150 tce_size = sizeof (mib2_tcpConnEntry_t);
151 tce6_size = sizeof (mib2_tcp6ConnEntry_t);
152 }
153
154 bzero(&tcp_mib, sizeof (tcp_mib));
155
156 /* build table of connections -- need count in fixed part */
157 SET_MIB(tcp_mib.tcpRtoAlgorithm, 4); /* vanj */
158 SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min);
159 SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max);
160 SET_MIB(tcp_mib.tcpMaxConn, -1);
161 SET_MIB(tcp_mib.tcpCurrEstab, 0);
162
163 ispriv =
164 secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
165 zoneid = Q_TO_CONN(q)->conn_zoneid;
166
167 v4_conn_idx = v6_conn_idx = 0;
168 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
169
170 for (i = 0; i < CONN_G_HASH_SIZE; i++) {
171 ipst = tcps->tcps_netstack->netstack_ip;
172
173 connfp = &ipst->ips_ipcl_globalhash_fanout[i];
174
175 connp = NULL;
176
177 while ((connp =
178 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
179 tcp_t *tcp;
180 boolean_t needattr;
181
182 if (connp->conn_zoneid != zoneid)
183 continue; /* not in this zone */
184
185 tcp = connp->conn_tcp;
186 TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
187 tcp->tcp_ibsegs = 0;
188 TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
264 tce6.tcp6ConnEntryInfo.ce_suna = 0;
265 tce6.tcp6ConnEntryInfo.ce_rnxt =
266 tcp->tcp_rnxt - tcp->tcp_rack;
267 tce6.tcp6ConnEntryInfo.ce_rack = 0;
268 }
269
270 tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
271 tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
272 tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto;
273 tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss;
274 tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
275
276 tce6.tcp6ConnCreationProcess =
277 (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
278 connp->conn_cpid;
279 tce6.tcp6ConnCreationTime = connp->conn_open_time;
280
281 (void) snmp_append_data2(mp6_conn_ctl->b_cont,
282 &mp6_conn_tail, (char *)&tce6, tce6_size);
283
284 mlp.tme_connidx = v6_conn_idx++;
285 if (needattr)
286 (void) snmp_append_data2(mp6_attr_ctl->b_cont,
287 &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
288 }
289 /*
290 * Create an IPv4 table entry for IPv4 entries and also
291 * for IPv6 entries which are bound to in6addr_any
292 * but don't have IPV6_V6ONLY set.
293 * (i.e. anything an IPv4 peer could connect to)
294 */
295 if (connp->conn_ipversion == IPV4_VERSION ||
296 (tcp->tcp_state <= TCPS_LISTEN &&
297 !connp->conn_ipv6_v6only &&
298 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
299 if (connp->conn_ipversion == IPV6_VERSION) {
300 tce.tcpConnRemAddress = INADDR_ANY;
301 tce.tcpConnLocalAddress = INADDR_ANY;
302 } else {
303 tce.tcpConnRemAddress =
331 tcp->tcp_rnxt - tcp->tcp_rack;
332 tce.tcpConnEntryInfo.ce_rack = 0;
333 }
334
335 tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
336 tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
337 tce.tcpConnEntryInfo.ce_rto = tcp->tcp_rto;
338 tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss;
339 tce.tcpConnEntryInfo.ce_state =
340 tcp->tcp_state;
341
342 tce.tcpConnCreationProcess =
343 (connp->conn_cpid < 0) ?
344 MIB2_UNKNOWN_PROCESS :
345 connp->conn_cpid;
346 tce.tcpConnCreationTime = connp->conn_open_time;
347
348 (void) snmp_append_data2(mp_conn_ctl->b_cont,
349 &mp_conn_tail, (char *)&tce, tce_size);
350
351 mlp.tme_connidx = v4_conn_idx++;
352 if (needattr)
353 (void) snmp_append_data2(
354 mp_attr_ctl->b_cont,
355 &mp_attr_tail, (char *)&mlp,
356 sizeof (mlp));
357 }
358 }
359 }
360
361 tcp_sum_mib(tcps, &tcp_mib);
362
363 /* Fixed length structure for IPv4 and IPv6 counters */
364 SET_MIB(tcp_mib.tcpConnTableSize, tce_size);
365 SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size);
366
367 /*
368 * Synchronize 32- and 64-bit counters. Note that tcpInSegs and
369 * tcpOutSegs are not updated anywhere in TCP. The new 64 bits
370 * counters are used. Hence the old counters' values in tcp_sc_mib
400 qreply(q, mp_attr_ctl);
401
402 /* table of IPv6 connections... */
403 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
404 sizeof (struct T_optmgmt_ack)];
405 optp->level = MIB2_TCP6;
406 optp->name = MIB2_TCP6_CONN;
407 optp->len = msgdsize(mp6_conn_ctl->b_cont);
408 qreply(q, mp6_conn_ctl);
409
410 /* table of IPv6 MLP attributes... */
411 optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
412 sizeof (struct T_optmgmt_ack)];
413 optp->level = MIB2_TCP6;
414 optp->name = EXPER_XPORT_MLP;
415 optp->len = msgdsize(mp6_attr_ctl->b_cont);
416 if (optp->len == 0)
417 freemsg(mp6_attr_ctl);
418 else
419 qreply(q, mp6_attr_ctl);
420 return (mp2ctl);
421 }
422
423 /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests */
424 /* ARGSUSED */
425 int
426 tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
427 {
428 mib2_tcpConnEntry_t *tce = (mib2_tcpConnEntry_t *)ptr;
429
430 switch (level) {
431 case MIB2_TCP:
432 switch (name) {
433 case 13:
434 if (tce->tcpConnState != MIB2_TCP_deleteTCB)
435 return (0);
436 /* TODO: delete entry defined by tce */
437 return (1);
438 default:
439 return (0);
|
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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/tihdr.h>
29 #include <sys/policy.h>
30 #include <sys/tsol/tnet.h>
31 #include <sys/kstat.h>
32
33 #include <sys/strsun.h>
34 #include <sys/stropts.h>
35 #include <sys/strsubr.h>
36 #include <sys/socket.h>
37 #include <sys/socketvar.h>
38 #include <sys/uio.h>
39
40 #include <inet/common.h>
41 #include <inet/ip.h>
42 #include <inet/tcp.h>
43 #include <inet/tcp_impl.h>
44 #include <inet/tcp_stats.h>
45 #include <inet/kstatcom.h>
46 #include <inet/snmpcom.h>
47
48 static int tcp_kstat_update(kstat_t *, int);
49 static int tcp_kstat2_update(kstat_t *, int);
50 static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
51
52 static void tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *);
53 static void tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *);
54 static void tcp_clr_stats(tcp_stat_t *);
55
56 tcp_g_stat_t tcp_g_statistics;
57 kstat_t *tcp_g_kstat;
58
59 /* Translate TCP state to MIB2 TCP state. */
87 case TCPS_FIN_WAIT_2:
88 return (MIB2_TCP_finWait2);
89 case TCPS_TIME_WAIT:
90 return (MIB2_TCP_timeWait);
91 default:
92 return (0);
93 }
94 }
95
96 /*
97 * Return SNMP stuff in buffer in mpdata.
98 */
99 mblk_t *
100 tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
101 {
102 mblk_t *mpdata;
103 mblk_t *mp_conn_ctl = NULL;
104 mblk_t *mp_conn_tail;
105 mblk_t *mp_attr_ctl = NULL;
106 mblk_t *mp_attr_tail;
107 mblk_t *mp_pidnode_ctl = NULL;
108 mblk_t *mp_pidnode_tail;
109 mblk_t *mp6_conn_ctl = NULL;
110 mblk_t *mp6_conn_tail;
111 mblk_t *mp6_attr_ctl = NULL;
112 mblk_t *mp6_attr_tail;
113 mblk_t *mp6_pidnode_ctl = NULL;
114 mblk_t *mp6_pidnode_tail;
115 struct opthdr *optp;
116 mib2_tcpConnEntry_t tce;
117 mib2_tcp6ConnEntry_t tce6;
118 mib2_transportMLPEntry_t mlp;
119 connf_t *connfp;
120 int i;
121 boolean_t ispriv;
122 zoneid_t zoneid;
123 int v4_conn_idx;
124 int v6_conn_idx;
125 conn_t *connp = Q_TO_CONN(q);
126 tcp_stack_t *tcps;
127 ip_stack_t *ipst;
128 mblk_t *mp2ctl;
129 mib2_tcp_t tcp_mib;
130 size_t tcp_mib_size, tce_size, tce6_size;
131
132 conn_pid_node_list_hdr_t *cph;
133
134 /*
135 * make a copy of the original message
136 */
137 mp2ctl = copymsg(mpctl);
138
139 if (mpctl == NULL ||
140 (mpdata = mpctl->b_cont) == NULL ||
141 (mp_conn_ctl = copymsg(mpctl)) == NULL ||
142 (mp_attr_ctl = copymsg(mpctl)) == NULL ||
143 (mp_pidnode_ctl = copymsg(mpctl)) == NULL ||
144 (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
145 (mp6_attr_ctl = copymsg(mpctl)) == NULL ||
146 (mp6_pidnode_ctl = copymsg(mpctl)) == NULL) {
147 freemsg(mp_conn_ctl);
148 freemsg(mp_attr_ctl);
149 freemsg(mp_pidnode_ctl);
150 freemsg(mp6_conn_ctl);
151 freemsg(mp6_attr_ctl);
152 freemsg(mp6_pidnode_ctl);
153 freemsg(mpctl);
154 freemsg(mp2ctl);
155 return (NULL);
156 }
157
158 ipst = connp->conn_netstack->netstack_ip;
159 tcps = connp->conn_netstack->netstack_tcp;
160
161 if (legacy_req) {
162 tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t);
163 tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t);
164 tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t);
165 } else {
166 tcp_mib_size = sizeof (mib2_tcp_t);
167 tce_size = sizeof (mib2_tcpConnEntry_t);
168 tce6_size = sizeof (mib2_tcp6ConnEntry_t);
169 }
170
171 bzero(&tcp_mib, sizeof (tcp_mib));
172
173 /* build table of connections -- need count in fixed part */
174 SET_MIB(tcp_mib.tcpRtoAlgorithm, 4); /* vanj */
175 SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min);
176 SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max);
177 SET_MIB(tcp_mib.tcpMaxConn, -1);
178 SET_MIB(tcp_mib.tcpCurrEstab, 0);
179
180 ispriv =
181 secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
182 zoneid = Q_TO_CONN(q)->conn_zoneid;
183
184 v4_conn_idx = v6_conn_idx = 0;
185 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
186 mp_pidnode_tail = mp6_pidnode_tail = NULL;
187
188 for (i = 0; i < CONN_G_HASH_SIZE; i++) {
189 ipst = tcps->tcps_netstack->netstack_ip;
190
191 connfp = &ipst->ips_ipcl_globalhash_fanout[i];
192
193 connp = NULL;
194
195 while ((connp =
196 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
197 tcp_t *tcp;
198 boolean_t needattr;
199
200 if (connp->conn_zoneid != zoneid)
201 continue; /* not in this zone */
202
203 tcp = connp->conn_tcp;
204 TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
205 tcp->tcp_ibsegs = 0;
206 TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
282 tce6.tcp6ConnEntryInfo.ce_suna = 0;
283 tce6.tcp6ConnEntryInfo.ce_rnxt =
284 tcp->tcp_rnxt - tcp->tcp_rack;
285 tce6.tcp6ConnEntryInfo.ce_rack = 0;
286 }
287
288 tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
289 tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
290 tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto;
291 tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss;
292 tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
293
294 tce6.tcp6ConnCreationProcess =
295 (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
296 connp->conn_cpid;
297 tce6.tcp6ConnCreationTime = connp->conn_open_time;
298
299 (void) snmp_append_data2(mp6_conn_ctl->b_cont,
300 &mp6_conn_tail, (char *)&tce6, tce6_size);
301
302 /* my data */
303 /* push connt_t */
304 (void) snmp_append_data2(mp6_pidnode_ctl->b_cont,
305 &mp6_pidnode_tail, (char *)&tce6, tce6_size);
306
307 cph = conn_get_pid_list(connp);
308
309 /* push the header + conn pid nodes */
310 (void) snmp_append_data2(mp6_pidnode_ctl->b_cont,
311 &mp6_pidnode_tail,
312 (char *)cph, cph->cph_tot_size);
313
314 kmem_free(cph, cph->cph_tot_size);
315 /* end of my data */
316
317 mlp.tme_connidx = v6_conn_idx++;
318 if (needattr)
319 (void) snmp_append_data2(mp6_attr_ctl->b_cont,
320 &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
321 }
322 /*
323 * Create an IPv4 table entry for IPv4 entries and also
324 * for IPv6 entries which are bound to in6addr_any
325 * but don't have IPV6_V6ONLY set.
326 * (i.e. anything an IPv4 peer could connect to)
327 */
328 if (connp->conn_ipversion == IPV4_VERSION ||
329 (tcp->tcp_state <= TCPS_LISTEN &&
330 !connp->conn_ipv6_v6only &&
331 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
332 if (connp->conn_ipversion == IPV6_VERSION) {
333 tce.tcpConnRemAddress = INADDR_ANY;
334 tce.tcpConnLocalAddress = INADDR_ANY;
335 } else {
336 tce.tcpConnRemAddress =
364 tcp->tcp_rnxt - tcp->tcp_rack;
365 tce.tcpConnEntryInfo.ce_rack = 0;
366 }
367
368 tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
369 tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
370 tce.tcpConnEntryInfo.ce_rto = tcp->tcp_rto;
371 tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss;
372 tce.tcpConnEntryInfo.ce_state =
373 tcp->tcp_state;
374
375 tce.tcpConnCreationProcess =
376 (connp->conn_cpid < 0) ?
377 MIB2_UNKNOWN_PROCESS :
378 connp->conn_cpid;
379 tce.tcpConnCreationTime = connp->conn_open_time;
380
381 (void) snmp_append_data2(mp_conn_ctl->b_cont,
382 &mp_conn_tail, (char *)&tce, tce_size);
383
384 /* my data */
385 /* push connt_t */
386 (void) snmp_append_data2(mp_pidnode_ctl->b_cont,
387 &mp_pidnode_tail, (char *)&tce, tce_size);
388
389 cph = conn_get_pid_list(connp);
390
391 /* push the header + conn pid nodes */
392 (void) snmp_append_data2(mp_pidnode_ctl->b_cont,
393 &mp_pidnode_tail, (char *)cph,
394 cph->cph_tot_size);
395
396 kmem_free(cph, cph->cph_tot_size);
397 /* end of my code */
398
399 mlp.tme_connidx = v4_conn_idx++;
400 if (needattr)
401 (void) snmp_append_data2(
402 mp_attr_ctl->b_cont,
403 &mp_attr_tail, (char *)&mlp,
404 sizeof (mlp));
405 }
406 }
407 }
408
409 tcp_sum_mib(tcps, &tcp_mib);
410
411 /* Fixed length structure for IPv4 and IPv6 counters */
412 SET_MIB(tcp_mib.tcpConnTableSize, tce_size);
413 SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size);
414
415 /*
416 * Synchronize 32- and 64-bit counters. Note that tcpInSegs and
417 * tcpOutSegs are not updated anywhere in TCP. The new 64 bits
418 * counters are used. Hence the old counters' values in tcp_sc_mib
448 qreply(q, mp_attr_ctl);
449
450 /* table of IPv6 connections... */
451 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
452 sizeof (struct T_optmgmt_ack)];
453 optp->level = MIB2_TCP6;
454 optp->name = MIB2_TCP6_CONN;
455 optp->len = msgdsize(mp6_conn_ctl->b_cont);
456 qreply(q, mp6_conn_ctl);
457
458 /* table of IPv6 MLP attributes... */
459 optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
460 sizeof (struct T_optmgmt_ack)];
461 optp->level = MIB2_TCP6;
462 optp->name = EXPER_XPORT_MLP;
463 optp->len = msgdsize(mp6_attr_ctl->b_cont);
464 if (optp->len == 0)
465 freemsg(mp6_attr_ctl);
466 else
467 qreply(q, mp6_attr_ctl);
468
469
470 /* table of EXPER_XPORT_PROC_INFO ipv4 */
471 optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[
472 sizeof (struct T_optmgmt_ack)];
473 optp->level = MIB2_TCP;
474 optp->name = EXPER_XPORT_PROC_INFO;
475 optp->len = msgdsize(mp_pidnode_ctl->b_cont);
476 if (optp->len == 0)
477 freemsg(mp_pidnode_ctl);
478 else
479 qreply(q, mp_pidnode_ctl);
480
481 /* table of EXPER_XPORT_PROC_INFO ipv6 */
482 optp = (struct opthdr *)&mp6_pidnode_ctl->b_rptr[
483 sizeof (struct T_optmgmt_ack)];
484 optp->level = MIB2_TCP6;
485 optp->name = EXPER_XPORT_PROC_INFO;
486 optp->len = msgdsize(mp6_pidnode_ctl->b_cont);
487 if (optp->len == 0)
488 freemsg(mp6_pidnode_ctl);
489 else
490 qreply(q, mp6_pidnode_ctl);
491
492 return (mp2ctl);
493 }
494
495 /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests */
496 /* ARGSUSED */
497 int
498 tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
499 {
500 mib2_tcpConnEntry_t *tce = (mib2_tcpConnEntry_t *)ptr;
501
502 switch (level) {
503 case MIB2_TCP:
504 switch (name) {
505 case 13:
506 if (tce->tcpConnState != MIB2_TCP_deleteTCB)
507 return (0);
508 /* TODO: delete entry defined by tce */
509 return (1);
510 default:
511 return (0);
|