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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <stdio.h>
30#include <sys/types.h>
31#include <netinet/in.h>
32#include <at.h>
33#include <snoop.h>
34
35extern char *src_name, *dst_name;
36
37struct socktable {
38	int	pt_num;
39	char	*pt_short;
40};
41
42static struct socktable pt_ddp[] = {
43	{1,	"RTMP"},
44	{2,	"NIS"},
45	{4,	"Echoer"},
46	{6,	"ZIS"},
47	{0,	NULL},
48};
49
50static struct socktable pt_ddp_types[] = {
51	{1,	"RTMP Resp"},
52	{2,	"NBP"},
53	{3,	"ATP"},
54	{4,	"AEP"},
55	{5,	"RTMP Req"},
56	{6,	"ZIP"},
57	{7,	"ADSP"},
58	{0,	NULL},
59};
60
61static char *
62apple_ddp_type(struct socktable *p, uint16_t port)
63{
64	for (; p->pt_num != 0; p++) {
65		if (port == p->pt_num)
66			return (p->pt_short);
67	}
68	return (NULL);
69}
70
71/*
72 * return the short at p, regardless of alignment
73 */
74
75uint16_t
76get_short(uint8_t *p)
77{
78	return (p[0] << 8 | p[1]);
79}
80
81/*
82 * return the long at p, regardless of alignment
83 */
84uint32_t
85get_long(uint8_t *p)
86{
87	return (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
88}
89
90/*
91 * format a MAC address
92 */
93
94char *
95print_macaddr(uint8_t *ha, int len)
96{
97	static char buf[128];
98	char *p = buf;
99
100	while (len-- != 0) {
101		p += snprintf(p, sizeof (buf) - (p - buf),
102		    len > 0 ? "%x:" : "%x", *ha++);
103	}
104	return (buf);
105}
106
107/* ARGSUSED */
108void
109interpret_at(int flags, struct ddp_hdr *ddp, int len)
110{
111	int ddplen;
112	char *pname;
113	char buff [32];
114	static char src_buf[16];
115	static char dst_buf[16];
116
117	if (ddp_pad(ddp) != 0)
118		return;			/* unknown AppleTalk proto */
119
120	ddplen = ddp_len(ddp);
121
122	(void) snprintf(src_buf, sizeof (src_buf),
123	    "%u.%u", ntohs(ddp->ddp_src_net), ddp->ddp_src_id);
124	src_name = src_buf;
125
126	(void) snprintf(dst_buf, sizeof (dst_buf),
127	    "%u.%u", ntohs(ddp->ddp_dest_net), ddp->ddp_dest_id);
128	if (ddp->ddp_dest_id == NODE_ID_BROADCAST)
129		dst_name = "(broadcast)";
130	else
131		dst_name = dst_buf;
132
133	if (flags & F_SUM) {
134		(void) snprintf(get_sum_line(), MAXLINE,
135		    "DDP S=%u.%u:%u D=%u.%u:%u LEN=%d",
136		    ntohs(ddp->ddp_src_net),
137		    ddp->ddp_src_id,
138		    ddp->ddp_src_sock,
139		    ntohs(ddp->ddp_dest_net),
140		    ddp->ddp_dest_id,
141		    ddp->ddp_dest_sock,
142		    ddp_len(ddp));
143	}
144
145	if (flags & F_DTAIL) {
146		show_header("DDP:  ", "DDP Header", ddplen - DDPHDR_SIZE);
147		show_space();
148		pname = apple_ddp_type(pt_ddp, ddp->ddp_src_sock);
149		if (pname == NULL) {
150			pname = "";
151		} else {
152			(void) snprintf(buff, sizeof (buff), "(%s)", pname);
153			pname = buff;
154		}
155
156		(void) snprintf(get_line(0, 0), get_line_remain(),
157		    "Source = %s, Socket = %u %s",
158		    src_name, ddp->ddp_src_sock, pname);
159		pname = apple_ddp_type(pt_ddp, ddp->ddp_dest_sock);
160		if (pname == NULL) {
161			pname = "";
162		} else {
163			(void) snprintf(buff, sizeof (buff), "(%s)", pname);
164			pname = buff;
165		}
166		(void) snprintf(get_line(0, 0), get_line_remain(),
167		    "Destination = %s, Socket = %u %s",
168		    dst_name, ddp->ddp_dest_sock, pname);
169		(void) snprintf(get_line(0, 0), get_line_remain(),
170		    "Hop count = %d",
171		    ddp_hop(ddp));
172		(void) snprintf(get_line(0, 0), get_line_remain(),
173		    "Length = %d",
174		    ddp_len(ddp));
175		(void) snprintf(get_line(0, 0), get_line_remain(),
176		    "Checksum = %04x %s",
177		    ntohs(ddp->ddp_cksum),
178		    ddp->ddp_cksum == 0 ? "(no checksum)" : "");
179		(void) snprintf(get_line(0, 0), get_line_remain(),
180		    "DDP type = %d (%s)",
181		    ddp->ddp_type,
182		    apple_ddp_type(pt_ddp_types, ddp->ddp_type));
183		show_space();
184	}
185
186
187	/* go to the next protocol layer */
188
189	switch (ddp->ddp_type) {
190	case DDP_TYPE_NBP:
191		interpret_nbp(flags, (struct nbp_hdr *)ddp, ddplen);
192		break;
193	case DDP_TYPE_AEP:
194		interpret_aecho(flags, ddp, ddplen);
195		break;
196	case DDP_TYPE_ATP:
197		interpret_atp(flags, ddp, ddplen);
198		break;
199	case DDP_TYPE_ZIP:
200		interpret_ddp_zip(flags, (struct zip_hdr *)ddp, ddplen);
201		break;
202	case DDP_TYPE_ADSP:
203		interpret_adsp(flags, (struct ddp_adsphdr *)ddp, ddplen);
204		break;
205	case DDP_TYPE_RTMPRQ:
206	case DDP_TYPE_RTMPRESP:
207		interpret_rtmp(flags, ddp, ddplen);
208		break;
209	}
210}
211