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 #include <stdio.h>
28 #include <sys/types.h>
29 #include <netinet/in.h>
30 #include <at.h>
31 #include <snoop.h>
32 
33 extern char *src_name, *dst_name;
34 
35 struct socktable {
36 	int	pt_num;
37 	char	*pt_short;
38 };
39 
40 static struct socktable pt_ddp[] = {
41 	{1,	"RTMP"},
42 	{2,	"NIS"},
43 	{4,	"Echoer"},
44 	{6,	"ZIS"},
45 	{0,	NULL},
46 };
47 
48 static struct socktable pt_ddp_types[] = {
49 	{1,	"RTMP Resp"},
50 	{2,	"NBP"},
51 	{3,	"ATP"},
52 	{4,	"AEP"},
53 	{5,	"RTMP Req"},
54 	{6,	"ZIP"},
55 	{7,	"ADSP"},
56 	{0,	NULL},
57 };
58 
59 static char *
apple_ddp_type(struct socktable * p,uint16_t port)60 apple_ddp_type(struct socktable *p, uint16_t port)
61 {
62 	for (; p->pt_num != 0; p++) {
63 		if (port == p->pt_num)
64 			return (p->pt_short);
65 	}
66 	return (NULL);
67 }
68 
69 /*
70  * return the short at p, regardless of alignment
71  */
72 
73 uint16_t
get_short(uint8_t * p)74 get_short(uint8_t *p)
75 {
76 	return (p[0] << 8 | p[1]);
77 }
78 
79 /*
80  * return the long at p, regardless of alignment
81  */
82 uint32_t
get_long(uint8_t * p)83 get_long(uint8_t *p)
84 {
85 	return (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
86 }
87 
88 /*
89  * format a MAC address
90  */
91 
92 char *
print_macaddr(uint8_t * ha,int len)93 print_macaddr(uint8_t *ha, int len)
94 {
95 	static char buf[128];
96 	char *p = buf;
97 
98 	while (len-- != 0) {
99 		p += snprintf(p, sizeof (buf) - (p - buf),
100 		    len > 0 ? "%x:" : "%x", *ha++);
101 	}
102 	return (buf);
103 }
104 
105 /* ARGSUSED */
106 void
interpret_at(int flags,struct ddp_hdr * ddp,int len)107 interpret_at(int flags, struct ddp_hdr *ddp, int len)
108 {
109 	int ddplen;
110 	char *pname;
111 	char buff [32];
112 	static char src_buf[16];
113 	static char dst_buf[16];
114 
115 	if (ddp_pad(ddp) != 0)
116 		return;			/* unknown AppleTalk proto */
117 
118 	ddplen = ddp_len(ddp);
119 
120 	(void) snprintf(src_buf, sizeof (src_buf),
121 	    "%u.%u", ntohs(ddp->ddp_src_net), ddp->ddp_src_id);
122 	src_name = src_buf;
123 
124 	(void) snprintf(dst_buf, sizeof (dst_buf),
125 	    "%u.%u", ntohs(ddp->ddp_dest_net), ddp->ddp_dest_id);
126 	if (ddp->ddp_dest_id == NODE_ID_BROADCAST)
127 		dst_name = "(broadcast)";
128 	else
129 		dst_name = dst_buf;
130 
131 	if (flags & F_SUM) {
132 		(void) snprintf(get_sum_line(), MAXLINE,
133 		    "DDP S=%u.%u:%u D=%u.%u:%u LEN=%d",
134 		    ntohs(ddp->ddp_src_net),
135 		    ddp->ddp_src_id,
136 		    ddp->ddp_src_sock,
137 		    ntohs(ddp->ddp_dest_net),
138 		    ddp->ddp_dest_id,
139 		    ddp->ddp_dest_sock,
140 		    ddp_len(ddp));
141 	}
142 
143 	if (flags & F_DTAIL) {
144 		show_header("DDP:  ", "DDP Header", ddplen - DDPHDR_SIZE);
145 		show_space();
146 		pname = apple_ddp_type(pt_ddp, ddp->ddp_src_sock);
147 		if (pname == NULL) {
148 			pname = "";
149 		} else {
150 			(void) snprintf(buff, sizeof (buff), "(%s)", pname);
151 			pname = buff;
152 		}
153 
154 		(void) snprintf(get_line(0, 0), get_line_remain(),
155 		    "Source = %s, Socket = %u %s",
156 		    src_name, ddp->ddp_src_sock, pname);
157 		pname = apple_ddp_type(pt_ddp, ddp->ddp_dest_sock);
158 		if (pname == NULL) {
159 			pname = "";
160 		} else {
161 			(void) snprintf(buff, sizeof (buff), "(%s)", pname);
162 			pname = buff;
163 		}
164 		(void) snprintf(get_line(0, 0), get_line_remain(),
165 		    "Destination = %s, Socket = %u %s",
166 		    dst_name, ddp->ddp_dest_sock, pname);
167 		(void) snprintf(get_line(0, 0), get_line_remain(),
168 		    "Hop count = %d",
169 		    ddp_hop(ddp));
170 		(void) snprintf(get_line(0, 0), get_line_remain(),
171 		    "Length = %d",
172 		    ddp_len(ddp));
173 		(void) snprintf(get_line(0, 0), get_line_remain(),
174 		    "Checksum = %04x %s",
175 		    ntohs(ddp->ddp_cksum),
176 		    ddp->ddp_cksum == 0 ? "(no checksum)" : "");
177 		(void) snprintf(get_line(0, 0), get_line_remain(),
178 		    "DDP type = %d (%s)",
179 		    ddp->ddp_type,
180 		    apple_ddp_type(pt_ddp_types, ddp->ddp_type));
181 		show_space();
182 	}
183 
184 
185 	/* go to the next protocol layer */
186 
187 	switch (ddp->ddp_type) {
188 	case DDP_TYPE_NBP:
189 		interpret_nbp(flags, (struct nbp_hdr *)ddp, ddplen);
190 		break;
191 	case DDP_TYPE_AEP:
192 		interpret_aecho(flags, ddp, ddplen);
193 		break;
194 	case DDP_TYPE_ATP:
195 		interpret_atp(flags, ddp, ddplen);
196 		break;
197 	case DDP_TYPE_ZIP:
198 		interpret_ddp_zip(flags, (struct zip_hdr *)ddp, ddplen);
199 		break;
200 	case DDP_TYPE_ADSP:
201 		interpret_adsp(flags, (struct ddp_adsphdr *)ddp, ddplen);
202 		break;
203 	case DDP_TYPE_RTMPRQ:
204 	case DDP_TYPE_RTMPRESP:
205 		interpret_rtmp(flags, ddp, ddplen);
206 		break;
207 	}
208 }
209