xref: /freebsd/contrib/tcpdump/print-zephyr.c (revision 6fd05b64b5b65dd4ba9b86482a0634a5f0b96c29)
1 /*
2  * Decode and print Zephyr packets.
3  *
4  * Copyright (c) 2001 Nickolai Zeldovich <kolya@MIT.EDU>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code
9  * distributions retain the above copyright notice and this paragraph
10  * in its entirety, and (2) distributions including binary code include
11  * the above copyright notice and this paragraph in its entirety in
12  * the documentation or other materials provided with the distribution.
13  * The name of the author(s) may not be used to endorse or promote
14  * products derived from this software without specific prior written
15  * permission.  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE.
19  */
20 
21 #ifndef lint
22 static const char rcsid[] _U_ =
23     "@(#) $Header: /tcpdump/master/tcpdump/print-zephyr.c,v 1.6.2.2 2003/11/16 08:51:56 guy Exp $";
24 #endif
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <tcpdump-stdinc.h>
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "interface.h"
37 
38 struct z_packet {
39     char *version;
40     int numfields;
41     int kind;
42     char *uid;
43     int port;
44     int auth;
45     int authlen;
46     char *authdata;
47     char *class;
48     char *inst;
49     char *opcode;
50     char *sender;
51     const char *recipient;
52     char *format;
53     int cksum;
54     int multi;
55     char *multi_uid;
56     /* Other fields follow here.. */
57 };
58 
59 enum z_packet_type {
60     Z_PACKET_UNSAFE = 0,
61     Z_PACKET_UNACKED,
62     Z_PACKET_ACKED,
63     Z_PACKET_HMACK,
64     Z_PACKET_HMCTL,
65     Z_PACKET_SERVACK,
66     Z_PACKET_SERVNAK,
67     Z_PACKET_CLIENTACK,
68     Z_PACKET_STAT
69 };
70 
71 static struct tok z_types[] = {
72     { Z_PACKET_UNSAFE,		"unsafe" },
73     { Z_PACKET_UNACKED,		"unacked" },
74     { Z_PACKET_ACKED,		"acked" },
75     { Z_PACKET_HMACK,		"hm-ack" },
76     { Z_PACKET_HMCTL,		"hm-ctl" },
77     { Z_PACKET_SERVACK,		"serv-ack" },
78     { Z_PACKET_SERVNAK,		"serv-nak" },
79     { Z_PACKET_CLIENTACK,	"client-ack" },
80     { Z_PACKET_STAT,		"stat" }
81 };
82 
83 char z_buf[256];
84 
85 static char *
86 parse_field(char **pptr, int *len)
87 {
88     char *s;
89 
90     if (*len <= 0 || !pptr || !*pptr)
91 	return NULL;
92     if (*pptr > (char *) snapend)
93 	return NULL;
94 
95     s = *pptr;
96     while (*pptr <= (char *) snapend && *len >= 0 && **pptr) {
97 	(*pptr)++;
98 	(*len)--;
99     }
100     (*pptr)++;
101     (*len)--;
102     if (*len < 0 || *pptr > (char *) snapend)
103 	return NULL;
104     return s;
105 }
106 
107 static const char *
108 z_triple(char *class, char *inst, const char *recipient)
109 {
110     if (!*recipient)
111 	recipient = "*";
112     snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient);
113     z_buf[sizeof(z_buf)-1] = '\0';
114     return z_buf;
115 }
116 
117 static const char *
118 str_to_lower(char *string)
119 {
120     strncpy(z_buf, string, sizeof(z_buf));
121     z_buf[sizeof(z_buf)-1] = '\0';
122 
123     string = z_buf;
124     while (*string) {
125 	*string = tolower((unsigned char)(*string));
126 	string++;
127     }
128 
129     return z_buf;
130 }
131 
132 void
133 zephyr_print(const u_char *cp, int length)
134 {
135     struct z_packet z;
136     char *parse = (char *) cp;
137     int parselen = length;
138     char *s;
139     int lose = 0;
140 
141 #define PARSE_STRING				\
142 	s = parse_field(&parse, &parselen);	\
143 	if (!s) lose = 1;
144 
145 #define PARSE_FIELD_INT(field)			\
146 	PARSE_STRING				\
147 	if (!lose) field = strtol(s, 0, 16);
148 
149 #define PARSE_FIELD_STR(field)			\
150 	PARSE_STRING				\
151 	if (!lose) field = s;
152 
153     PARSE_FIELD_STR(z.version);
154     if (lose) return;
155     if (strncmp(z.version, "ZEPH", 4))
156 	return;
157 
158     PARSE_FIELD_INT(z.numfields);
159     PARSE_FIELD_INT(z.kind);
160     PARSE_FIELD_STR(z.uid);
161     PARSE_FIELD_INT(z.port);
162     PARSE_FIELD_INT(z.auth);
163     PARSE_FIELD_INT(z.authlen);
164     PARSE_FIELD_STR(z.authdata);
165     PARSE_FIELD_STR(z.class);
166     PARSE_FIELD_STR(z.inst);
167     PARSE_FIELD_STR(z.opcode);
168     PARSE_FIELD_STR(z.sender);
169     PARSE_FIELD_STR(z.recipient);
170     PARSE_FIELD_STR(z.format);
171     PARSE_FIELD_INT(z.cksum);
172     PARSE_FIELD_INT(z.multi);
173     PARSE_FIELD_STR(z.multi_uid);
174 
175     if (lose) {
176 	printf(" [|zephyr] (%d)", length);
177 	return;
178     }
179 
180     printf(" zephyr");
181     if (strncmp(z.version+4, "0.2", 3)) {
182 	printf(" v%s", z.version+4);
183 	return;
184     }
185 
186     printf(" %s", tok2str(z_types, "type %d", z.kind));
187     if (z.kind == Z_PACKET_SERVACK) {
188 	/* Initialization to silence warnings */
189 	char *ackdata = NULL;
190 	PARSE_FIELD_STR(ackdata);
191 	if (!lose && strcmp(ackdata, "SENT"))
192 	    printf("/%s", str_to_lower(ackdata));
193     }
194     if (*z.sender) printf(" %s", z.sender);
195 
196     if (!strcmp(z.class, "USER_LOCATE")) {
197 	if (!strcmp(z.opcode, "USER_HIDE"))
198 	    printf(" hide");
199 	else if (!strcmp(z.opcode, "USER_UNHIDE"))
200 	    printf(" unhide");
201 	else
202 	    printf(" locate %s", z.inst);
203 	return;
204     }
205 
206     if (!strcmp(z.class, "ZEPHYR_ADMIN")) {
207 	printf(" zephyr-admin %s", str_to_lower(z.opcode));
208 	return;
209     }
210 
211     if (!strcmp(z.class, "ZEPHYR_CTL")) {
212 	if (!strcmp(z.inst, "CLIENT")) {
213 	    if (!strcmp(z.opcode, "SUBSCRIBE") ||
214 		!strcmp(z.opcode, "SUBSCRIBE_NODEFS") ||
215 		!strcmp(z.opcode, "UNSUBSCRIBE")) {
216 
217 		printf(" %ssub%s", strcmp(z.opcode, "SUBSCRIBE") ? "un" : "",
218 				   strcmp(z.opcode, "SUBSCRIBE_NODEFS") ? "" :
219 								   "-nodefs");
220 		if (z.kind != Z_PACKET_SERVACK) {
221 		    /* Initialization to silence warnings */
222 		    char *c = NULL, *i = NULL, *r = NULL;
223 		    PARSE_FIELD_STR(c);
224 		    PARSE_FIELD_STR(i);
225 		    PARSE_FIELD_STR(r);
226 		    if (!lose) printf(" %s", z_triple(c, i, r));
227 		}
228 		return;
229 	    }
230 
231 	    if (!strcmp(z.opcode, "GIMME")) {
232 		printf(" ret");
233 		return;
234 	    }
235 
236 	    if (!strcmp(z.opcode, "GIMMEDEFS")) {
237 		printf(" gimme-defs");
238 		return;
239 	    }
240 
241 	    if (!strcmp(z.opcode, "CLEARSUB")) {
242 		printf(" clear-subs");
243 		return;
244 	    }
245 
246 	    printf(" %s", str_to_lower(z.opcode));
247 	    return;
248 	}
249 
250 	if (!strcmp(z.inst, "HM")) {
251 	    printf(" %s", str_to_lower(z.opcode));
252 	    return;
253 	}
254 
255 	if (!strcmp(z.inst, "REALM")) {
256 	    if (!strcmp(z.opcode, "ADD_SUBSCRIBE"))
257 		printf(" realm add-subs");
258 	    if (!strcmp(z.opcode, "REQ_SUBSCRIBE"))
259 		printf(" realm req-subs");
260 	    if (!strcmp(z.opcode, "RLM_SUBSCRIBE"))
261 		printf(" realm rlm-sub");
262 	    if (!strcmp(z.opcode, "RLM_UNSUBSCRIBE"))
263 		printf(" realm rlm-unsub");
264 	    return;
265 	}
266     }
267 
268     if (!strcmp(z.class, "HM_CTL")) {
269 	printf(" hm_ctl %s", str_to_lower(z.inst));
270 	printf(" %s", str_to_lower(z.opcode));
271 	return;
272     }
273 
274     if (!strcmp(z.class, "HM_STAT")) {
275 	if (!strcmp(z.inst, "HMST_CLIENT") && !strcmp(z.opcode, "GIMMESTATS")) {
276 	    printf(" get-client-stats");
277 	    return;
278 	}
279     }
280 
281     if (!strcmp(z.class, "WG_CTL")) {
282 	printf(" wg_ctl %s", str_to_lower(z.inst));
283 	printf(" %s", str_to_lower(z.opcode));
284 	return;
285     }
286 
287     if (!strcmp(z.class, "LOGIN")) {
288 	if (!strcmp(z.opcode, "USER_FLUSH")) {
289 	    printf(" flush_locs");
290 	    return;
291 	}
292 
293 	if (!strcmp(z.opcode, "NONE") ||
294 	    !strcmp(z.opcode, "OPSTAFF") ||
295 	    !strcmp(z.opcode, "REALM-VISIBLE") ||
296 	    !strcmp(z.opcode, "REALM-ANNOUNCED") ||
297 	    !strcmp(z.opcode, "NET-VISIBLE") ||
298 	    !strcmp(z.opcode, "NET-ANNOUNCED")) {
299 	    printf(" set-exposure %s", str_to_lower(z.opcode));
300 	    return;
301 	}
302     }
303 
304     if (!*z.recipient)
305 	z.recipient = "*";
306 
307     printf(" to %s", z_triple(z.class, z.inst, z.recipient));
308     if (*z.opcode)
309 	printf(" op %s", z.opcode);
310     return;
311 }
312