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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/stropts.h>
28 #include <sys/stream.h>
29 #include <sys/socket.h>
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>
41 #include <sppp/sppp.h>
42 #include <sppptun/sppptun_impl.h>
44 #include <mdb/mdb_modapi.h>
45 #include <mdb/mdb_ks.h>
48 /* ****************** sppp ****************** */
51 sppp_walk_init(mdb_walk_state_t
*wsp
)
53 if (mdb_readvar(&wsp
->walk_addr
, "sps_list") == -1) {
54 mdb_warn("failed to read sps_list");
62 sppp_walk_step(mdb_walk_state_t
*wsp
)
67 if (wsp
->walk_addr
== NULL
)
70 if (mdb_vread(&sps
, sizeof (sps
), wsp
->walk_addr
) == -1) {
71 mdb_warn("can't read spppstr_t at %p", wsp
->walk_addr
);
75 status
= (wsp
->walk_callback(wsp
->walk_addr
, &sps
, wsp
->walk_cbdata
));
77 wsp
->walk_addr
= (uintptr_t)sps
.sps_nextmn
;
82 sps_format(uintptr_t addr
, const spppstr_t
*sps
, uint_t
*qfmt
)
86 uintptr_t upaddr
, illaddr
;
90 mdb_printf("%?p ", addr
);
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
) ==
97 mdb_printf("? ?%p ", sps
->sps_ppa
);
99 mdb_printf("%-6d sppp%-5d ", ppa
.ppa_zoneid
, ppa
.ppa_ppa_id
);
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");
110 upaddr
= (uintptr_t)sps
->sps_rq
;
113 while (upaddr
!= NULL
) {
114 if (mdb_vread(&upq
, sizeof (upq
), upaddr
) == -1) {
118 if ((upaddr
= (uintptr_t)upq
.q_next
) != 0)
119 illaddr
= (uintptr_t)upq
.q_ptr
;
122 if (mdb_vread(&ill
, sizeof (ill
), illaddr
) == -1 ||
123 mdb_vread(&ipif
, sizeof (ipif
),
124 (uintptr_t)ill
.ill_ipif
) == -1) {
129 switch (sps
->sps_req_sap
) {
131 mdb_printf("DLPI IPv4 ");
134 } else if (illaddr
== 0) {
135 mdb_printf("(no addresses)\n");
138 * SCCS oddity here -- % <capital> %
139 * suffers from keyword replacement.
140 * Avoid that by using ANSI string
143 mdb_printf("%I:%I" "%s\n",
144 ipif
.ipif_lcl_addr
, ipif
.ipif_pp_dst_addr
,
145 (ipif
.ipif_next
? " ..." : ""));
149 mdb_printf("DLPI IPv6 ");
155 mdb_printf("(no addresses)\n");
158 mdb_printf("%N\n%?s%21s", &ipif
.ipif_v6lcl_addr
,
160 mdb_printf("%N\n", &ipif
.ipif_v6pp_dst_addr
);
162 case ETHERTYPE_ALLSAP
:
163 mdb_printf("DLPI Snoop\n");
166 mdb_printf("DLPI SAP 0x%04X\n", sps
->sps_req_sap
);
175 sppp(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
180 if (mdb_getopts(argc
, argv
, 'q', MDB_OPT_SETBITS
, TRUE
, &qfmt
, NULL
) !=
184 if ((flags
& DCMD_LOOPFIRST
) || !(flags
& DCMD_LOOP
)) {
186 mdb_printf("%<u>%?s %?s %-6s %-9s %s%</u>\n", "Address",
187 "RecvQ", "ZoneID", "Interface", "Type");
189 mdb_printf("%<u>%?s %-6s %-9s %s%</u>\n", "Address",
190 "ZoneID", "Interface", "Type");
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");
206 sppa_walk_init(mdb_walk_state_t
*wsp
)
208 if (mdb_readvar(&wsp
->walk_addr
, "ppa_list") == -1) {
209 mdb_warn("failed to read ppa_list");
217 sppa_walk_step(mdb_walk_state_t
*wsp
)
222 if (wsp
->walk_addr
== NULL
)
225 if (mdb_vread(&ppa
, sizeof (ppa
), wsp
->walk_addr
) == -1) {
226 mdb_warn("can't read spppstr_t at %p", wsp
->walk_addr
);
230 status
= (wsp
->walk_callback(wsp
->walk_addr
, &ppa
, wsp
->walk_cbdata
));
232 wsp
->walk_addr
= (uintptr_t)ppa
.ppa_nextppa
;
238 ppa_format(uintptr_t addr
, const sppa_t
*ppa
, uint_t
*qfmt
)
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
);
248 sppa(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
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");
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");
270 sppp_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
275 if (mdb_vread(&sps
, sizeof (sps
), (uintptr_t)q
->q_ptr
) ==
277 if (sps
.sps_ppa
== NULL
||
278 mdb_vread(&ppa
, sizeof (ppa
), (uintptr_t)sps
.sps_ppa
) ==
280 (void) mdb_snprintf(buf
, nbytes
, "minor %d",
283 (void) mdb_snprintf(buf
, nbytes
, "sppp%d",
290 sppp_rnext(const queue_t
*q
)
294 if (mdb_vread(&sps
, sizeof (sps
), (uintptr_t)q
->q_ptr
) == sizeof (sps
))
295 return ((uintptr_t)sps
.sps_rq
);
301 sppp_wnext(const queue_t
*q
)
306 if (mdb_vread(&sps
, sizeof (sps
), (uintptr_t)q
->q_ptr
) != sizeof (sps
))
309 if (sps
.sps_ppa
!= NULL
&&
310 mdb_vread(&ppa
, sizeof (ppa
), (uintptr_t)sps
.sps_ppa
) ==
312 return ((uintptr_t)ppa
.ppa_lower_wq
);
317 /* ****************** sppptun ****************** */
319 struct tcl_walk_data
{
322 tuncl_t
*tcl_slots
[1];
326 tuncl_walk_fini(mdb_walk_state_t
*wsp
)
328 struct tcl_walk_data
*twd
;
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])));
339 tuncl_walk_init(mdb_walk_state_t
*wsp
)
343 struct tcl_walk_data
*twd
;
348 if (wsp
->walk_addr
!= 0)
349 tuncl_walk_fini(wsp
);
351 if (mdb_readvar(&tcl_nslots
, "tcl_nslots") == -1) {
352 mdb_warn("failed to read tcl_nslots");
359 if (mdb_readvar(&tcl_slots
, "tcl_slots") == -1) {
360 mdb_warn("failed to read tcl_slots");
364 twd
= (struct tcl_walk_data
*)mdb_alloc(sizeof (*twd
) +
365 (tcl_nslots
- 1) * sizeof (*tcl_slots
), UM_NOSLEEP
);
368 twd
->tcl_nslots
= tcl_nslots
;
370 wsp
->walk_addr
= (uintptr_t)twd
;
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
);
383 tuncl_walk_step(mdb_walk_state_t
*wsp
)
387 struct tcl_walk_data
*twd
;
390 if (wsp
== NULL
|| wsp
->walk_addr
== NULL
)
393 twd
= (struct tcl_walk_data
*)wsp
->walk_addr
;
395 while (twd
->walkpos
< twd
->tcl_nslots
&&
396 twd
->tcl_slots
[twd
->walkpos
] == NULL
)
398 if (twd
->walkpos
>= twd
->tcl_nslots
)
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
);
407 status
= wsp
->walk_callback(addr
, &tcl
, wsp
->walk_cbdata
);
415 tuncl_format(uintptr_t addr
, const tuncl_t
*tcl
, uint_t
*qfmt
)
417 mdb_printf("%?p %-6d %?p %?p", addr
, tcl
->tcl_zoneid
, tcl
->tcl_data_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");
424 mdb_printf("sppp%d\n", tcl
->tcl_unit
);
432 tuncl(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
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");
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
);
446 tuncl_format(addr
, &tcl
, &qfmt
);
447 } else if (mdb_walk("tuncl", (mdb_walk_cb_t
)tuncl_format
, &qfmt
) ==
449 mdb_warn("failed to walk tcl_slots");
456 struct tll_walk_data
{
462 tunll_walk_fini(mdb_walk_state_t
*wsp
)
464 struct tll_walk_data
*twd
;
466 if (wsp
!= NULL
&& wsp
->walk_addr
!= 0) {
467 twd
= (struct tll_walk_data
*)wsp
->walk_addr
;
468 mdb_free(twd
, sizeof (*twd
));
474 tunll_walk_init(mdb_walk_state_t
*wsp
)
477 struct tll_walk_data
*twd
;
478 struct qelem tunll_list
;
480 if (wsp
->walk_addr
!= 0)
481 tunll_walk_fini(wsp
);
483 if (mdb_lookup_by_obj("sppptun", "tunll_list", &sym
) != 0) {
484 mdb_warn("failed to find tunll_list");
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
);
495 twd
= (struct tll_walk_data
*)mdb_alloc(sizeof (*twd
), UM_NOSLEEP
);
498 twd
->listhead
= (void *)(uintptr_t)sym
.st_value
;
499 twd
->next
= (void *)tunll_list
.q_forw
;
500 wsp
->walk_addr
= (uintptr_t)twd
;
506 tunll_walk_step(mdb_walk_state_t
*wsp
)
508 struct tll_walk_data
*twd
;
513 if (wsp
== NULL
|| wsp
->walk_addr
== 0)
516 twd
= (struct tll_walk_data
*)wsp
->walk_addr
;
517 if (twd
->next
== NULL
|| twd
->next
== twd
->listhead
)
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
);
527 status
= wsp
->walk_callback(addr
, &tll
, wsp
->walk_cbdata
);
529 twd
->next
= (void *)tll
.tll_next
;
535 tunll_format(uintptr_t addr
, const tunll_t
*tll
, uint_t
*qfmt
)
537 mdb_printf("%?p %-6d %-14s %?p", addr
, tll
->tll_zoneid
, tll
->tll_name
,
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]);
555 tunll(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
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");
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
);
569 tunll_format(addr
, &tll
, &qfmt
);
570 } else if (mdb_walk("tunll", (mdb_walk_cb_t
)tunll_format
, &qfmt
) ==
572 mdb_warn("failed to walk tunll_list");
586 tun_state_read(void *ptr
, union tun_state
*ts
)
589 * First, get the flags on this structure. This is either a
590 * tuncl_t or a tunll_t.
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
)) {
600 if (mdb_vread(&ts
->tll
, sizeof (ts
->tll
),
601 (uintptr_t)ptr
) == sizeof (ts
->tll
)) {
610 sppptun_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
614 if (tun_state_read(q
->q_ptr
, &ts
) == -1)
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
);
621 mdb_snprintf(buf
, nbytes
, "%s", ts
.tll
.tll_name
);
625 sppptun_rnext(const queue_t
*q
)
629 if (tun_state_read(q
->q_ptr
, &ts
) == -1)
632 if (ts
.tcl
.tcl_flags
& TCLF_ISCLIENT
) {
633 return ((uintptr_t)ts
.tcl
.tcl_rq
);
635 /* Not quite right, but ... */
636 return ((uintptr_t)ts
.tll
.tll_defcl
);
641 sppptun_wnext(const queue_t
*q
)
645 if (tun_state_read(q
->q_ptr
, &ts
) == -1)
648 if (ts
.tcl
.tcl_flags
& TCLF_ISCLIENT
) {
649 if (ts
.tcl
.tcl_data_tll
== NULL
)
651 if (mdb_vread(&ts
.tll
, sizeof (ts
.tll
),
652 (uintptr_t)ts
.tcl
.tcl_data_tll
) != sizeof (ts
.tll
)) {
656 return ((uintptr_t)ts
.tll
.tll_wq
);
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",
664 { "tunll", "", "display sppptun lower stream state structures",
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
},
681 static const mdb_qops_t sppp_qops
= { sppp_qinfo
, sppp_rnext
, sppp_wnext
};
682 static const mdb_qops_t sppptun_qops
= {
683 sppptun_qinfo
, sppptun_rnext
, sppptun_wnext
685 static const mdb_modinfo_t modinfo
= { MDB_API_VERSION
, dcmds
, walkers
};
687 const mdb_modinfo_t
*
692 if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym
) == 0)
693 mdb_qops_install(&sppp_qops
, (uintptr_t)sym
.st_value
);
695 if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym
) == 0)
696 mdb_qops_install(&sppptun_qops
, (uintptr_t)sym
.st_value
);
706 if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym
) == 0)
707 mdb_qops_remove(&sppptun_qops
, (uintptr_t)sym
.st_value
);
709 if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym
) == 0)
710 mdb_qops_remove(&sppp_qops
, (uintptr_t)sym
.st_value
);