/*
Copyright (C) 2000 - 2004 Christian Kreibich <christian@whoop.org>.
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 <config.h>
#endif
#include <nd.h>
#include <nd_dialog.h>
#include <nd_protocol.h>
#include <nd_protocol_inst.h>
#include <nd_gui.h>
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);
}
syntax highlighted by Code2HTML, v. 0.9.1