/* * Debug packet dumper * * $Id: dump.c,v 1.3 2008/01/01 00:14:50 chas3 Exp $ * */ #if HAVE_CONFIG_H #include #endif /* System includes */ #include #include #include #include #include #include #include #include /* Local includes */ #include "atmsap.h" #include "dump.h" #include "lane.h" #include "load.h" #include "units.h" /* Local function prototypes */ static void dump_init0(void); static void dump_init1(void); static void dump_dump(void); static void dump_release(void); /* Data */ #define BUFSIZE 256 static const char *rcsid = "$Id: dump.c,v 1.3 2008/01/01 00:14:50 chas3 Exp $"; const Unit_t dump_unit = { "dump", &dump_init0, &dump_init1, &dump_dump, &dump_release }; DumpType_t dump_type; static DumpType_t dump_open; static FILE *dump_filep; static const char *dump_filename = "/tmp/lane.log"; static const char *dump_console = "/dev/console"; /* Functions */ static const char* dump_opcode_text(unsigned short opcode); static const char* dump_status_text(unsigned short status); static const char* dump_maxframe(unsigned char size); static const char* dump_lantype(unsigned char lantype); static void dump_atmtext(const AtmAddr_t addr); /* Initialize local data */ static void dump_init0(void) { dump_filep = NULL; dump_open = dump_type; switch (dump_open) { case DT_NONE: case DT_CMN_ERR: break; case DT_STDERR: dump_filep = stderr; break; case DT_FILE: dump_filep = fopen(dump_filename, "a"); if (dump_filep == NULL) { dump_open = DT_STDERR; dump_filep = stderr; dump_printf(EL_WARN, "Cannot open log file %s", dump_filename); } break; case DT_SYSLOG: openlog("lane", LOG_PID | LOG_CONS, LOG_DAEMON); break; case DT_CONSOLE: dump_filep = fopen(dump_console, "w"); if (dump_filep == NULL) { dump_open = DT_STDERR; dump_filep = stderr; dump_printf(EL_WARN, "Cannot open console log"); } break; } dump_printf(EL_DEBUG, "Log opened"); } /* Initialization for data that needs other units */ static void dump_init1(void) { set_var_str(&dump_unit, "version", rcsid); Debug_unit(&dump_unit, "Initialized."); } /* Dump status, local data etc. */ static void dump_dump(void) { static const char *dumptypes [] = { "none", "standard error", "file", "syslog()", "cmn_err()", "/dev/console" }; Debug_unit(&dump_unit, "Dumping to %s, filename: %s", dumptypes[dump_open], dump_filename); } /* Release allocated memory, close files etc. */ static void dump_release(void) { int flush_ret; Debug_unit(&dump_unit, "Releasing unit"); dump_printf(EL_DEBUG, "Closing log file"); switch (dump_open) { case DT_NONE: case DT_CMN_ERR: break; case DT_STDERR: flush_ret = fflush(stderr); assert(flush_ret == 0); break; case DT_FILE: if (fclose(dump_filep) != 0) { dump_open = DT_STDERR; dump_filep = stderr; dump_printf(EL_WARN, "Cannot close log file %s", dump_filename); } break; case DT_SYSLOG: closelog(); break; case DT_CONSOLE: if (fclose(dump_filep) != 0) { dump_open = DT_STDERR; dump_filep = stderr; dump_printf(EL_WARN, "Cannot close console log"); } break; } dump_filep = NULL; dump_open = DT_NONE; } static const int el_to_log[] = { /* EL_CONT, EL_DEBUG, EL_NOTE, EL_WARN, EL_ERROR, EL_PANIC */ LOG_DEBUG, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_ALERT }; static const char *el_prefix[] = { /* EL_CONT, EL_DEBUG, EL_NOTE, EL_WARN, EL_ERROR, EL_PANIC */ "", "DEBUG: ", "NOTE: ", "WARNING: ", "ERROR: ", "PANIC: " }; /* General printing function */ void dump_printf(ErrorLevel_t level, const char *const format, ...) { va_list args; int printf_ret, flush_ret; char buffer[BUFSIZE]; assert(level <= EL_PANIC); switch (dump_open) { case DT_CMN_ERR: case DT_NONE: return; case DT_CONSOLE: case DT_STDERR: case DT_FILE: va_start(args, format); printf_ret = vsnprintf(buffer, BUFSIZE, format, args); assert(printf_ret > 0); printf_ret = fprintf(dump_filep, "%s%s%s", el_prefix[level], buffer, level != EL_CONT? "\n" : ""); assert(printf_ret > 0); va_end(args); flush_ret = fflush(dump_filep); assert(flush_ret == 0); break; case DT_SYSLOG: va_start(args, format); printf_ret = vsnprintf(buffer, BUFSIZE, format, args); assert(printf_ret > 0); syslog(el_to_log[level], "%s", buffer); va_end(args); break; } } /* Unit-specific debugging, can be enabled with variables */ void Debug_unit(const Unit_t *unit, const char *const format, ...) { va_list args; char buffer[2048]; char buffer2[2048]; int sprintf_ret; #ifndef DEBUG if (get_var_bool(unit, "debug") == BL_TRUE) { #endif /* DEBUG */ sprintf_ret = sprintf(buffer, "%s: %s", unit->name, format); assert(sprintf_ret > 0); va_start(args, format); sprintf_ret = vsnprintf(buffer2, 2048, buffer, args); assert(sprintf_ret > 0); va_end(args); dump_printf(EL_DEBUG, "%s", buffer2); #ifndef DEBUG } #endif /* DEBUG */ } void dump_error(const Unit_t *unit, const char *msg) { Debug_unit(unit, "%s: %s", msg, strerror(errno)); } /* Dumping functions, LANE address */ void dump_addr(const LaneDestination_t *addr) { assert(addr != NULL); switch (ntohs(addr->tag)) { case LANE_DEST_NP: dump_printf(EL_CONT, "Not present"); break; case LANE_DEST_MAC: dump_printf(EL_CONT, "MAC addr %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x", addr->a_r.mac_address[0],addr->a_r.mac_address[1], addr->a_r.mac_address[2],addr->a_r.mac_address[3], addr->a_r.mac_address[4],addr->a_r.mac_address[5] ); break; case LANE_DEST_RD: dump_printf(EL_CONT, "Route Designator %4.4x", addr->a_r.route.designator); break; } } /* Dumping functions, ATM address */ void dump_atmaddr(const AtmAddr_t *addr) { int i; char buffer[ATM_ADDR_LEN*3+2]; assert(addr != 0); for (i = 0; iaddr[i]); } dump_printf(EL_DEBUG, "%s", buffer); } static void dump_atmtext(const AtmAddr_t addr) { int i; char buffer[ATM_ADDR_LEN*3+2]; for (i=0;i"; } } static const char* dump_opcode_text(unsigned short opcode) { switch (opcode) { case LE_CONFIGURE_REQUEST : return "LE_CONFIG_REQUEST"; case LE_CONFIGURE_RESPONSE : return "LE_CONFIG_RESPONSE"; case LE_JOIN_REQUEST : return "LE_JOIN_REQUEST"; case LE_JOIN_RESPONSE : return "LE_JOIN_RESPONSE"; case READY_QUERY : return "READY_QUERY"; case READY_IND : return "READY_INDICATION"; case LE_REGISTER_REQUEST : return "LE_REGISTER_REQUEST"; case LE_REGISTER_RESPONSE : return "LE_REGISTER_RESPONSE"; case LE_UNREGISTER_REQUEST : return "LE_UNREGISTER_REQUEST"; case LE_UNREGISTER_RESPONSE : return "LE_UNREGISTER_RESPONSE"; case LE_ARP_REQUEST : return "LE_ARP_REQUEST"; case LE_ARP_RESPONSE : return "LE_ARP_RESPONSE"; case LE_FLUSH_REQUEST : return "LE_FLUSH_REQUEST"; case LE_FLUSH_RESPONSE : return "LE_FLUSH_RESPONSE"; case LE_NARP_REQUEST : return "LE_NARP_REQUEST"; case LE_TOPOLOGY_REQUEST : return "LE_TOPOLOGY_REQUEST"; default : return ""; } } static const char* dump_lantype(unsigned char lantype) { switch (lantype) { case LE_LAN_TYPE_UNSPECIFIED: return "Unspecified"; case LE_LAN_TYPE_802_3: return "Ethernet/IEEE 802.3"; case LE_LAN_TYPE_802_5: return "IEEE 802.5"; default: return ""; } } static const char* dump_maxframe(unsigned char size) { switch (size) { case LE_MAX_FRAME_UNSPECIFIED: return "Unspecified"; case LE_MAX_FRAME_1516: return "1516"; case LE_MAX_FRAME_4544: return "4544"; case LE_MAX_FRAME_9234: return "9234"; case LE_MAX_FRAME_18190: return "18190"; default: return ""; } } void dump_control(const LaneControl_t *c) { dump_printf(EL_DEBUG, "\tMarker:\t0x%4.4hx\n\tProtocol:\t0x%2.2x\n\tVersion:\t0x%2.2x", ntohs(c->marker), c->protocol, c->version); dump_printf(EL_CONT, "\tOpcode:\t\t%s\n\tStatus:\t\t%s\n\tTransactionID:\t0x%8.8x\n\t" "LECID:\t\t0x%4.4hx\n\tFlags:\t\t0x%4.4hx\n", dump_opcode_text(ntohs(c->opcode)), dump_status_text(ntohs(c->status)), ntohl(c->transaction_id), ntohs(c->lecid), ntohs(c->flags)); switch(ntohs(c->opcode)) { case LE_CONFIGURE_REQUEST: case LE_CONFIGURE_RESPONSE: case LE_JOIN_REQUEST: case LE_JOIN_RESPONSE: dump_printf(EL_CONT,"\tSource LAN:\t"); dump_addr(&c->source); dump_printf(EL_CONT,"\n\tSource ATM:\t"); dump_atmtext(c->source_addr); dump_printf(EL_CONT,"\n\tLan type:\t%s\n",dump_lantype(c->lan_type)); dump_printf(EL_CONT,"\tMax frame:\t%s\n",dump_maxframe(c->max_frame)); dump_printf(EL_CONT,"\tELAN name size:\t%d\n",c->elan_name_size); if (c->elan_name_size>0) { dump_printf(EL_CONT,"\nELAN name:\t%s\n",c->elan_name); } break; case LE_ARP_REQUEST: case LE_ARP_RESPONSE: dump_printf(EL_CONT,"\tSource LAN:\t"); dump_addr(&c->source); dump_printf(EL_CONT,"\n\tTarget LAN:\t"); dump_addr(&c->target); dump_printf(EL_CONT,"\n\tSource ATM:\t"); dump_atmtext(c->source_addr); dump_printf(EL_CONT,"\n\tTarget ATM:\t"); dump_atmtext(c->target_addr); dump_printf(EL_CONT,"\n"); break; case LE_FLUSH_REQUEST: case LE_FLUSH_RESPONSE: dump_printf(EL_CONT,"\tSource ATM:\t"); dump_atmtext(c->source_addr); dump_printf(EL_CONT,"\n\tTarget ATM:\t"); dump_atmtext(c->target_addr); dump_printf(EL_CONT,"\n"); break; case LE_REGISTER_REQUEST: case LE_REGISTER_RESPONSE: case LE_UNREGISTER_REQUEST: case LE_UNREGISTER_RESPONSE: dump_printf(EL_CONT,"\tSource LAN:\t"); dump_addr(&c->source); dump_printf(EL_CONT,"\n\tSource ATM:\t"); dump_atmtext(c->source_addr); dump_printf(EL_CONT,"\n"); break; } } void disp_sockaddr(struct sockaddr_atmsvc *addr, struct atm_blli *blli) { int i; dump_printf(EL_DEBUG,"Socket_address"); dump_printf(EL_CONT, "Sas_family:%d\n\tAddress:",addr->sas_family); for(i=0;i<20;i++) { dump_printf(EL_CONT,"%2.2x ",addr->sas_addr.prv[i]); } dump_printf(EL_CONT,"\nBlli:\n\t"); dump_printf(EL_CONT,"l2_proto:%d\n\t",blli->l2_proto); dump_printf(EL_CONT,"l3_proto:%d\n\t\t",blli->l3_proto); dump_printf(EL_CONT,"ipi:%x\tsnap:",blli->l3.tr9577.ipi); for(i=0;i<5;i++) { dump_printf(EL_CONT,"%2.2x ",blli->l3.tr9577.snap[i]); } dump_printf(EL_CONT,"\n"); }