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