141c99275SPeter Avalos /*
241c99275SPeter Avalos * Decode and print Zephyr packets.
341c99275SPeter Avalos *
4*ed775ee7SAntonio Huete Jimenez * https://web.mit.edu/zephyr/doc/protocol
541c99275SPeter Avalos *
641c99275SPeter Avalos * Copyright (c) 2001 Nickolai Zeldovich <kolya@MIT.EDU>
741c99275SPeter Avalos * All rights reserved.
841c99275SPeter Avalos *
941c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
1041c99275SPeter Avalos * modification, are permitted provided that: (1) source code
1141c99275SPeter Avalos * distributions retain the above copyright notice and this paragraph
1241c99275SPeter Avalos * in its entirety, and (2) distributions including binary code include
1341c99275SPeter Avalos * the above copyright notice and this paragraph in its entirety in
1441c99275SPeter Avalos * the documentation or other materials provided with the distribution.
1541c99275SPeter Avalos * The name of the author(s) may not be used to endorse or promote
1641c99275SPeter Avalos * products derived from this software without specific prior written
1741c99275SPeter Avalos * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
1841c99275SPeter Avalos * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
1941c99275SPeter Avalos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2041c99275SPeter Avalos * PURPOSE.
2141c99275SPeter Avalos */
2241c99275SPeter Avalos
23411677aeSAaron LI /* \summary: Zephyr printer */
2441c99275SPeter Avalos
2541c99275SPeter Avalos #ifdef HAVE_CONFIG_H
26*ed775ee7SAntonio Huete Jimenez #include <config.h>
2741c99275SPeter Avalos #endif
2841c99275SPeter Avalos
29*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3041c99275SPeter Avalos
3141c99275SPeter Avalos #include <stdio.h>
3241c99275SPeter Avalos #include <string.h>
3341c99275SPeter Avalos #include <stdlib.h>
3441c99275SPeter Avalos
35*ed775ee7SAntonio Huete Jimenez #include "netdissect-ctype.h"
36*ed775ee7SAntonio Huete Jimenez
37411677aeSAaron LI #include "netdissect.h"
38*ed775ee7SAntonio Huete Jimenez #include "extract.h"
3941c99275SPeter Avalos
4041c99275SPeter Avalos struct z_packet {
41411677aeSAaron LI const char *version;
4241c99275SPeter Avalos int numfields;
4341c99275SPeter Avalos int kind;
44411677aeSAaron LI const char *uid;
4541c99275SPeter Avalos int port;
4641c99275SPeter Avalos int auth;
4741c99275SPeter Avalos int authlen;
48411677aeSAaron LI const char *authdata;
49411677aeSAaron LI const char *class;
50411677aeSAaron LI const char *inst;
51411677aeSAaron LI const char *opcode;
52411677aeSAaron LI const char *sender;
5341c99275SPeter Avalos const char *recipient;
54411677aeSAaron LI const char *format;
5541c99275SPeter Avalos int cksum;
5641c99275SPeter Avalos int multi;
57411677aeSAaron LI const char *multi_uid;
5841c99275SPeter Avalos /* Other fields follow here.. */
5941c99275SPeter Avalos };
6041c99275SPeter Avalos
6141c99275SPeter Avalos enum z_packet_type {
6241c99275SPeter Avalos Z_PACKET_UNSAFE = 0,
6341c99275SPeter Avalos Z_PACKET_UNACKED,
6441c99275SPeter Avalos Z_PACKET_ACKED,
6541c99275SPeter Avalos Z_PACKET_HMACK,
6641c99275SPeter Avalos Z_PACKET_HMCTL,
6741c99275SPeter Avalos Z_PACKET_SERVACK,
6841c99275SPeter Avalos Z_PACKET_SERVNAK,
6941c99275SPeter Avalos Z_PACKET_CLIENTACK,
7041c99275SPeter Avalos Z_PACKET_STAT
7141c99275SPeter Avalos };
7241c99275SPeter Avalos
73411677aeSAaron LI static const struct tok z_types[] = {
7441c99275SPeter Avalos { Z_PACKET_UNSAFE, "unsafe" },
7541c99275SPeter Avalos { Z_PACKET_UNACKED, "unacked" },
7641c99275SPeter Avalos { Z_PACKET_ACKED, "acked" },
7741c99275SPeter Avalos { Z_PACKET_HMACK, "hm-ack" },
7841c99275SPeter Avalos { Z_PACKET_HMCTL, "hm-ctl" },
7941c99275SPeter Avalos { Z_PACKET_SERVACK, "serv-ack" },
8041c99275SPeter Avalos { Z_PACKET_SERVNAK, "serv-nak" },
8141c99275SPeter Avalos { Z_PACKET_CLIENTACK, "client-ack" },
82411677aeSAaron LI { Z_PACKET_STAT, "stat" },
83411677aeSAaron LI { 0, NULL }
8441c99275SPeter Avalos };
8541c99275SPeter Avalos
86411677aeSAaron LI static char z_buf[256];
8741c99275SPeter Avalos
88411677aeSAaron LI static const char *
parse_field(netdissect_options * ndo,const char ** pptr,int * len)89*ed775ee7SAntonio Huete Jimenez parse_field(netdissect_options *ndo, const char **pptr, int *len)
9041c99275SPeter Avalos {
91411677aeSAaron LI const char *s;
9241c99275SPeter Avalos
93411677aeSAaron LI /* Start of string */
9441c99275SPeter Avalos s = *pptr;
95411677aeSAaron LI /* Scan for the NUL terminator */
96411677aeSAaron LI for (;;) {
97411677aeSAaron LI if (*len == 0) {
98411677aeSAaron LI /* Ran out of packet data without finding it */
99411677aeSAaron LI return NULL;
100411677aeSAaron LI }
101*ed775ee7SAntonio Huete Jimenez if (GET_U_1(*pptr) == '\0') {
102411677aeSAaron LI /* Found it */
103411677aeSAaron LI break;
104411677aeSAaron LI }
105411677aeSAaron LI /* Keep scanning */
10641c99275SPeter Avalos (*pptr)++;
10741c99275SPeter Avalos (*len)--;
10841c99275SPeter Avalos }
109411677aeSAaron LI /* Skip the NUL terminator */
11041c99275SPeter Avalos (*pptr)++;
11141c99275SPeter Avalos (*len)--;
11241c99275SPeter Avalos return s;
11341c99275SPeter Avalos }
11441c99275SPeter Avalos
11541c99275SPeter Avalos static const char *
z_triple(const char * class,const char * inst,const char * recipient)116411677aeSAaron LI z_triple(const char *class, const char *inst, const char *recipient)
11741c99275SPeter Avalos {
11841c99275SPeter Avalos if (!*recipient)
11941c99275SPeter Avalos recipient = "*";
12041c99275SPeter Avalos snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient);
12141c99275SPeter Avalos z_buf[sizeof(z_buf)-1] = '\0';
12241c99275SPeter Avalos return z_buf;
12341c99275SPeter Avalos }
12441c99275SPeter Avalos
12541c99275SPeter Avalos static const char *
str_to_lower(const char * string)126411677aeSAaron LI str_to_lower(const char *string)
12741c99275SPeter Avalos {
128411677aeSAaron LI char *zb_string;
129411677aeSAaron LI
13041c99275SPeter Avalos strncpy(z_buf, string, sizeof(z_buf));
13141c99275SPeter Avalos z_buf[sizeof(z_buf)-1] = '\0';
13241c99275SPeter Avalos
133411677aeSAaron LI zb_string = z_buf;
134411677aeSAaron LI while (*zb_string) {
135*ed775ee7SAntonio Huete Jimenez *zb_string = ND_ASCII_TOLOWER(*zb_string);
136411677aeSAaron LI zb_string++;
13741c99275SPeter Avalos }
13841c99275SPeter Avalos
13941c99275SPeter Avalos return z_buf;
14041c99275SPeter Avalos }
14141c99275SPeter Avalos
14241c99275SPeter Avalos void
zephyr_print(netdissect_options * ndo,const u_char * cp,u_int length)143*ed775ee7SAntonio Huete Jimenez zephyr_print(netdissect_options *ndo, const u_char *cp, u_int length)
14441c99275SPeter Avalos {
145*ed775ee7SAntonio Huete Jimenez struct z_packet z = {
146*ed775ee7SAntonio Huete Jimenez NULL, /* version */
147*ed775ee7SAntonio Huete Jimenez 0, /* numfields */
148*ed775ee7SAntonio Huete Jimenez 0, /* kind */
149*ed775ee7SAntonio Huete Jimenez NULL, /* uid */
150*ed775ee7SAntonio Huete Jimenez 0, /* port */
151*ed775ee7SAntonio Huete Jimenez 0, /* auth */
152*ed775ee7SAntonio Huete Jimenez 0, /* authlen */
153*ed775ee7SAntonio Huete Jimenez NULL, /* authdata */
154*ed775ee7SAntonio Huete Jimenez NULL, /* class */
155*ed775ee7SAntonio Huete Jimenez NULL, /* inst */
156*ed775ee7SAntonio Huete Jimenez NULL, /* opcode */
157*ed775ee7SAntonio Huete Jimenez NULL, /* sender */
158*ed775ee7SAntonio Huete Jimenez NULL, /* recipient */
159*ed775ee7SAntonio Huete Jimenez NULL, /* format */
160*ed775ee7SAntonio Huete Jimenez 0, /* cksum */
161*ed775ee7SAntonio Huete Jimenez 0, /* multi */
162*ed775ee7SAntonio Huete Jimenez NULL /* multi_uid */
163*ed775ee7SAntonio Huete Jimenez };
164411677aeSAaron LI const char *parse = (const char *) cp;
16541c99275SPeter Avalos int parselen = length;
166411677aeSAaron LI const char *s;
16741c99275SPeter Avalos int lose = 0;
16841c99275SPeter Avalos
169*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "zephyr";
170ea7b4bf5SPeter Avalos /* squelch compiler warnings */
171ea7b4bf5SPeter Avalos
17241c99275SPeter Avalos #define PARSE_STRING \
173*ed775ee7SAntonio Huete Jimenez s = parse_field(ndo, &parse, &parselen); \
17441c99275SPeter Avalos if (!s) lose = 1;
17541c99275SPeter Avalos
17641c99275SPeter Avalos #define PARSE_FIELD_INT(field) \
17741c99275SPeter Avalos PARSE_STRING \
17841c99275SPeter Avalos if (!lose) field = strtol(s, 0, 16);
17941c99275SPeter Avalos
18041c99275SPeter Avalos #define PARSE_FIELD_STR(field) \
18141c99275SPeter Avalos PARSE_STRING \
18241c99275SPeter Avalos if (!lose) field = s;
18341c99275SPeter Avalos
18441c99275SPeter Avalos PARSE_FIELD_STR(z.version);
185*ed775ee7SAntonio Huete Jimenez if (lose)
186*ed775ee7SAntonio Huete Jimenez goto invalid;
187*ed775ee7SAntonio Huete Jimenez
18841c99275SPeter Avalos if (strncmp(z.version, "ZEPH", 4))
18941c99275SPeter Avalos return;
19041c99275SPeter Avalos
19141c99275SPeter Avalos PARSE_FIELD_INT(z.numfields);
19241c99275SPeter Avalos PARSE_FIELD_INT(z.kind);
19341c99275SPeter Avalos PARSE_FIELD_STR(z.uid);
19441c99275SPeter Avalos PARSE_FIELD_INT(z.port);
19541c99275SPeter Avalos PARSE_FIELD_INT(z.auth);
19641c99275SPeter Avalos PARSE_FIELD_INT(z.authlen);
19741c99275SPeter Avalos PARSE_FIELD_STR(z.authdata);
19841c99275SPeter Avalos PARSE_FIELD_STR(z.class);
19941c99275SPeter Avalos PARSE_FIELD_STR(z.inst);
20041c99275SPeter Avalos PARSE_FIELD_STR(z.opcode);
20141c99275SPeter Avalos PARSE_FIELD_STR(z.sender);
20241c99275SPeter Avalos PARSE_FIELD_STR(z.recipient);
20341c99275SPeter Avalos PARSE_FIELD_STR(z.format);
20441c99275SPeter Avalos PARSE_FIELD_INT(z.cksum);
20541c99275SPeter Avalos PARSE_FIELD_INT(z.multi);
20641c99275SPeter Avalos PARSE_FIELD_STR(z.multi_uid);
20741c99275SPeter Avalos
208411677aeSAaron LI if (lose)
209*ed775ee7SAntonio Huete Jimenez goto invalid;
21041c99275SPeter Avalos
211*ed775ee7SAntonio Huete Jimenez ND_PRINT(" zephyr");
21241c99275SPeter Avalos if (strncmp(z.version+4, "0.2", 3)) {
213*ed775ee7SAntonio Huete Jimenez ND_PRINT(" v%s", z.version+4);
21441c99275SPeter Avalos return;
21541c99275SPeter Avalos }
21641c99275SPeter Avalos
217*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", tok2str(z_types, "type %d", z.kind));
21841c99275SPeter Avalos if (z.kind == Z_PACKET_SERVACK) {
21941c99275SPeter Avalos /* Initialization to silence warnings */
220411677aeSAaron LI const char *ackdata = NULL;
22141c99275SPeter Avalos PARSE_FIELD_STR(ackdata);
22241c99275SPeter Avalos if (!lose && strcmp(ackdata, "SENT"))
223*ed775ee7SAntonio Huete Jimenez ND_PRINT("/%s", str_to_lower(ackdata));
22441c99275SPeter Avalos }
225*ed775ee7SAntonio Huete Jimenez if (*z.sender) ND_PRINT(" %s", z.sender);
22641c99275SPeter Avalos
22741c99275SPeter Avalos if (!strcmp(z.class, "USER_LOCATE")) {
22841c99275SPeter Avalos if (!strcmp(z.opcode, "USER_HIDE"))
229*ed775ee7SAntonio Huete Jimenez ND_PRINT(" hide");
23041c99275SPeter Avalos else if (!strcmp(z.opcode, "USER_UNHIDE"))
231*ed775ee7SAntonio Huete Jimenez ND_PRINT(" unhide");
23241c99275SPeter Avalos else
233*ed775ee7SAntonio Huete Jimenez ND_PRINT(" locate %s", z.inst);
23441c99275SPeter Avalos return;
23541c99275SPeter Avalos }
23641c99275SPeter Avalos
23741c99275SPeter Avalos if (!strcmp(z.class, "ZEPHYR_ADMIN")) {
238*ed775ee7SAntonio Huete Jimenez ND_PRINT(" zephyr-admin %s", str_to_lower(z.opcode));
23941c99275SPeter Avalos return;
24041c99275SPeter Avalos }
24141c99275SPeter Avalos
24241c99275SPeter Avalos if (!strcmp(z.class, "ZEPHYR_CTL")) {
24341c99275SPeter Avalos if (!strcmp(z.inst, "CLIENT")) {
24441c99275SPeter Avalos if (!strcmp(z.opcode, "SUBSCRIBE") ||
24541c99275SPeter Avalos !strcmp(z.opcode, "SUBSCRIBE_NODEFS") ||
24641c99275SPeter Avalos !strcmp(z.opcode, "UNSUBSCRIBE")) {
24741c99275SPeter Avalos
248*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %ssub%s", strcmp(z.opcode, "SUBSCRIBE") ? "un" : "",
24941c99275SPeter Avalos strcmp(z.opcode, "SUBSCRIBE_NODEFS") ? "" :
250*ed775ee7SAntonio Huete Jimenez "-nodefs");
25141c99275SPeter Avalos if (z.kind != Z_PACKET_SERVACK) {
25241c99275SPeter Avalos /* Initialization to silence warnings */
253411677aeSAaron LI const char *c = NULL, *i = NULL, *r = NULL;
25441c99275SPeter Avalos PARSE_FIELD_STR(c);
25541c99275SPeter Avalos PARSE_FIELD_STR(i);
25641c99275SPeter Avalos PARSE_FIELD_STR(r);
257*ed775ee7SAntonio Huete Jimenez if (!lose) ND_PRINT(" %s", z_triple(c, i, r));
25841c99275SPeter Avalos }
25941c99275SPeter Avalos return;
26041c99275SPeter Avalos }
26141c99275SPeter Avalos
26241c99275SPeter Avalos if (!strcmp(z.opcode, "GIMME")) {
263*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ret");
26441c99275SPeter Avalos return;
26541c99275SPeter Avalos }
26641c99275SPeter Avalos
26741c99275SPeter Avalos if (!strcmp(z.opcode, "GIMMEDEFS")) {
268*ed775ee7SAntonio Huete Jimenez ND_PRINT(" gimme-defs");
26941c99275SPeter Avalos return;
27041c99275SPeter Avalos }
27141c99275SPeter Avalos
27241c99275SPeter Avalos if (!strcmp(z.opcode, "CLEARSUB")) {
273*ed775ee7SAntonio Huete Jimenez ND_PRINT(" clear-subs");
27441c99275SPeter Avalos return;
27541c99275SPeter Avalos }
27641c99275SPeter Avalos
277*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", str_to_lower(z.opcode));
27841c99275SPeter Avalos return;
27941c99275SPeter Avalos }
28041c99275SPeter Avalos
28141c99275SPeter Avalos if (!strcmp(z.inst, "HM")) {
282*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", str_to_lower(z.opcode));
28341c99275SPeter Avalos return;
28441c99275SPeter Avalos }
28541c99275SPeter Avalos
28641c99275SPeter Avalos if (!strcmp(z.inst, "REALM")) {
28741c99275SPeter Avalos if (!strcmp(z.opcode, "ADD_SUBSCRIBE"))
288*ed775ee7SAntonio Huete Jimenez ND_PRINT(" realm add-subs");
28941c99275SPeter Avalos if (!strcmp(z.opcode, "REQ_SUBSCRIBE"))
290*ed775ee7SAntonio Huete Jimenez ND_PRINT(" realm req-subs");
29141c99275SPeter Avalos if (!strcmp(z.opcode, "RLM_SUBSCRIBE"))
292*ed775ee7SAntonio Huete Jimenez ND_PRINT(" realm rlm-sub");
29341c99275SPeter Avalos if (!strcmp(z.opcode, "RLM_UNSUBSCRIBE"))
294*ed775ee7SAntonio Huete Jimenez ND_PRINT(" realm rlm-unsub");
29541c99275SPeter Avalos return;
29641c99275SPeter Avalos }
29741c99275SPeter Avalos }
29841c99275SPeter Avalos
29941c99275SPeter Avalos if (!strcmp(z.class, "HM_CTL")) {
300*ed775ee7SAntonio Huete Jimenez ND_PRINT(" hm_ctl %s", str_to_lower(z.inst));
301*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", str_to_lower(z.opcode));
30241c99275SPeter Avalos return;
30341c99275SPeter Avalos }
30441c99275SPeter Avalos
30541c99275SPeter Avalos if (!strcmp(z.class, "HM_STAT")) {
30641c99275SPeter Avalos if (!strcmp(z.inst, "HMST_CLIENT") && !strcmp(z.opcode, "GIMMESTATS")) {
307*ed775ee7SAntonio Huete Jimenez ND_PRINT(" get-client-stats");
30841c99275SPeter Avalos return;
30941c99275SPeter Avalos }
31041c99275SPeter Avalos }
31141c99275SPeter Avalos
31241c99275SPeter Avalos if (!strcmp(z.class, "WG_CTL")) {
313*ed775ee7SAntonio Huete Jimenez ND_PRINT(" wg_ctl %s", str_to_lower(z.inst));
314*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", str_to_lower(z.opcode));
31541c99275SPeter Avalos return;
31641c99275SPeter Avalos }
31741c99275SPeter Avalos
31841c99275SPeter Avalos if (!strcmp(z.class, "LOGIN")) {
31941c99275SPeter Avalos if (!strcmp(z.opcode, "USER_FLUSH")) {
320*ed775ee7SAntonio Huete Jimenez ND_PRINT(" flush_locs");
32141c99275SPeter Avalos return;
32241c99275SPeter Avalos }
32341c99275SPeter Avalos
32441c99275SPeter Avalos if (!strcmp(z.opcode, "NONE") ||
32541c99275SPeter Avalos !strcmp(z.opcode, "OPSTAFF") ||
32641c99275SPeter Avalos !strcmp(z.opcode, "REALM-VISIBLE") ||
32741c99275SPeter Avalos !strcmp(z.opcode, "REALM-ANNOUNCED") ||
32841c99275SPeter Avalos !strcmp(z.opcode, "NET-VISIBLE") ||
32941c99275SPeter Avalos !strcmp(z.opcode, "NET-ANNOUNCED")) {
330*ed775ee7SAntonio Huete Jimenez ND_PRINT(" set-exposure %s", str_to_lower(z.opcode));
33141c99275SPeter Avalos return;
33241c99275SPeter Avalos }
33341c99275SPeter Avalos }
33441c99275SPeter Avalos
33541c99275SPeter Avalos if (!*z.recipient)
33641c99275SPeter Avalos z.recipient = "*";
33741c99275SPeter Avalos
338*ed775ee7SAntonio Huete Jimenez ND_PRINT(" to %s", z_triple(z.class, z.inst, z.recipient));
33941c99275SPeter Avalos if (*z.opcode)
340*ed775ee7SAntonio Huete Jimenez ND_PRINT(" op %s", z.opcode);
341411677aeSAaron LI return;
342411677aeSAaron LI
343*ed775ee7SAntonio Huete Jimenez invalid:
344*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
34541c99275SPeter Avalos }
346