Instead of using the non-standard conforming %+ format string,
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-zephyr.c
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 }