/* * Decode and print Zephyr packets. * * http://web.mit.edu/zephyr/doc/protocol * * Copyright (c) 2001 Nickolai Zeldovich * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code * distributions retain the above copyright notice and this paragraph * in its entirety, and (2) distributions including binary code include * the above copyright notice and this paragraph in its entirety in * the documentation or other materials provided with the distribution. * The name of the author(s) may not be used to endorse or promote * products derived from this software without specific prior written * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "netdissect.h" struct z_packet { const char *version; int numfields; int kind; const char *uid; int port; int auth; int authlen; const char *authdata; const char *class; const char *inst; const char *opcode; const char *sender; const char *recipient; const char *format; int cksum; int multi; const char *multi_uid; /* Other fields follow here.. */ }; enum z_packet_type { Z_PACKET_UNSAFE = 0, Z_PACKET_UNACKED, Z_PACKET_ACKED, Z_PACKET_HMACK, Z_PACKET_HMCTL, Z_PACKET_SERVACK, Z_PACKET_SERVNAK, Z_PACKET_CLIENTACK, Z_PACKET_STAT }; static const struct tok z_types[] = { { Z_PACKET_UNSAFE, "unsafe" }, { Z_PACKET_UNACKED, "unacked" }, { Z_PACKET_ACKED, "acked" }, { Z_PACKET_HMACK, "hm-ack" }, { Z_PACKET_HMCTL, "hm-ctl" }, { Z_PACKET_SERVACK, "serv-ack" }, { Z_PACKET_SERVNAK, "serv-nak" }, { Z_PACKET_CLIENTACK, "client-ack" }, { Z_PACKET_STAT, "stat" } }; static char z_buf[256]; static const char * parse_field(netdissect_options *ndo, const char **pptr, int *len) { const char *s; if (*len <= 0 || !pptr || !*pptr) return NULL; if (*pptr > (const char *) ndo->ndo_snapend) return NULL; s = *pptr; while (*pptr <= (const char *) ndo->ndo_snapend && *len >= 0 && **pptr) { (*pptr)++; (*len)--; } (*pptr)++; (*len)--; if (*len < 0 || *pptr > (const char *) ndo->ndo_snapend) return NULL; return s; } static const char * z_triple(const char *class, const char *inst, const char *recipient) { if (!*recipient) recipient = "*"; snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient); z_buf[sizeof(z_buf)-1] = '\0'; return z_buf; } static const char * str_to_lower(const char *string) { char *zb_string; strncpy(z_buf, string, sizeof(z_buf)); z_buf[sizeof(z_buf)-1] = '\0'; zb_string = z_buf; while (*zb_string) { *zb_string = tolower((unsigned char)(*zb_string)); zb_string++; } return z_buf; } void zephyr_print(netdissect_options *ndo, const u_char *cp, int length) { struct z_packet z; const char *parse = (const char *) cp; int parselen = length; const char *s; int lose = 0; /* squelch compiler warnings */ z.kind = 0; z.class = 0; z.inst = 0; z.opcode = 0; z.sender = 0; z.recipient = 0; #define PARSE_STRING \ s = parse_field(ndo, &parse, &parselen); \ if (!s) lose = 1; #define PARSE_FIELD_INT(field) \ PARSE_STRING \ if (!lose) field = strtol(s, 0, 16); #define PARSE_FIELD_STR(field) \ PARSE_STRING \ if (!lose) field = s; PARSE_FIELD_STR(z.version); if (lose) return; if (strncmp(z.version, "ZEPH", 4)) return; PARSE_FIELD_INT(z.numfields); PARSE_FIELD_INT(z.kind); PARSE_FIELD_STR(z.uid); PARSE_FIELD_INT(z.port); PARSE_FIELD_INT(z.auth); PARSE_FIELD_INT(z.authlen