198524Sfenner/* 298524Sfenner * Decode and print Zephyr packets. 398524Sfenner * 4147899Ssam * http://web.mit.edu/zephyr/doc/protocol 5147899Ssam * 698524Sfenner * Copyright (c) 2001 Nickolai Zeldovich <kolya@MIT.EDU> 798524Sfenner * All rights reserved. 898524Sfenner * 998524Sfenner * Redistribution and use in source and binary forms, with or without 1098524Sfenner * modification, are permitted provided that: (1) source code 1198524Sfenner * distributions retain the above copyright notice and this paragraph 1298524Sfenner * in its entirety, and (2) distributions including binary code include 1398524Sfenner * the above copyright notice and this paragraph in its entirety in 1498524Sfenner * the documentation or other materials provided with the distribution. 1598524Sfenner * The name of the author(s) may not be used to endorse or promote 1698524Sfenner * products derived from this software without specific prior written 1798524Sfenner * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY 1898524Sfenner * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE 1998524Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2098524Sfenner * PURPOSE. 2198524Sfenner */ 2298524Sfenner 2398524Sfenner#ifndef lint 24127668Sbmsstatic const char rcsid[] _U_ = 25190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-zephyr.c,v 1.10 2007-08-09 18:47:27 hannes Exp $"; 2698524Sfenner#endif 2798524Sfenner 2898524Sfenner#ifdef HAVE_CONFIG_H 2998524Sfenner#include "config.h" 3098524Sfenner#endif 3198524Sfenner 32127668Sbms#include <tcpdump-stdinc.h> 33127668Sbms 3498524Sfenner#include <stdio.h> 3598524Sfenner#include <string.h> 3698524Sfenner#include <stdlib.h> 3798524Sfenner 3898524Sfenner#include "interface.h" 3998524Sfenner 4098524Sfennerstruct z_packet { 4198524Sfenner char *version; 4298524Sfenner int numfields; 4398524Sfenner int kind; 4498524Sfenner char *uid; 4598524Sfenner int port; 4698524Sfenner int auth; 4798524Sfenner int authlen; 4898524Sfenner char *authdata; 4998524Sfenner char *class; 5098524Sfenner char *inst; 5198524Sfenner char *opcode; 5298524Sfenner char *sender; 53127668Sbms const char *recipient; 5498524Sfenner char *format; 5598524Sfenner int cksum; 5698524Sfenner int multi; 5798524Sfenner char *multi_uid; 5898524Sfenner /* Other fields follow here.. */ 5998524Sfenner}; 6098524Sfenner 61111726Sfennerenum z_packet_type { 6298524Sfenner Z_PACKET_UNSAFE = 0, 6398524Sfenner Z_PACKET_UNACKED, 6498524Sfenner Z_PACKET_ACKED, 6598524Sfenner Z_PACKET_HMACK, 6698524Sfenner Z_PACKET_HMCTL, 6798524Sfenner Z_PACKET_SERVACK, 6898524Sfenner Z_PACKET_SERVNAK, 6998524Sfenner Z_PACKET_CLIENTACK, 7098524Sfenner Z_PACKET_STAT 71111726Sfenner}; 7298524Sfenner 7398524Sfennerstatic struct tok z_types[] = { 7498524Sfenner { Z_PACKET_UNSAFE, "unsafe" }, 7598524Sfenner { Z_PACKET_UNACKED, "unacked" }, 7698524Sfenner { Z_PACKET_ACKED, "acked" }, 7798524Sfenner { Z_PACKET_HMACK, "hm-ack" }, 7898524Sfenner { Z_PACKET_HMCTL, "hm-ctl" }, 7998524Sfenner { Z_PACKET_SERVACK, "serv-ack" }, 8098524Sfenner { Z_PACKET_SERVNAK, "serv-nak" }, 8198524Sfenner { Z_PACKET_CLIENTACK, "client-ack" }, 8298524Sfenner { Z_PACKET_STAT, "stat" } 8398524Sfenner}; 8498524Sfenner 8598524Sfennerchar z_buf[256]; 8698524Sfenner 8798524Sfennerstatic char * 8898524Sfennerparse_field(char **pptr, int *len) 8998524Sfenner{ 9098524Sfenner char *s; 9198524Sfenner 9298524Sfenner if (*len <= 0 || !pptr || !*pptr) 9398524Sfenner return NULL; 9498524Sfenner if (*pptr > (char *) snapend) 9598524Sfenner return NULL; 9698524Sfenner 9798524Sfenner s = *pptr; 9898524Sfenner while (*pptr <= (char *) snapend && *len >= 0 && **pptr) { 9998524Sfenner (*pptr)++; 10098524Sfenner (*len)--; 10198524Sfenner } 10298524Sfenner (*pptr)++; 10398524Sfenner (*len)--; 10498524Sfenner if (*len < 0 || *pptr > (char *) snapend) 10598524Sfenner return NULL; 10698524Sfenner return s; 10798524Sfenner} 10898524Sfenner 10998524Sfennerstatic const char * 110127668Sbmsz_triple(char *class, char *inst, const char *recipient) 11198524Sfenner{ 11298524Sfenner if (!*recipient) 11398524Sfenner recipient = "*"; 11498524Sfenner snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient); 11598524Sfenner z_buf[sizeof(z_buf)-1] = '\0'; 11698524Sfenner return z_buf; 11798524Sfenner} 11898524Sfenner 11998524Sfennerstatic const char * 12098524Sfennerstr_to_lower(char *string) 12198524Sfenner{ 12298524Sfenner strncpy(z_buf, string, sizeof(z_buf)); 12398524Sfenner z_buf[sizeof(z_buf)-1] = '\0'; 12498524Sfenner 12598524Sfenner string = z_buf; 12698524Sfenner while (*string) { 127111726Sfenner *string = tolower((unsigned char)(*string)); 12898524Sfenner string++; 12998524Sfenner } 13098524Sfenner 13198524Sfenner return z_buf; 13298524Sfenner} 13398524Sfenner 13498524Sfennervoid 13598524Sfennerzephyr_print(const u_char *cp, int length) 13698524Sfenner{ 13798524Sfenner struct z_packet z; 13898524Sfenner char *parse = (char *) cp; 13998524Sfenner int parselen = length; 14098524Sfenner char *s; 14198524Sfenner int lose = 0; 14298524Sfenner 143190207Srpaulo /* squelch compiler warnings */ 144190207Srpaulo 145190207Srpaulo z.kind = 0; 146190207Srpaulo z.class = 0; 147190207Srpaulo z.inst = 0; 148190207Srpaulo z.opcode = 0; 149190207Srpaulo z.sender = 0; 150190207Srpaulo z.recipient = 0; 151190207Srpaulo 15298524Sfenner#define PARSE_STRING \ 15398524Sfenner s = parse_field(&parse, &parselen); \ 15498524Sfenner if (!s) lose = 1; 15598524Sfenner 15698524Sfenner#define PARSE_FIELD_INT(field) \ 15798524Sfenner PARSE_STRING \ 15898524Sfenner if (!lose) field = strtol(s, 0, 16); 15998524Sfenner 16098524Sfenner#define PARSE_FIELD_STR(field) \ 16198524Sfenner PARSE_STRING \ 16298524Sfenner if (!lose) field = s; 16398524Sfenner 16498524Sfenner PARSE_FIELD_STR(z.version); 16598524Sfenner if (lose) return; 16698524Sfenner if (strncmp(z.version, "ZEPH", 4)) 16798524Sfenner return; 16898524Sfenner 16998524Sfenner PARSE_FIELD_INT(z.numfields); 17098524Sfenner PARSE_FIELD_INT(z.kind); 17198524Sfenner PARSE_FIELD_STR(z.uid); 17298524Sfenner PARSE_FIELD_INT(z.port); 17398524Sfenner PARSE_FIELD_INT(z.auth); 17498524Sfenner PARSE_FIELD_INT(z.authlen); 17598524Sfenner PARSE_FIELD_STR(z.authdata); 17698524Sfenner PARSE_FIELD_STR(z.class); 17798524Sfenner PARSE_FIELD_STR(z.inst); 17898524Sfenner PARSE_FIELD_STR(z.opcode); 17998524Sfenner PARSE_FIELD_STR(z.sender); 18098524Sfenner PARSE_FIELD_STR(z.recipient); 18198524Sfenner PARSE_FIELD_STR(z.format); 18298524Sfenner PARSE_FIELD_INT(z.cksum); 18398524Sfenner PARSE_FIELD_INT(z.multi); 18498524Sfenner PARSE_FIELD_STR(z.multi_uid); 18598524Sfenner 18698524Sfenner if (lose) { 18798524Sfenner printf(" [|zephyr] (%d)", length); 18898524Sfenner return; 18998524Sfenner } 19098524Sfenner 19198524Sfenner printf(" zephyr"); 19298524Sfenner if (strncmp(z.version+4, "0.2", 3)) { 19398524Sfenner printf(" v%s", z.version+4); 19498524Sfenner return; 19598524Sfenner } 19698524Sfenner 19798524Sfenner printf(" %s", tok2str(z_types, "type %d", z.kind)); 19898524Sfenner if (z.kind == Z_PACKET_SERVACK) { 19998524Sfenner /* Initialization to silence warnings */ 20098524Sfenner char *ackdata = NULL; 20198524Sfenner PARSE_FIELD_STR(ackdata); 20298524Sfenner if (!lose && strcmp(ackdata, "SENT")) 20398524Sfenner printf("/%s", str_to_lower(ackdata)); 20498524Sfenner } 20598524Sfenner if (*z.sender) printf(" %s", z.sender); 20698524Sfenner 20798524Sfenner if (!strcmp(z.class, "USER_LOCATE")) { 20898524Sfenner if (!strcmp(z.opcode, "USER_HIDE")) 20998524Sfenner printf(" hide"); 21098524Sfenner else if (!strcmp(z.opcode, "USER_UNHIDE")) 21198524Sfenner printf(" unhide"); 21298524Sfenner else 21398524Sfenner printf(" locate %s", z.inst); 21498524Sfenner return; 21598524Sfenner } 21698524Sfenner 21798524Sfenner if (!strcmp(z.class, "ZEPHYR_ADMIN")) { 21898524Sfenner printf(" zephyr-admin %s", str_to_lower(z.opcode)); 21998524Sfenner return; 22098524Sfenner } 22198524Sfenner 22298524Sfenner if (!strcmp(z.class, "ZEPHYR_CTL")) { 22398524Sfenner if (!strcmp(z.inst, "CLIENT")) { 22498524Sfenner if (!strcmp(z.opcode, "SUBSCRIBE") || 22598524Sfenner !strcmp(z.opcode, "SUBSCRIBE_NODEFS") || 22698524Sfenner !strcmp(z.opcode, "UNSUBSCRIBE")) { 22798524Sfenner 22898524Sfenner printf(" %ssub%s", strcmp(z.opcode, "SUBSCRIBE") ? "un" : "", 22998524Sfenner strcmp(z.opcode, "SUBSCRIBE_NODEFS") ? "" : 23098524Sfenner "-nodefs"); 23198524Sfenner if (z.kind != Z_PACKET_SERVACK) { 23298524Sfenner /* Initialization to silence warnings */ 23398524Sfenner char *c = NULL, *i = NULL, *r = NULL; 23498524Sfenner PARSE_FIELD_STR(c); 23598524Sfenner PARSE_FIELD_STR(i); 23698524Sfenner PARSE_FIELD_STR(r); 23798524Sfenner if (!lose) printf(" %s", z_triple(c, i, r)); 23898524Sfenner } 23998524Sfenner return; 24098524Sfenner } 24198524Sfenner 24298524Sfenner if (!strcmp(z.opcode, "GIMME")) { 24398524Sfenner printf(" ret"); 24498524Sfenner return; 24598524Sfenner } 24698524Sfenner 24798524Sfenner if (!strcmp(z.opcode, "GIMMEDEFS")) { 24898524Sfenner printf(" gimme-defs"); 24998524Sfenner return; 25098524Sfenner } 25198524Sfenner 25298524Sfenner if (!strcmp(z.opcode, "CLEARSUB")) { 25398524Sfenner printf(" clear-subs"); 25498524Sfenner return; 25598524Sfenner } 25698524Sfenner 25798524Sfenner printf(" %s", str_to_lower(z.opcode)); 25898524Sfenner return; 25998524Sfenner } 26098524Sfenner 26198524Sfenner if (!strcmp(z.inst, "HM")) { 26298524Sfenner printf(" %s", str_to_lower(z.opcode)); 26398524Sfenner return; 26498524Sfenner } 26598524Sfenner 26698524Sfenner if (!strcmp(z.inst, "REALM")) { 26798524Sfenner if (!strcmp(z.opcode, "ADD_SUBSCRIBE")) 26898524Sfenner printf(" realm add-subs"); 26998524Sfenner if (!strcmp(z.opcode, "REQ_SUBSCRIBE")) 27098524Sfenner printf(" realm req-subs"); 27198524Sfenner if (!strcmp(z.opcode, "RLM_SUBSCRIBE")) 27298524Sfenner printf(" realm rlm-sub"); 27398524Sfenner if (!strcmp(z.opcode, "RLM_UNSUBSCRIBE")) 27498524Sfenner printf(" realm rlm-unsub"); 27598524Sfenner return; 27698524Sfenner } 27798524Sfenner } 27898524Sfenner 27998524Sfenner if (!strcmp(z.class, "HM_CTL")) { 28098524Sfenner printf(" hm_ctl %s", str_to_lower(z.inst)); 28198524Sfenner printf(" %s", str_to_lower(z.opcode)); 28298524Sfenner return; 28398524Sfenner } 28498524Sfenner 28598524Sfenner if (!strcmp(z.class, "HM_STAT")) { 28698524Sfenner if (!strcmp(z.inst, "HMST_CLIENT") && !strcmp(z.opcode, "GIMMESTATS")) { 28798524Sfenner printf(" get-client-stats"); 28898524Sfenner return; 28998524Sfenner } 29098524Sfenner } 29198524Sfenner 29298524Sfenner if (!strcmp(z.class, "WG_CTL")) { 29398524Sfenner printf(" wg_ctl %s", str_to_lower(z.inst)); 29498524Sfenner printf(" %s", str_to_lower(z.opcode)); 29598524Sfenner return; 29698524Sfenner } 29798524Sfenner 29898524Sfenner if (!strcmp(z.class, "LOGIN")) { 29998524Sfenner if (!strcmp(z.opcode, "USER_FLUSH")) { 30098524Sfenner printf(" flush_locs"); 30198524Sfenner return; 30298524Sfenner } 30398524Sfenner 30498524Sfenner if (!strcmp(z.opcode, "NONE") || 30598524Sfenner !strcmp(z.opcode, "OPSTAFF") || 30698524Sfenner !strcmp(z.opcode, "REALM-VISIBLE") || 30798524Sfenner !strcmp(z.opcode, "REALM-ANNOUNCED") || 30898524Sfenner !strcmp(z.opcode, "NET-VISIBLE") || 30998524Sfenner !strcmp(z.opcode, "NET-ANNOUNCED")) { 31098524Sfenner printf(" set-exposure %s", str_to_lower(z.opcode)); 31198524Sfenner return; 31298524Sfenner } 31398524Sfenner } 31498524Sfenner 31598524Sfenner if (!*z.recipient) 31698524Sfenner z.recipient = "*"; 31798524Sfenner 31898524Sfenner printf(" to %s", z_triple(z.class, z.inst, z.recipient)); 31998524Sfenner if (*z.opcode) 32098524Sfenner printf(" op %s", z.opcode); 32198524Sfenner return; 32298524Sfenner} 323