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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/stropts.h>
28 #include <sys/stream.h>
29 #include <sys/socket.h>
30 #include <net/if.h>
31 #define SOL2
32 #include <net/ppp_defs.h>
33 #include <net/pppio.h>
34 #include <net/sppptun.h>
35 #include <netinet/in.h>
36 #include <netinet/ip6.h>
37 #include <inet/common.h>
38 #include <inet/mib2.h>
39 #include <inet/ip.h>
40 #include <inet/ip6.h>
41 #include <sppp/sppp.h>
42 #include <sppptun/sppptun_impl.h>
43
44 #include <mdb/mdb_modapi.h>
45 #include <mdb/mdb_ks.h>
46 #include <stdio.h>
47
48 /* ****************** sppp ****************** */
49
50 static int
sppp_walk_init(mdb_walk_state_t * wsp)51 sppp_walk_init(mdb_walk_state_t *wsp)
52 {
53 if (mdb_readvar(&wsp->walk_addr, "sps_list") == -1) {
54 mdb_warn("failed to read sps_list");
55 return (WALK_ERR);
56 }
57
58 return (WALK_NEXT);
59 }
60
61 static int
sppp_walk_step(mdb_walk_state_t * wsp)62 sppp_walk_step(mdb_walk_state_t *wsp)
63 {
64 spppstr_t sps;
65 int status;
66
67 if (wsp->walk_addr == 0)
68 return (WALK_DONE);
69
70 if (mdb_vread(&sps, sizeof (sps), wsp->walk_addr) == -1) {
71 mdb_warn("can't read spppstr_t at %p", wsp->walk_addr);
72 return (WALK_ERR);
73 }
74
75 status = (wsp->walk_callback(wsp->walk_addr, &sps, wsp->walk_cbdata));
76
77 wsp->walk_addr = (uintptr_t)sps.sps_nextmn;
78 return (status);
79 }
80
81 static int
sps_format(uintptr_t addr,const spppstr_t * sps,uint_t * qfmt)82 sps_format(uintptr_t addr, const spppstr_t *sps, uint_t *qfmt)
83 {
84 sppa_t ppa;
85 queue_t upq;
86 uintptr_t upaddr, illaddr;
87 ill_t ill;
88 ipif_t ipif;
89
90 mdb_printf("%?p ", addr);
91 if (*qfmt)
92 mdb_printf("%?p ", sps->sps_rq);
93 if (sps->sps_ppa == NULL) {
94 mdb_printf("? unset ");
95 } else if (mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps->sps_ppa) ==
96 -1) {
97 mdb_printf("? ?%p ", sps->sps_ppa);
98 } else {
99 mdb_printf("%-6d sppp%-5d ", ppa.ppa_zoneid, ppa.ppa_ppa_id);
100 }
101 if (IS_SPS_CONTROL(sps)) {
102 mdb_printf("Control\n");
103 } else if (IS_SPS_PIOATTACH(sps)) {
104 mdb_printf("Stats\n");
105 } else if (sps->sps_dlstate == DL_UNATTACHED) {
106 mdb_printf("Unknown\n");
107 } else if (sps->sps_dlstate != DL_IDLE) {
108 mdb_printf("DLPI Unbound\n");
109 } else {
110 upaddr = (uintptr_t)sps->sps_rq;
111 upq.q_ptr = NULL;
112 illaddr = 0;
113 while (upaddr != 0) {
114 if (mdb_vread(&upq, sizeof (upq), upaddr) == -1) {
115 upq.q_ptr = NULL;
116 break;
117 }
118 if ((upaddr = (uintptr_t)upq.q_next) != 0)
119 illaddr = (uintptr_t)upq.q_ptr;
120 }
121 if (illaddr != 0) {
122 if (mdb_vread(&ill, sizeof (ill), illaddr) == -1 ||
123 mdb_vread(&ipif, sizeof (ipif),
124 (uintptr_t)ill.ill_ipif) == -1) {
125 illaddr = 0;
126 }
127 }
128
129 switch (sps->sps_req_sap) {
130 case ETHERTYPE_IP:
131 mdb_printf("DLPI IPv4 ");
132 if (*qfmt) {
133 mdb_printf("\n");
134 } else if (illaddr == 0) {
135 mdb_printf("(no addresses)\n");
136 } else {
137 /*
138 * SCCS oddity here -- % <capital> %
139 * suffers from keyword replacement.
140 * Avoid that by using ANSI string
141 * pasting.
142 */
143 mdb_printf("%I:%I" "%s\n",
144 ipif.ipif_lcl_addr, ipif.ipif_pp_dst_addr,
145 (ipif.ipif_next ? " ..." : ""));
146 }
147 break;
148 case ETHERTYPE_IPV6:
149 mdb_printf("DLPI IPv6 ");
150 if (*qfmt) {
151 mdb_printf("\n");
152 break;
153 }
154 if (illaddr == 0) {
155 mdb_printf("(no addresses)\n");
156 break;
157 }
158 mdb_printf("%N\n%?s%21s", &ipif.ipif_v6lcl_addr,
159 "", "");
160 mdb_printf("%N\n", &ipif.ipif_v6pp_dst_addr);
161 break;
162 case ETHERTYPE_ALLSAP:
163 mdb_printf("DLPI Snoop\n");
164 break;
165 default:
166 mdb_printf("DLPI SAP 0x%04X\n", sps->sps_req_sap);
167 break;
168 }
169 }
170
171 return (WALK_NEXT);
172 }
173
174 static int
sppp(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)175 sppp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
176 {
177 uint_t qfmt = FALSE;
178 spppstr_t sps;
179
180 if (mdb_getopts(argc, argv, 'q', MDB_OPT_SETBITS, TRUE, &qfmt, NULL) !=
181 argc)
182 return (DCMD_USAGE);
183
184 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
185 if (qfmt) {
186 mdb_printf("%<u>%?s %?s %-6s %-9s %s%</u>\n", "Address",
187 "RecvQ", "ZoneID", "Interface", "Type");
188 } else {
189 mdb_printf("%<u>%?s %-6s %-9s %s%</u>\n", "Address",
190 "ZoneID", "Interface", "Type");
191 }
192 }
193
194 if (flags & DCMD_ADDRSPEC) {
195 (void) mdb_vread(&sps, sizeof (sps), addr);
196 (void) sps_format(addr, &sps, &qfmt);
197 } else if (mdb_walk("sppp", (mdb_walk_cb_t)sps_format, &qfmt) == -1) {
198 mdb_warn("failed to walk sps_list");
199 return (DCMD_ERR);
200 }
201
202 return (DCMD_OK);
203 }
204
205 static int
sppa_walk_init(mdb_walk_state_t * wsp)206 sppa_walk_init(mdb_walk_state_t *wsp)
207 {
208 if (mdb_readvar(&wsp->walk_addr, "ppa_list") == -1) {
209 mdb_warn("failed to read ppa_list");
210 return (WALK_ERR);
211 }
212
213 return (WALK_NEXT);
214 }
215
216 static int
sppa_walk_step(mdb_walk_state_t * wsp)217 sppa_walk_step(mdb_walk_state_t *wsp)
218 {
219 sppa_t ppa;
220 int status;
221
222 if (wsp->walk_addr == 0)
223 return (WALK_DONE);
224
225 if (mdb_vread(&ppa, sizeof (ppa), wsp->walk_addr) == -1) {
226 mdb_warn("can't read spppstr_t at %p", wsp->walk_addr);
227 return (WALK_ERR);
228 }
229
230 status = (wsp->walk_callback(wsp->walk_addr, &ppa, wsp->walk_cbdata));
231
232 wsp->walk_addr = (uintptr_t)ppa.ppa_nextppa;
233 return (status);
234 }
235
236 /* ARGSUSED */
237 static int
ppa_format(uintptr_t addr,const sppa_t * ppa,uint_t * qfmt)238 ppa_format(uintptr_t addr, const sppa_t *ppa, uint_t *qfmt)
239 {
240 mdb_printf("%?p %-6d sppp%-5d %?p %?p\n", addr, ppa->ppa_zoneid,
241 ppa->ppa_ppa_id, ppa->ppa_ctl, ppa->ppa_lower_wq);
242
243 return (WALK_NEXT);
244 }
245
246 /* ARGSUSED */
247 static int
sppa(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)248 sppa(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
249 {
250 uint_t qfmt = FALSE;
251 sppa_t ppa;
252
253 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
254 mdb_printf("%<u>%?s %-6s %-9s %?s %?s%</u>\n", "Address",
255 "ZoneID", "Interface", "Control", "LowerQ");
256 }
257
258 if (flags & DCMD_ADDRSPEC) {
259 (void) mdb_vread(&ppa, sizeof (ppa), addr);
260 (void) ppa_format(addr, &ppa, &qfmt);
261 } else if (mdb_walk("sppa", (mdb_walk_cb_t)ppa_format, &qfmt) == -1) {
262 mdb_warn("failed to walk ppa_list");
263 return (DCMD_ERR);
264 }
265
266 return (DCMD_OK);
267 }
268
269 static void
sppp_qinfo(const queue_t * q,char * buf,size_t nbytes)270 sppp_qinfo(const queue_t *q, char *buf, size_t nbytes)
271 {
272 spppstr_t sps;
273 sppa_t ppa;
274
275 if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) ==
276 sizeof (sps)) {
277 if (sps.sps_ppa == NULL ||
278 mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps.sps_ppa) ==
279 -1) {
280 (void) mdb_snprintf(buf, nbytes, "minor %d",
281 sps.sps_mn_id);
282 } else {
283 (void) mdb_snprintf(buf, nbytes, "sppp%d",
284 ppa.ppa_ppa_id);
285 }
286 }
287 }
288
289 static uintptr_t
sppp_rnext(const queue_t * q)290 sppp_rnext(const queue_t *q)
291 {
292 spppstr_t sps;
293
294 if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) == sizeof (sps))
295 return ((uintptr_t)sps.sps_rq);
296
297 return (0);
298 }
299
300 static uintptr_t
sppp_wnext(const queue_t * q)301 sppp_wnext(const queue_t *q)
302 {
303 spppstr_t sps;
304 sppa_t ppa;
305
306 if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) != sizeof (sps))
307 return (0);
308
309 if (sps.sps_ppa != NULL &&
310 mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps.sps_ppa) ==
311 sizeof (ppa))
312 return ((uintptr_t)ppa.ppa_lower_wq);
313
314 return (0);
315 }
316
317 /* ****************** sppptun ****************** */
318
319 struct tcl_walk_data {
320 size_t tcl_nslots;
321 size_t walkpos;
322 tuncl_t *tcl_slots[1];
323 };
324
325 static void
tuncl_walk_fini(mdb_walk_state_t * wsp)326 tuncl_walk_fini(mdb_walk_state_t *wsp)
327 {
328 struct tcl_walk_data *twd;
329
330 if (wsp != NULL && wsp->walk_addr != 0) {
331 twd = (struct tcl_walk_data *)wsp->walk_addr;
332 mdb_free(twd, sizeof (*twd) + ((twd->tcl_nslots - 1) *
333 sizeof (twd->tcl_slots[0])));
334 wsp->walk_addr = 0;
335 }
336 }
337
338 static int
tuncl_walk_init(mdb_walk_state_t * wsp)339 tuncl_walk_init(mdb_walk_state_t *wsp)
340 {
341 size_t tcl_nslots;
342 tuncl_t **tcl_slots;
343 struct tcl_walk_data *twd;
344
345 if (wsp == NULL)
346 return (WALK_ERR);
347
348 if (wsp->walk_addr != 0)
349 tuncl_walk_fini(wsp);
350
351 if (mdb_readvar(&tcl_nslots, "tcl_nslots") == -1) {
352 mdb_warn("failed to read tcl_nslots");
353 return (WALK_ERR);
354 }
355
356 if (tcl_nslots == 0)
357 return (WALK_DONE);
358
359 if (mdb_readvar(&tcl_slots, "tcl_slots") == -1) {
360 mdb_warn("failed to read tcl_slots");
361 return (WALK_ERR);
362 }
363
364 twd = (struct tcl_walk_data *)mdb_alloc(sizeof (*twd) +
365 (tcl_nslots - 1) * sizeof (*tcl_slots), UM_NOSLEEP);
366 if (twd == NULL)
367 return (WALK_ERR);
368 twd->tcl_nslots = tcl_nslots;
369 twd->walkpos = 0;
370 wsp->walk_addr = (uintptr_t)twd;
371
372 if (mdb_vread(twd->tcl_slots, tcl_nslots * sizeof (twd->tcl_slots[0]),
373 (uintptr_t)tcl_slots) == -1) {
374 mdb_warn("can't read tcl_slots at %p", tcl_slots);
375 tuncl_walk_fini(wsp);
376 return (WALK_ERR);
377 }
378
379 return (WALK_NEXT);
380 }
381
382 static int
tuncl_walk_step(mdb_walk_state_t * wsp)383 tuncl_walk_step(mdb_walk_state_t *wsp)
384 {
385 tuncl_t tcl;
386 int status;
387 struct tcl_walk_data *twd;
388 uintptr_t addr;
389
390 if (wsp == NULL || wsp->walk_addr == 0)
391 return (WALK_DONE);
392
393 twd = (struct tcl_walk_data *)wsp->walk_addr;
394
395 while (twd->walkpos < twd->tcl_nslots &&
396 twd->tcl_slots[twd->walkpos] == NULL)
397 twd->walkpos++;
398 if (twd->walkpos >= twd->tcl_nslots)
399 return (WALK_DONE);
400
401 addr = (uintptr_t)twd->tcl_slots[twd->walkpos];
402 if (mdb_vread(&tcl, sizeof (tcl), addr) == -1) {
403 mdb_warn("can't read tuncl_t at %p", addr);
404 return (WALK_ERR);
405 }
406
407 status = wsp->walk_callback(addr, &tcl, wsp->walk_cbdata);
408
409 twd->walkpos++;
410 return (status);
411 }
412
413 /* ARGSUSED */
414 static int
tuncl_format(uintptr_t addr,const tuncl_t * tcl,uint_t * qfmt)415 tuncl_format(uintptr_t addr, const tuncl_t *tcl, uint_t *qfmt)
416 {
417 mdb_printf("%?p %-6d %?p %?p", addr, tcl->tcl_zoneid, tcl->tcl_data_tll,
418 tcl->tcl_ctrl_tll);
419 mdb_printf(" %-2d %04X %04X ", tcl->tcl_style,
420 tcl->tcl_lsessid, tcl->tcl_rsessid);
421 if (tcl->tcl_flags & TCLF_DAEMON) {
422 mdb_printf("<daemon>\n");
423 } else {
424 mdb_printf("sppp%d\n", tcl->tcl_unit);
425 }
426
427 return (WALK_NEXT);
428 }
429
430 /* ARGSUSED */
431 static int
tuncl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)432 tuncl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
433 {
434 uint_t qfmt = FALSE;
435 tuncl_t tcl;
436
437 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
438 mdb_printf("%<u>%?s %-6s %?s %?s Ty LSes RSes %s%</u>\n",
439 "Address", "ZoneID", "Data", "Control", "Interface");
440 }
441
442 if (flags & DCMD_ADDRSPEC) {
443 if (mdb_vread(&tcl, sizeof (tcl), addr) == -1)
444 mdb_warn("failed to read tuncl_t at %p", addr);
445 else
446 tuncl_format(addr, &tcl, &qfmt);
447 } else if (mdb_walk("tuncl", (mdb_walk_cb_t)tuncl_format, &qfmt) ==
448 -1) {
449 mdb_warn("failed to walk tcl_slots");
450 return (DCMD_ERR);
451 }
452
453 return (DCMD_OK);
454 }
455
456 struct tll_walk_data {
457 void *listhead;
458 void *next;
459 };
460
461 static void
tunll_walk_fini(mdb_walk_state_t * wsp)462 tunll_walk_fini(mdb_walk_state_t *wsp)
463 {
464 struct tll_walk_data *twd;
465
466 if (wsp != NULL && wsp->walk_addr != 0) {
467 twd = (struct tll_walk_data *)wsp->walk_addr;
468 mdb_free(twd, sizeof (*twd));
469 wsp->walk_addr = 0;
470 }
471 }
472
473 static int
tunll_walk_init(mdb_walk_state_t * wsp)474 tunll_walk_init(mdb_walk_state_t *wsp)
475 {
476 GElf_Sym sym;
477 struct tll_walk_data *twd;
478 struct qelem tunll_list;
479
480 if (wsp->walk_addr != 0)
481 tunll_walk_fini(wsp);
482
483 if (mdb_lookup_by_obj("sppptun", "tunll_list", &sym) != 0) {
484 mdb_warn("failed to find tunll_list");
485 return (WALK_ERR);
486 }
487
488 if (mdb_vread(&tunll_list, sizeof (tunll_list),
489 (uintptr_t)sym.st_value) == -1) {
490 mdb_warn("can't read tunll_list at %p",
491 (uintptr_t)sym.st_value);
492 return (WALK_ERR);
493 }
494
495 twd = (struct tll_walk_data *)mdb_alloc(sizeof (*twd), UM_NOSLEEP);
496 if (twd == NULL)
497 return (WALK_ERR);
498 twd->listhead = (void *)(uintptr_t)sym.st_value;
499 twd->next = (void *)tunll_list.q_forw;
500 wsp->walk_addr = (uintptr_t)twd;
501
502 return (WALK_NEXT);
503 }
504
505 static int
tunll_walk_step(mdb_walk_state_t * wsp)506 tunll_walk_step(mdb_walk_state_t *wsp)
507 {
508 struct tll_walk_data *twd;
509 tunll_t tll;
510 int status;
511 uintptr_t addr;
512
513 if (wsp == NULL || wsp->walk_addr == 0)
514 return (WALK_DONE);
515
516 twd = (struct tll_walk_data *)wsp->walk_addr;
517 if (twd->next == NULL || twd->next == twd->listhead)
518 return (WALK_DONE);
519
520 /* LINTED */
521 addr = (uintptr_t)TO_TLL(twd->next);
522 if (mdb_vread(&tll, sizeof (tll), addr) == -1) {
523 mdb_warn("can't read tunll_t at %p", addr);
524 return (WALK_ERR);
525 }
526
527 status = wsp->walk_callback(addr, &tll, wsp->walk_cbdata);
528
529 twd->next = (void *)tll.tll_next;
530 return (status);
531 }
532
533 /* ARGSUSED */
534 static int
tunll_format(uintptr_t addr,const tunll_t * tll,uint_t * qfmt)535 tunll_format(uintptr_t addr, const tunll_t *tll, uint_t *qfmt)
536 {
537 mdb_printf("%?p %-6d %-14s %?p", addr, tll->tll_zoneid, tll->tll_name,
538 tll->tll_defcl);
539 if (tll->tll_style == PTS_PPPOE) {
540 mdb_printf(" %x:%x:%x:%x:%x:%x",
541 tll->tll_lcladdr.pta_pppoe.ptma_mac[0],
542 tll->tll_lcladdr.pta_pppoe.ptma_mac[1],
543 tll->tll_lcladdr.pta_pppoe.ptma_mac[2],
544 tll->tll_lcladdr.pta_pppoe.ptma_mac[3],
545 tll->tll_lcladdr.pta_pppoe.ptma_mac[4],
546 tll->tll_lcladdr.pta_pppoe.ptma_mac[5]);
547 }
548 mdb_printf("\n");
549
550 return (WALK_NEXT);
551 }
552
553 /* ARGSUSED */
554 static int
tunll(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)555 tunll(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
556 {
557 uint_t qfmt = FALSE;
558 tunll_t tll;
559
560 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
561 mdb_printf("%<u>%?s %-6s %-14s %?s %s%</u>\n", "Address",
562 "ZoneID", "Interface Name", "Daemon", "Local Address");
563 }
564
565 if (flags & DCMD_ADDRSPEC) {
566 if (mdb_vread(&tll, sizeof (tll), addr) == -1)
567 mdb_warn("failed to read tunll_t at %p", addr);
568 else
569 tunll_format(addr, &tll, &qfmt);
570 } else if (mdb_walk("tunll", (mdb_walk_cb_t)tunll_format, &qfmt) ==
571 -1) {
572 mdb_warn("failed to walk tunll_list");
573 return (DCMD_ERR);
574 }
575
576 return (DCMD_OK);
577 }
578
579 union tun_state {
580 uint32_t tunflags;
581 tuncl_t tcl;
582 tunll_t tll;
583 };
584
585 static int
tun_state_read(void * ptr,union tun_state * ts)586 tun_state_read(void *ptr, union tun_state *ts)
587 {
588 /*
589 * First, get the flags on this structure. This is either a
590 * tuncl_t or a tunll_t.
591 */
592 if (mdb_vread(&ts->tunflags, sizeof (ts->tunflags), (uintptr_t)ptr) ==
593 sizeof (ts->tunflags)) {
594 if (ts->tunflags & TCLF_ISCLIENT) {
595 if (mdb_vread(&ts->tcl, sizeof (ts->tcl),
596 (uintptr_t)ptr) == sizeof (ts->tcl)) {
597 return (0);
598 }
599 } else {
600 if (mdb_vread(&ts->tll, sizeof (ts->tll),
601 (uintptr_t)ptr) == sizeof (ts->tll)) {
602 return (0);
603 }
604 }
605 }
606 return (-1);
607 }
608
609 static void
sppptun_qinfo(const queue_t * q,char * buf,size_t nbytes)610 sppptun_qinfo(const queue_t *q, char *buf, size_t nbytes)
611 {
612 union tun_state ts;
613
614 if (tun_state_read(q->q_ptr, &ts) == -1)
615 return;
616
617 if (ts.tcl.tcl_flags & TCLF_ISCLIENT)
618 mdb_snprintf(buf, nbytes, "sppp%d client %04X",
619 ts.tcl.tcl_unit, ts.tcl.tcl_lsessid);
620 else
621 mdb_snprintf(buf, nbytes, "%s", ts.tll.tll_name);
622 }
623
624 static uintptr_t
sppptun_rnext(const queue_t * q)625 sppptun_rnext(const queue_t *q)
626 {
627 union tun_state ts;
628
629 if (tun_state_read(q->q_ptr, &ts) == -1)
630 return (0);
631
632 if (ts.tcl.tcl_flags & TCLF_ISCLIENT) {
633 return ((uintptr_t)ts.tcl.tcl_rq);
634 } else {
635 /* Not quite right, but ... */
636 return ((uintptr_t)ts.tll.tll_defcl);
637 }
638 }
639
640 static uintptr_t
sppptun_wnext(const queue_t * q)641 sppptun_wnext(const queue_t *q)
642 {
643 union tun_state ts;
644
645 if (tun_state_read(q->q_ptr, &ts) == -1)
646 return (0);
647
648 if (ts.tcl.tcl_flags & TCLF_ISCLIENT) {
649 if (ts.tcl.tcl_data_tll == NULL)
650 return (0);
651 if (mdb_vread(&ts.tll, sizeof (ts.tll),
652 (uintptr_t)ts.tcl.tcl_data_tll) != sizeof (ts.tll)) {
653 return (0);
654 }
655 }
656 return ((uintptr_t)ts.tll.tll_wq);
657 }
658
659 static const mdb_dcmd_t dcmds[] = {
660 { "sppp", "[-q]", "display PPP stream state structures", sppp },
661 { "sppa", "", "display PPP attachment state structures", sppa },
662 { "tuncl", "", "display sppptun client stream state structures",
663 tuncl },
664 { "tunll", "", "display sppptun lower stream state structures",
665 tunll },
666 { NULL }
667 };
668
669 static const mdb_walker_t walkers[] = {
670 { "sppp", "walk active spppstr_t structures",
671 sppp_walk_init, sppp_walk_step, NULL },
672 { "sppa", "walk active sppa_t structures",
673 sppa_walk_init, sppa_walk_step, NULL },
674 { "tuncl", "walk active tuncl_t structures",
675 tuncl_walk_init, tuncl_walk_step, tuncl_walk_fini },
676 { "tunll", "walk active tunll_t structures",
677 tunll_walk_init, tunll_walk_step, tunll_walk_fini },
678 { NULL }
679 };
680
681 static const mdb_qops_t sppp_qops = {
682 .q_info = sppp_qinfo,
683 .q_rnext = sppp_rnext,
684 .q_wnext = sppp_wnext,
685 };
686
687 static const mdb_qops_t sppptun_qops = {
688 .q_info = sppptun_qinfo,
689 .q_rnext = sppptun_rnext,
690 .q_wnext = sppptun_wnext,
691 };
692
693 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
694
695 const mdb_modinfo_t *
_mdb_init(void)696 _mdb_init(void)
697 {
698 GElf_Sym sym;
699
700 if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym) == 0)
701 mdb_qops_install(&sppp_qops, (uintptr_t)sym.st_value);
702
703 if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym) == 0)
704 mdb_qops_install(&sppptun_qops, (uintptr_t)sym.st_value);
705
706 return (&modinfo);
707 }
708
709 void
_mdb_fini(void)710 _mdb_fini(void)
711 {
712 GElf_Sym sym;
713
714 if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym) == 0)
715 mdb_qops_remove(&sppptun_qops, (uintptr_t)sym.st_value);
716
717 if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym) == 0)
718 mdb_qops_remove(&sppp_qops, (uintptr_t)sym.st_value);
719 }
720