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