/* Copyright (C) 2000 - 2004 Christian Kreibich . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include ND_Protocol * nd_proto_new(LND_Protocol *proto) { ND_Protocol *proto_gui; if (!proto) return NULL; proto_gui = g_new0(ND_Protocol, 1); if (! proto_gui) return NULL; libnd_reg_set_data(proto->registry, "proto_gui", proto_gui); return proto_gui; } void nd_proto_free(LND_Protocol *proto) { ND_Protocol *proto_gui; if (!proto) return; if ( (proto_gui = libnd_reg_del_data(proto->registry, "proto_gui"))) g_free(proto_gui); /* FIXME -- is this properly cleaned up? */ libnd_proto_free(proto); } ND_Protocol * nd_proto_get(const LND_Protocol *proto) { ND_Protocol *proto_gui; if (!proto) return NULL; proto_gui = libnd_reg_get_data(proto->registry, "proto_gui"); D_ASSERT_PTR(proto_gui); return proto_gui; } ND_ProtoField * nd_proto_field_duplicate(ND_ProtoField *field) { ND_ProtoField *result; result = g_new(ND_ProtoField, 1); if (!result) return NULL; memcpy(result, field, sizeof(ND_ProtoField)); return result; } void nd_proto_field_free(ND_ProtoField *field) { g_free(field); } void nd_proto_field_set(const LND_ProtoInfo *pinf, ND_ProtoField *field, void *data) { GtkWidget *button; char s[MAXPATHLEN]; if (!pinf || !field) return; button = libnd_reg_get_data(pinf->registry, nd_proto_field_to_string(field)); D_ASSERT_PTR(button); switch (field->type) { case ND_VAL_FIELD: g_snprintf(s, MAXPATHLEN, field->label, data); gtk_label_set_text(GTK_LABEL(GTK_BIN(button)->child), s); break; case ND_FLG_FIELD: if (GPOINTER_TO_INT(data)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); break; default: D(("Warning -- invalid type in header field!")); } } void nd_proto_field_set_for_menu(const LND_ProtoInfo *pinf, ND_ProtoField *field, void *data, ND_MenuData *menu, char *alt_form_str) { GtkWidget *button; char s[MAXPATHLEN]; char s2[MAXPATHLEN]; int i; gboolean found_value = FALSE; if (!pinf || !field || !menu || !alt_form_str) return; if (field->type != ND_VAL_FIELD) { nd_proto_field_set(pinf, field, data); return; } for (i = 0; menu[i].label; i++) { if (GPOINTER_TO_INT(data) == menu[i].value) { g_snprintf(s2, MAXPATHLEN, field->label, menu[i].label); found_value = TRUE; break; } } if (!found_value) { g_snprintf(s, MAXPATHLEN, alt_form_str, data); g_snprintf(s2, MAXPATHLEN, field->label, s); } button = libnd_reg_get_data(pinf->registry, nd_proto_field_to_string(field)); D_ASSERT_PTR(button); gtk_label_set_text(GTK_LABEL(GTK_BIN(button)->child), s2); } const char * nd_proto_field_to_string(const ND_ProtoField *field) { static char key[MAXPATHLEN]; g_snprintf(key, MAXPATHLEN, "field_%p", field); return key; } char * nd_proto_get_opt_key(LND_Protocol *proto) { static char key[MAXPATHLEN]; g_snprintf(key, MAXPATHLEN, "%s_opt_fields", proto->name); return key; } static void proto_4bit_lo_ok_cb(LND_Packet *packet, void *user_data, guint value) { guchar val8; guchar *data = (guchar*) user_data; val8 = (guchar) value; *data &= 0xF0; *data |= (val8 & 0x0F); libnd_packet_modified(packet); } void nd_proto_4bit_lo_cb(LND_Packet *packet, guchar *header, guchar *data) { nd_dialog_number(_("Enter 4-bit data:"), ND_BASE_DEC, (*data & 0x0F), 15, proto_4bit_lo_ok_cb, NULL, packet, data); return; TOUCH(header); } static void proto_4bit_hi_ok_cb(LND_Packet *packet, void *user_data, guint value) { guchar val8; guchar *data = (guchar*) user_data; val8 = (guchar) value; *data &= 0x0F; *data |= ((val8 & 0x0F) << 4); libnd_packet_modified(packet); } void nd_proto_4bit_hi_cb(LND_Packet *packet, guchar *header, guchar *data) { nd_dialog_number(_("Enter 4-bit data:"), ND_BASE_DEC, (*data & 0xF0), 15, proto_4bit_hi_ok_cb, NULL, packet, data); return; TOUCH(header); } static void proto_8bit_ok_cb(LND_Packet *packet, void *user_data, guint value) { guchar *data = (guchar*) user_data; *data = (guchar) value; libnd_packet_modified(packet); } void nd_proto_8bit_cb(LND_Packet *packet, guchar *header, guchar *data) { nd_dialog_number(_("Enter 8-bit data:"), ND_BASE_DEC, *data, 255, proto_8bit_ok_cb, NULL, packet, data); return; TOUCH(header); } static void proto_16bit_ok_cb(LND_Packet *packet, void *user_data, guint value) { guint16 *data = (guint16*) user_data; *data = htons((guint16) value); libnd_packet_modified(packet); } void nd_proto_16bit_cb(LND_Packet *packet, guchar *header, guchar *data) { guint16 *data16 = (guint16 *) data; nd_dialog_number(_("Enter 16-bit data:"), ND_BASE_HEX, ntohs(*data16), 65535, proto_16bit_ok_cb, NULL, packet, data); return; TOUCH(header); } static void proto_24bit_ok_cb(LND_Packet *packet, void *user_data, guint value) { guchar *val_p = (guchar *) &value; guchar *data = (guchar *) user_data; #ifdef WORDS_BIGENDIAN data[0] = val_p[0]; data[1] = val_p[1]; data[2] = val_p[2]; #else data[0] = val_p[2]; data[1] = val_p[1]; data[2] = val_p[0]; #endif libnd_packet_modified(packet); } void nd_proto_24bit_cb(LND_Packet *packet, guchar *header, guchar *data) { guint val = 0; #ifdef WORDS_BIGENDIAN val = (data[2] << 16 | data[1] << 8 | data[0]); #else val = (data[0] << 16 | data[1] << 8 | data[2]); #endif nd_dialog_number(_("Enter 32-bit timestamp:"), ND_BASE_HEX, val, (1 << 23) - 1, proto_24bit_ok_cb, NULL, packet, data); return; TOUCH(header); } static void proto_32bit_ok_cb(LND_Packet *packet, void *user_data, guint value) { guint32 *data = (guint32 *) user_data; *data = htonl((guint32) value); libnd_packet_modified(packet); } void nd_proto_32bit_cb(LND_Packet *packet, guchar *header, guchar *data) { guint32 *data32 = (guint32 *) data; nd_dialog_number(_("Enter 32-bit data:"), ND_BASE_DEC, ntohl(*data32), (guint) -1, proto_32bit_ok_cb, NULL, packet, data); return; TOUCH(header); } ND_ProtoCallbackData * nd_proto_cb_data_new(LND_Protocol *proto, guchar *data, guint offset, gboolean update_packet) { ND_ProtoCallbackData *cb_data; if (!proto) return NULL; cb_data = g_new0(ND_ProtoCallbackData, 1); D_ASSERT_PTR(cb_data); if (!cb_data) return NULL; cb_data->proto = proto; cb_data->data = data; cb_data->offset = offset; cb_data->update_packet = update_packet; return cb_data; } void nd_proto_cb_data_free(ND_ProtoCallbackData *cb_data) { g_free(cb_data); } static void proto_iterate_impl(LND_Packet *packet, void *user_data, guint value, ND_ProtoCallbackMode mode) { LND_Trace *trace; LND_PacketIterator pit; ND_ProtoCallbackData *data = (ND_ProtoCallbackData *) user_data; int nesting; guchar *data_ptr; D_ENTER; if (!packet || !user_data || !data || !data->proto) D_RETURN; D(("Generic callback -- proto %s, offset %u, value %lu, updating: %i, mode %i\n", data->proto->name, data->offset, (long unsigned) value, data->update_packet, mode)); nesting = libnd_packet_get_proto_nesting(packet, data->proto, data->data); trace = libnd_packet_get_trace(packet); if (nesting < 0 || !trace) { D(("Invalid input -- aborting.\n")); D_RETURN; } for (libnd_pit_init(&pit, trace); libnd_pit_get(&pit); libnd_pit_next(&pit)) { if (! (data_ptr = libnd_packet_get_data(libnd_pit_get(&pit), data->proto, nesting))) continue; switch (mode) { case ND_PROT_CB_4LO: *(data_ptr + data->offset) &= 0xF0; *(data_ptr + data->offset) |= ((((guchar) value) & 0x0F)); break; case ND_PROT_CB_4HI: *(data_ptr + data->offset) &= 0x0F; *(data_ptr + data->offset) |= ((((guchar) value) & 0x0F) << 4); break; case ND_PROT_CB_8: *(data_ptr + data->offset) = (guchar) value; break; case ND_PROT_CB_16: *((guint16*) (data_ptr + data->offset)) = htons((guint16) value); break; case ND_PROT_CB_32: *((guint32*) (data_ptr + data->offset)) = htonl((guint32) value); break; default: D(("Invalid callback data type %i\n", data->mode)); } if (data->update_packet) libnd_packet_update(libnd_pit_get(&pit), data->proto, data->nesting); libnd_packet_modified(libnd_pit_get(&pit)); } nd_gui_list_update(trace); D_RETURN; TOUCH(value); } void nd_proto_iterate_4bit_lo_cb(LND_Packet *packet, void *user_data, guint value) { proto_iterate_impl(packet, user_data, value, ND_PROT_CB_4LO); } void nd_proto_iterate_4bit_hi_cb(LND_Packet *packet, void *user_data, guint value) { proto_iterate_impl(packet, user_data, value, ND_PROT_CB_4HI); } void nd_proto_iterate_8bit_cb(LND_Packet *packet, void *user_data, guint value) { proto_iterate_impl(packet, user_data, value, ND_PROT_CB_8); } void nd_proto_iterate_16bit_cb(LND_Packet *packet, void *user_data, guint value) { proto_iterate_impl(packet, user_data, value, ND_PROT_CB_16); } void nd_proto_iterate_32bit_cb(LND_Packet *packet, void *user_data, guint value) { proto_iterate_impl(packet, user_data, value, ND_PROT_CB_32); }