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 } 312