xref: /freebsd/contrib/tcpdump/print-zephyr.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
1a90e161bSBill Fenner /*
2a90e161bSBill Fenner  * Decode and print Zephyr packets.
3a90e161bSBill Fenner  *
4*ee67461eSJoseph Mingrone  *	https://web.mit.edu/zephyr/doc/protocol
5f4d0c64aSSam Leffler  *
6a90e161bSBill Fenner  * Copyright (c) 2001 Nickolai Zeldovich <kolya@MIT.EDU>
7a90e161bSBill Fenner  * All rights reserved.
8a90e161bSBill Fenner  *
9a90e161bSBill Fenner  * Redistribution and use in source and binary forms, with or without
10a90e161bSBill Fenner  * modification, are permitted provided that: (1) source code
11a90e161bSBill Fenner  * distributions retain the above copyright notice and this paragraph
12a90e161bSBill Fenner  * in its entirety, and (2) distributions including binary code include
13a90e161bSBill Fenner  * the above copyright notice and this paragraph in its entirety in
14a90e161bSBill Fenner  * the documentation or other materials provided with the distribution.
15a90e161bSBill Fenner  * The name of the author(s) may not be used to endorse or promote
16a90e161bSBill Fenner  * products derived from this software without specific prior written
17a90e161bSBill Fenner  * permission.  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
18a90e161bSBill Fenner  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
19a90e161bSBill Fenner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20a90e161bSBill Fenner  * PURPOSE.
21a90e161bSBill Fenner  */
22a90e161bSBill Fenner 
233340d773SGleb Smirnoff /* \summary: Zephyr printer */
243340d773SGleb Smirnoff 
25*ee67461eSJoseph Mingrone #include <config.h>
26a90e161bSBill Fenner 
27*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
285b0fe478SBruce M Simpson 
29a90e161bSBill Fenner #include <stdio.h>
30a90e161bSBill Fenner #include <string.h>
31a90e161bSBill Fenner #include <stdlib.h>
32a90e161bSBill Fenner 
33*ee67461eSJoseph Mingrone #include "netdissect-ctype.h"
34*ee67461eSJoseph Mingrone 
353340d773SGleb Smirnoff #include "netdissect.h"
36*ee67461eSJoseph Mingrone #include "extract.h"
37a90e161bSBill Fenner 
38a90e161bSBill Fenner struct z_packet {
393340d773SGleb Smirnoff     const char *version;
40a90e161bSBill Fenner     int numfields;
41a90e161bSBill Fenner     int kind;
423340d773SGleb Smirnoff     const char *uid;
43a90e161bSBill Fenner     int port;
44a90e161bSBill Fenner     int auth;
45a90e161bSBill Fenner     int authlen;
463340d773SGleb Smirnoff     const char *authdata;
473340d773SGleb Smirnoff     const char *class;
483340d773SGleb Smirnoff     const char *inst;
493340d773SGleb Smirnoff     const char *opcode;
503340d773SGleb Smirnoff     const char *sender;
515b0fe478SBruce M Simpson     const char *recipient;
523340d773SGleb Smirnoff     const char *format;
53a90e161bSBill Fenner     int cksum;
54a90e161bSBill Fenner     int multi;
553340d773SGleb Smirnoff     const char *multi_uid;
56a90e161bSBill Fenner     /* Other fields follow here.. */
57a90e161bSBill Fenner };
58a90e161bSBill Fenner 
599afd0c29SBill Fenner enum z_packet_type {
60a90e161bSBill Fenner     Z_PACKET_UNSAFE = 0,
61a90e161bSBill Fenner     Z_PACKET_UNACKED,
62a90e161bSBill Fenner     Z_PACKET_ACKED,
63a90e161bSBill Fenner     Z_PACKET_HMACK,
64a90e161bSBill Fenner     Z_PACKET_HMCTL,
65a90e161bSBill Fenner     Z_PACKET_SERVACK,
66a90e161bSBill Fenner     Z_PACKET_SERVNAK,
67a90e161bSBill Fenner     Z_PACKET_CLIENTACK,
68a90e161bSBill Fenner     Z_PACKET_STAT
699afd0c29SBill Fenner };
70a90e161bSBill Fenner 
713c602fabSXin LI static const struct tok z_types[] = {
72a90e161bSBill Fenner     { Z_PACKET_UNSAFE,		"unsafe" },
73a90e161bSBill Fenner     { Z_PACKET_UNACKED,		"unacked" },
74a90e161bSBill Fenner     { Z_PACKET_ACKED,		"acked" },
75a90e161bSBill Fenner     { Z_PACKET_HMACK,		"hm-ack" },
76a90e161bSBill Fenner     { Z_PACKET_HMCTL,		"hm-ctl" },
77a90e161bSBill Fenner     { Z_PACKET_SERVACK,		"serv-ack" },
78a90e161bSBill Fenner     { Z_PACKET_SERVNAK,		"serv-nak" },
79a90e161bSBill Fenner     { Z_PACKET_CLIENTACK,	"client-ack" },
800bff6a5aSEd Maste     { Z_PACKET_STAT,		"stat" },
810bff6a5aSEd Maste     { 0,			NULL }
82a90e161bSBill Fenner };
83a90e161bSBill Fenner 
843c602fabSXin LI static char z_buf[256];
85a90e161bSBill Fenner 
863340d773SGleb Smirnoff static const char *
parse_field(netdissect_options * ndo,const char ** pptr,int * len)87*ee67461eSJoseph Mingrone parse_field(netdissect_options *ndo, const char **pptr, int *len)
88a90e161bSBill Fenner {
893340d773SGleb Smirnoff     const char *s;
90a90e161bSBill Fenner 
910bff6a5aSEd Maste     /* Start of string */
92a90e161bSBill Fenner     s = *pptr;
930bff6a5aSEd Maste     /* Scan for the NUL terminator */
940bff6a5aSEd Maste     for (;;) {
950bff6a5aSEd Maste 	if (*len == 0) {
960bff6a5aSEd Maste 	    /* Ran out of packet data without finding it */
970bff6a5aSEd Maste 	    return NULL;
980bff6a5aSEd Maste 	}
99*ee67461eSJoseph Mingrone 	if (GET_U_1(*pptr) == '\0') {
1000bff6a5aSEd Maste 	    /* Found it */
1010bff6a5aSEd Maste 	    break;
1020bff6a5aSEd Maste 	}
1030bff6a5aSEd Maste 	/* Keep scanning */
104a90e161bSBill Fenner 	(*pptr)++;
105a90e161bSBill Fenner 	(*len)--;
106a90e161bSBill Fenner     }
1070bff6a5aSEd Maste     /* Skip the NUL terminator */
108a90e161bSBill Fenner     (*pptr)++;
109a90e161bSBill Fenner     (*len)--;
110a90e161bSBill Fenner     return s;
111a90e161bSBill Fenner }
112a90e161bSBill Fenner 
113a90e161bSBill Fenner static const char *
z_triple(const char * class,const char * inst,const char * recipient)1143340d773SGleb Smirnoff z_triple(const char *class, const char *inst, const char *recipient)
115a90e161bSBill Fenner {
116a90e161bSBill Fenner     if (!*recipient)
117a90e161bSBill Fenner 	recipient = "*";
118a90e161bSBill Fenner     snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient);
119a90e161bSBill Fenner     z_buf[sizeof(z_buf)-1] = '\0';
120a90e161bSBill Fenner     return z_buf;
121a90e161bSBill Fenner }
122a90e161bSBill Fenner 
123a90e161bSBill Fenner static const char *
str_to_lower(const char * string)1243340d773SGleb Smirnoff str_to_lower(const char *string)
125a90e161bSBill Fenner {
1263340d773SGleb Smirnoff     char *zb_string;
1273340d773SGleb Smirnoff 
128a90e161bSBill Fenner     strncpy(z_buf, string, sizeof(z_buf));
129a90e161bSBill Fenner     z_buf[sizeof(z_buf)-1] = '\0';
130a90e161bSBill Fenner 
1313340d773SGleb Smirnoff     zb_string = z_buf;
1323340d773SGleb Smirnoff     while (*zb_string) {
133*ee67461eSJoseph Mingrone 	*zb_string = ND_ASCII_TOLOWER(*zb_string);
1343340d773SGleb Smirnoff 	zb_string++;
135a90e161bSBill Fenner     }
136a90e161bSBill Fenner 
137a90e161bSBill Fenner     return z_buf;
138a90e161bSBill Fenner }
139a90e161bSBill Fenner 
140*ee67461eSJoseph Mingrone #define ZEPHYR_PRINT(str1,str2) \
141*ee67461eSJoseph Mingrone { ND_PRINT("%s", (str1)); fn_print_str(ndo, (const u_char *)(str2)); }
142*ee67461eSJoseph Mingrone 
143a90e161bSBill Fenner void
zephyr_print(netdissect_options * ndo,const u_char * cp,u_int length)144*ee67461eSJoseph Mingrone zephyr_print(netdissect_options *ndo, const u_char *cp, u_int length)
145a90e161bSBill Fenner {
146*ee67461eSJoseph Mingrone     struct z_packet z = {
147*ee67461eSJoseph Mingrone 	NULL,	/* version */
148*ee67461eSJoseph Mingrone 	0,	/* numfields */
149*ee67461eSJoseph Mingrone 	0,	/* kind */
150*ee67461eSJoseph Mingrone 	NULL,	/* uid */
151*ee67461eSJoseph Mingrone 	0,	/* port */
152*ee67461eSJoseph Mingrone 	0,	/* auth */
153*ee67461eSJoseph Mingrone 	0,	/* authlen */
154*ee67461eSJoseph Mingrone 	NULL,	/* authdata */
155*ee67461eSJoseph Mingrone 	NULL,	/* class */
156*ee67461eSJoseph Mingrone 	NULL,	/* inst */
157*ee67461eSJoseph Mingrone 	NULL,	/* opcode */
158*ee67461eSJoseph Mingrone 	NULL,	/* sender */
159*ee67461eSJoseph Mingrone 	NULL,	/* recipient */
160*ee67461eSJoseph Mingrone 	NULL,	/* format */
161*ee67461eSJoseph Mingrone 	0,	/* cksum */
162*ee67461eSJoseph Mingrone 	0,	/* multi */
163*ee67461eSJoseph Mingrone 	NULL	/* multi_uid */
164*ee67461eSJoseph Mingrone     };
1653340d773SGleb Smirnoff     const char *parse = (const char *) cp;
166a90e161bSBill Fenner     int parselen = length;
1673340d773SGleb Smirnoff     const char *s;
168a90e161bSBill Fenner     int lose = 0;
169a90e161bSBill Fenner 
170*ee67461eSJoseph Mingrone     ndo->ndo_protocol = "zephyr";
171a5779b6eSRui Paulo     /* squelch compiler warnings */
172a5779b6eSRui Paulo 
173a90e161bSBill Fenner #define PARSE_STRING						\
174*ee67461eSJoseph Mingrone 	s = parse_field(ndo, &parse, &parselen);	\
175a90e161bSBill Fenner 	if (!s) lose = 1;
176a90e161bSBill Fenner 
177a90e161bSBill Fenner #define PARSE_FIELD_INT(field)			\
178a90e161bSBill Fenner 	PARSE_STRING				\
179a90e161bSBill Fenner 	if (!lose) field = strtol(s, 0, 16);
180a90e161bSBill Fenner 
181a90e161bSBill Fenner #define PARSE_FIELD_STR(field)			\
182a90e161bSBill Fenner 	PARSE_STRING				\
183a90e161bSBill Fenner 	if (!lose) field = s;
184a90e161bSBill Fenner 
185a90e161bSBill Fenner     PARSE_FIELD_STR(z.version);
186*ee67461eSJoseph Mingrone     if (lose)
187*ee67461eSJoseph Mingrone 	goto invalid;
188*ee67461eSJoseph Mingrone 
189a90e161bSBill Fenner     if (strncmp(z.version, "ZEPH", 4))
190a90e161bSBill Fenner 	return;
191a90e161bSBill Fenner 
192a90e161bSBill Fenner     PARSE_FIELD_INT(z.numfields);
193a90e161bSBill Fenner     PARSE_FIELD_INT(z.kind);
194a90e161bSBill Fenner     PARSE_FIELD_STR(z.uid);
195a90e161bSBill Fenner     PARSE_FIELD_INT(z.port);
196a90e161bSBill Fenner     PARSE_FIELD_INT(z.auth);
197a90e161bSBill Fenner     PARSE_FIELD_INT(z.authlen);
198a90e161bSBill Fenner     PARSE_FIELD_STR(z.authdata);
199a90e161bSBill Fenner     PARSE_FIELD_STR(z.class);
200a90e161bSBill Fenner     PARSE_FIELD_STR(z.inst);
201a90e161bSBill Fenner     PARSE_FIELD_STR(z.opcode);
202a90e161bSBill Fenner     PARSE_FIELD_STR(z.sender);
203a90e161bSBill Fenner     PARSE_FIELD_STR(z.recipient);
204a90e161bSBill Fenner     PARSE_FIELD_STR(z.format);
205a90e161bSBill Fenner     PARSE_FIELD_INT(z.cksum);
206a90e161bSBill Fenner     PARSE_FIELD_INT(z.multi);
207a90e161bSBill Fenner     PARSE_FIELD_STR(z.multi_uid);
208a90e161bSBill Fenner 
2090bff6a5aSEd Maste     if (lose)
210*ee67461eSJoseph Mingrone 	goto invalid;
211a90e161bSBill Fenner 
212*ee67461eSJoseph Mingrone     ND_PRINT(" zephyr");
213a90e161bSBill Fenner     if (strncmp(z.version+4, "0.2", 3)) {
214*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" v", z.version+4)
215a90e161bSBill Fenner 	return;
216a90e161bSBill Fenner     }
217a90e161bSBill Fenner 
218*ee67461eSJoseph Mingrone     ND_PRINT(" %s", tok2str(z_types, "type %d", z.kind));
219a90e161bSBill Fenner     if (z.kind == Z_PACKET_SERVACK) {
220a90e161bSBill Fenner 	/* Initialization to silence warnings */
2213340d773SGleb Smirnoff 	const char *ackdata = NULL;
222a90e161bSBill Fenner 	PARSE_FIELD_STR(ackdata);
223a90e161bSBill Fenner 	if (!lose && strcmp(ackdata, "SENT"))
224*ee67461eSJoseph Mingrone 	    ZEPHYR_PRINT("/", str_to_lower(ackdata))
225a90e161bSBill Fenner     }
226*ee67461eSJoseph Mingrone     if (*z.sender) ZEPHYR_PRINT(" ", z.sender);
227a90e161bSBill Fenner 
228a90e161bSBill Fenner     if (!strcmp(z.class, "USER_LOCATE")) {
229a90e161bSBill Fenner 	if (!strcmp(z.opcode, "USER_HIDE"))
230*ee67461eSJoseph Mingrone 	    ND_PRINT(" hide");
231a90e161bSBill Fenner 	else if (!strcmp(z.opcode, "USER_UNHIDE"))
232*ee67461eSJoseph Mingrone 	    ND_PRINT(" unhide");
233a90e161bSBill Fenner 	else
234*ee67461eSJoseph Mingrone 	    ZEPHYR_PRINT(" locate ", z.inst);
235a90e161bSBill Fenner 	return;
236a90e161bSBill Fenner     }
237a90e161bSBill Fenner 
238a90e161bSBill Fenner     if (!strcmp(z.class, "ZEPHYR_ADMIN")) {
239*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" zephyr-admin ", str_to_lower(z.opcode));
240a90e161bSBill Fenner 	return;
241a90e161bSBill Fenner     }
242a90e161bSBill Fenner 
243a90e161bSBill Fenner     if (!strcmp(z.class, "ZEPHYR_CTL")) {
244a90e161bSBill Fenner 	if (!strcmp(z.inst, "CLIENT")) {
245a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "SUBSCRIBE") ||
246a90e161bSBill Fenner 		!strcmp(z.opcode, "SUBSCRIBE_NODEFS") ||
247a90e161bSBill Fenner 		!strcmp(z.opcode, "UNSUBSCRIBE")) {
248a90e161bSBill Fenner 
249*ee67461eSJoseph Mingrone 		ND_PRINT(" %ssub%s", strcmp(z.opcode, "SUBSCRIBE") ? "un" : "",
250a90e161bSBill Fenner 				   strcmp(z.opcode, "SUBSCRIBE_NODEFS") ? "" :
251*ee67461eSJoseph Mingrone 								   "-nodefs");
252a90e161bSBill Fenner 		if (z.kind != Z_PACKET_SERVACK) {
253a90e161bSBill Fenner 		    /* Initialization to silence warnings */
2543340d773SGleb Smirnoff 		    const char *c = NULL, *i = NULL, *r = NULL;
255a90e161bSBill Fenner 		    PARSE_FIELD_STR(c);
256a90e161bSBill Fenner 		    PARSE_FIELD_STR(i);
257a90e161bSBill Fenner 		    PARSE_FIELD_STR(r);
258*ee67461eSJoseph Mingrone 		    if (!lose) ZEPHYR_PRINT(" ", z_triple(c, i, r));
259a90e161bSBill Fenner 		}
260a90e161bSBill Fenner 		return;
261a90e161bSBill Fenner 	    }
262a90e161bSBill Fenner 
263a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "GIMME")) {
264*ee67461eSJoseph Mingrone 		ND_PRINT(" ret");
265a90e161bSBill Fenner 		return;
266a90e161bSBill Fenner 	    }
267a90e161bSBill Fenner 
268a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "GIMMEDEFS")) {
269*ee67461eSJoseph Mingrone 		ND_PRINT(" gimme-defs");
270a90e161bSBill Fenner 		return;
271a90e161bSBill Fenner 	    }
272a90e161bSBill Fenner 
273a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "CLEARSUB")) {
274*ee67461eSJoseph Mingrone 		ND_PRINT(" clear-subs");
275a90e161bSBill Fenner 		return;
276a90e161bSBill Fenner 	    }
277a90e161bSBill Fenner 
278*ee67461eSJoseph Mingrone 	    ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
279a90e161bSBill Fenner 	    return;
280a90e161bSBill Fenner 	}
281a90e161bSBill Fenner 
282a90e161bSBill Fenner 	if (!strcmp(z.inst, "HM")) {
283*ee67461eSJoseph Mingrone 	    ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
284a90e161bSBill Fenner 	    return;
285a90e161bSBill Fenner 	}
286a90e161bSBill Fenner 
287a90e161bSBill Fenner 	if (!strcmp(z.inst, "REALM")) {
288a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "ADD_SUBSCRIBE"))
289*ee67461eSJoseph Mingrone 		ND_PRINT(" realm add-subs");
290a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "REQ_SUBSCRIBE"))
291*ee67461eSJoseph Mingrone 		ND_PRINT(" realm req-subs");
292a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "RLM_SUBSCRIBE"))
293*ee67461eSJoseph Mingrone 		ND_PRINT(" realm rlm-sub");
294a90e161bSBill Fenner 	    if (!strcmp(z.opcode, "RLM_UNSUBSCRIBE"))
295*ee67461eSJoseph Mingrone 		ND_PRINT(" realm rlm-unsub");
296a90e161bSBill Fenner 	    return;
297a90e161bSBill Fenner 	}
298a90e161bSBill Fenner     }
299a90e161bSBill Fenner 
300a90e161bSBill Fenner     if (!strcmp(z.class, "HM_CTL")) {
301*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" hm_ctl ", str_to_lower(z.inst));
302*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
303a90e161bSBill Fenner 	return;
304a90e161bSBill Fenner     }
305a90e161bSBill Fenner 
306a90e161bSBill Fenner     if (!strcmp(z.class, "HM_STAT")) {
307a90e161bSBill Fenner 	if (!strcmp(z.inst, "HMST_CLIENT") && !strcmp(z.opcode, "GIMMESTATS")) {
308*ee67461eSJoseph Mingrone 	    ND_PRINT(" get-client-stats");
309a90e161bSBill Fenner 	    return;
310a90e161bSBill Fenner 	}
311a90e161bSBill Fenner     }
312a90e161bSBill Fenner 
313a90e161bSBill Fenner     if (!strcmp(z.class, "WG_CTL")) {
314*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" wg_ctl ", str_to_lower(z.inst));
315*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
316a90e161bSBill Fenner 	return;
317a90e161bSBill Fenner     }
318a90e161bSBill Fenner 
319a90e161bSBill Fenner     if (!strcmp(z.class, "LOGIN")) {
320a90e161bSBill Fenner 	if (!strcmp(z.opcode, "USER_FLUSH")) {
321*ee67461eSJoseph Mingrone 	    ND_PRINT(" flush_locs");
322a90e161bSBill Fenner 	    return;
323a90e161bSBill Fenner 	}
324a90e161bSBill Fenner 
325a90e161bSBill Fenner 	if (!strcmp(z.opcode, "NONE") ||
326a90e161bSBill Fenner 	    !strcmp(z.opcode, "OPSTAFF") ||
327a90e161bSBill Fenner 	    !strcmp(z.opcode, "REALM-VISIBLE") ||
328a90e161bSBill Fenner 	    !strcmp(z.opcode, "REALM-ANNOUNCED") ||
329a90e161bSBill Fenner 	    !strcmp(z.opcode, "NET-VISIBLE") ||
330a90e161bSBill Fenner 	    !strcmp(z.opcode, "NET-ANNOUNCED")) {
331*ee67461eSJoseph Mingrone 	    ZEPHYR_PRINT(" set-exposure ", str_to_lower(z.opcode));
332a90e161bSBill Fenner 	    return;
333a90e161bSBill Fenner 	}
334a90e161bSBill Fenner     }
335a90e161bSBill Fenner 
336a90e161bSBill Fenner     if (!*z.recipient)
337a90e161bSBill Fenner 	z.recipient = "*";
338a90e161bSBill Fenner 
339*ee67461eSJoseph Mingrone     ZEPHYR_PRINT(" to ", z_triple(z.class, z.inst, z.recipient));
340a90e161bSBill Fenner     if (*z.opcode)
341*ee67461eSJoseph Mingrone 	ZEPHYR_PRINT(" op ", z.opcode);
3420bff6a5aSEd Maste     return;
3430bff6a5aSEd Maste 
344*ee67461eSJoseph Mingrone invalid:
345*ee67461eSJoseph Mingrone     nd_print_invalid(ndo);
346a90e161bSBill Fenner }
347