/* * Initializer function. This function is called only once, if and only iif * this plugin will be utilized. Remember, if you need to keep track of any state, * store it in your plugin->config, not a global! * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_hdlc_init(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; hdlc_config_t *config; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to initalize unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } /* allocate memory for our deocde extra data */ if (sizeof(hdlc_extra_t) > 0) ctx->decoded_extra = safe_malloc(sizeof(hdlc_extra_t)); /* allocate memory for our config data */ if (sizeof(hdlc_config_t) > 0) plugin->config = safe_malloc(sizeof(hdlc_config_t)); config = (hdlc_config_t *)plugin->config; /* default to unset */ config->address = 65535; config->control = 65535; return TCPEDIT_OK; /* success */ }
/* * Since this is used in a library, we should manually clean up after ourselves * Unless you allocated some memory in dlt_jnpr_ether_init(), this is just an stub. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_jnpr_ether_cleanup(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; jnpr_ether_config_t *config; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to cleanup unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } if (ctx->decoded_extra != NULL) { safe_free(ctx->decoded_extra); ctx->decoded_extra = NULL; } if (plugin->config != NULL) { /* clean up the en10mb plugin */ config = (jnpr_ether_config_t *)ctx->encoder->config; tcpedit_dlt_cleanup(config->subctx); plugin->config = NULL; } return TCPEDIT_OK; /* success */ }
/* * Initializer function. This function is called only once, if and only iif * this plugin will be utilized. Remember, if you need to keep track of any state, * store it in your plugin->config, not a global! * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_radiotap_init(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; radiotap_config_t *config; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to initalize unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } /* allocate memory for our deocde extra data */ if (sizeof(radiotap_extra_t) > 0) ctx->decoded_extra = safe_malloc(sizeof(radiotap_extra_t)); /* allocate memory for our config data */ if (sizeof(radiotap_config_t) > 0) plugin->config = safe_malloc(sizeof(radiotap_config_t)); config = (radiotap_config_t *)plugin->config; return TCPEDIT_OK; /* success */ }
/* * Since this is used in a library, we should manually clean up after ourselves * Unless you allocated some memory in dlt_null_init(), this is just an stub. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_null_cleanup(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to cleanup unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } if (ctx->decoded_extra != NULL) { safe_free(ctx->decoded_extra); ctx->decoded_extra = NULL; ctx->decoded_extra_size = 0; } if (plugin->config != NULL) { safe_free(plugin->config); plugin->config = NULL; plugin->config_size = 0; } return TCPEDIT_OK; /* success */ }
/** * Set output DLT plugin by using it's DLT_<type>. Note that the user plugin * is DLT_USER0. */ int tcpedit_set_encoder_dltplugin_byid(tcpedit_t *tcpedit, int dlt) { tcpeditdlt_plugin_t *plugin; tcpeditdlt_t *ctx; assert(tcpedit); ctx = tcpedit->dlt_ctx; assert(ctx); if (ctx->encoder) { tcpedit_seterr(tcpedit, "You have already selected a DLT encoder: %s", ctx->encoder->name); return TCPEDIT_ERROR; } plugin = tcpedit_dlt_getplugin(ctx, dlt); if (plugin == NULL) { tcpedit_seterr(tcpedit, "No output DLT plugin decoder with DLT type: 0x%04x", dlt); return TCPEDIT_ERROR; } ctx->encoder = plugin; /* init the encoder plugin if it's not the decoder plugin too */ if (ctx->encoder->dlt != ctx->decoder->dlt) { if (ctx->encoder->plugin_init(ctx) != TCPEDIT_OK) { /* plugin should generate the error */ return TCPEDIT_ERROR; } } return TCPEDIT_OK; }
/* * Function to encode the layer 2 header back into the packet. * Returns: total packet len or TCPEDIT_ERROR */ int dlt_hdlc_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, _U_ tcpr_dir_t dir) { cisco_hdlc_t *hdlc; hdlc_config_t *config = NULL; hdlc_extra_t *extra = NULL; tcpeditdlt_plugin_t *plugin = NULL; u_char tmpbuff[MAXPACKET]; int newpktlen; assert(ctx); assert(pktlen >= 4); assert(packet); /* Make room for our new l2 header if old l2len != 4 */ if (ctx->l2len > 4) { memmove(packet + 4, packet + ctx->l2len, pktlen - ctx->l2len); } else if (ctx->l2len < 4) { memcpy(tmpbuff, packet, pktlen); memcpy(packet + 4, (tmpbuff + ctx->l2len), pktlen - ctx->l2len); } /* update the total packet length */ newpktlen = pktlen + 4 - ctx->l2len; /* * HDLC doesn't support direction, since we have no real src/dst addresses * to deal with, so we just use the original packet data or option data */ hdlc = (cisco_hdlc_t *)packet; plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; extra = (hdlc_extra_t *)ctx->decoded_extra; /* set the address field */ if (config->address < 65535) { hdlc->address = (uint8_t)config->address; } else if (extra->hdlc) { hdlc->address = extra->hdlc; } else { tcpedit_seterr(ctx->tcpedit, "%s", "Non-HDLC packet requires --hdlc-address"); return TCPEDIT_ERROR; } /* set the control field */ if (config->control < 65535) { hdlc->control = (uint8_t)config->control; } else if (extra->hdlc) { hdlc->control = extra->hdlc; } else { tcpedit_seterr(ctx->tcpedit, "%s", "Non-HDLC packet requires --hdlc-control"); return TCPEDIT_ERROR; } /* copy over our protocol */ hdlc->protocol = ctx->proto; return newpktlen; /* success */ }
uint16_t dlt_user_get_output_dlt(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; user_config_t *config; assert(ctx); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; return config->dlt; }
/* * Initializer function. This function is called only once, if and only if * this plugin will be utilized. Remember, if you need to keep track of any state, * store it in your plugin->config, not a global! * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_loop_init(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to initalize unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } return TCPEDIT_OK; /* success */ }
/* * return the length of the L2 header of the current packet */ int dlt_user_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) { tcpeditdlt_plugin_t *plugin; user_config_t *config; assert(ctx); assert(packet); assert(pktlen); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; return config->length; }
/** * initialize our plugin library. Pass the DLT of the source pcap handle. * Actions: * - Create new tcpeditdlt_t context * - Link tcpedit to new context * - Register plugins * - Select decoder plugin using srcdlt * - Select encoder plugin using destination name * - Initialize decoder/encoder plugins * - Parse options for encoder plugin * - Validate provides/reqiures + user options */ tcpeditdlt_t * tcpedit_dlt_init(tcpedit_t *tcpedit, const int srcdlt) { tcpeditdlt_t *ctx; int rcode; assert(tcpedit); assert(srcdlt >= 0); ctx = (tcpeditdlt_t *)safe_malloc(sizeof(tcpeditdlt_t)); /* do we need a side buffer for L3 data? */ #ifdef FORCE_ALIGN ctx->l3buff = (u_char *)safe_malloc(MAXPACKET); #endif /* copy our tcpedit context */ ctx->tcpedit = tcpedit; /* register all our plugins */ if (tcpedit_dlt_register(ctx) != TCPEDIT_OK) { tcpedit_dlt_cleanup(ctx); return NULL; } /* Choose decode plugin */ if ((ctx->decoder = tcpedit_dlt_getplugin(ctx, srcdlt)) == NULL) { tcpedit_seterr(tcpedit, "No DLT plugin available for source DLT: 0x%x", srcdlt); tcpedit_dlt_cleanup(ctx); return NULL; } /* set our dlt type */ ctx->dlt = srcdlt; /* set our address type */ ctx->addr_type = ctx->decoder->plugin_l2addr_type(); /* initalize decoder plugin */ rcode = ctx->decoder->plugin_init(ctx); if (tcpedit_checkerror(ctx->tcpedit, rcode, NULL) != TCPEDIT_OK) { tcpedit_dlt_cleanup(ctx); return NULL; } /* we're OK */ return ctx; }
/** * Get the layer 2 length of the packet using the DLT plugin currently in * place */ int tcpedit_dlt_l2len(tcpeditdlt_t *ctx, int dlt, const u_char *packet, const int pktlen) { tcpeditdlt_plugin_t *plugin; assert(ctx); assert(dlt >= 0); assert(packet); assert(pktlen); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to find plugin for DLT 0x%04x", dlt); return -1; } return plugin->plugin_l2len(ctx, packet, pktlen); }
/* * This is where you should define all your AutoGen AutoOpts option parsing. * Any user specified option should have it's bit turned on in the 'provides' * bit mask. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_user_parse_opts(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; user_config_t *config; assert(ctx); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; /* * --user-dlt will override the output DLT type, otherwise we'll use * the DLT of the decoder */ if (HAVE_OPT(USER_DLT)) { config->dlt = OPT_VALUE_USER_DLT; } else { config->dlt = ctx->decoder->dlt; } /* --user-dlink */ if (HAVE_OPT(USER_DLINK)) { int ct = STACKCT_OPT(USER_DLINK); char **list = STACKLST_OPT(USER_DLINK); int first = 1; do { char *p = *list++; if (first) { config->length = read_hexstring(p, config->l2server, USER_L2MAXLEN); memcpy(config->l2client, config->l2server, config->length); } else { if (config->length != read_hexstring(p, config->l2client, USER_L2MAXLEN)) { tcpedit_seterr(ctx->tcpedit, "%s", "both --dlink's must contain the same number of bytes"); return TCPEDIT_ERROR; } } first = 0; } while (--ct > 0); } return TCPEDIT_OK; /* success */ }
/** * \brief Merge the Layer 3 data back onto the mainbuffer so it's immediately * after the layer 2 header * * Since some L2 headers aren't strictly aligned, we need to "merge" the packet w/ L2 data * and the L3 buffer. This is basically a NO-OP for things like vlan tagged ethernet (16 byte) header * or Cisco HDLC (4 byte header) but is critical for std ethernet (12 byte header) */ u_char * tcpedit_dlt_merge_l3data(tcpeditdlt_t *ctx, int dlt, u_char *packet, const int pktlen, u_char *l3data) { tcpeditdlt_plugin_t *plugin; assert(ctx); assert(dlt >= 0); assert(pktlen >= 0); assert(packet); if (l3data == NULL) return packet; if ((plugin = tcpedit_dlt_getplugin(ctx, dlt)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to find plugin for DLT 0x%04x", dlt); return NULL; } return plugin->plugin_merge_layer3(ctx, packet, pktlen, l3data); }
/* * This is where you should define all your AutoGen AutoOpts option parsing. * Any user specified option should have it's bit turned on in the 'provides' * bit mask. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_hdlc_parse_opts(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; hdlc_config_t *config; assert(ctx); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; if (HAVE_OPT(HDLC_CONTROL)) { config->control = (uint16_t)OPT_VALUE_HDLC_CONTROL; } if (HAVE_OPT(HDLC_ADDRESS)) { config->address = (uint16_t)OPT_VALUE_HDLC_ADDRESS; } return TCPEDIT_OK; /* success */ }
/* * Initializer function. This function is called only once, if and only if * this plugin will be utilized. Remember, if you need to keep track of any state, * store it in your plugin->config, not a global! * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_linuxsll_init(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to initialize unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } /* allocate memory for our decode extra data */ ctx->decoded_extra_size = sizeof(linuxsll_extra_t); ctx->decoded_extra = safe_malloc(ctx->decoded_extra_size); /* allocate memory for our config data */ plugin->config_size = sizeof(linuxsll_config_t); plugin->config = safe_malloc(plugin->config_size); return TCPEDIT_OK; /* success */ }
/* * Initializer function. This function is called only once, if and only iif * this plugin will be utilized. Remember, if you need to keep track of any state, * store it in your plugin->config, not a global! * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_ieee80211_init(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to initalize unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } /* allocate memory for our deocde extra data */ if (sizeof(ieee80211_extra_t) > 0) ctx->decoded_extra = safe_malloc(sizeof(ieee80211_extra_t)); /* allocate memory for our config data */ if (sizeof(ieee80211_config_t) > 0) plugin->config = safe_malloc(sizeof(ieee80211_config_t)); /* FIXME: set default config values here */ return TCPEDIT_OK; /* success */ }
/* * Function to encode the layer 2 header back into the packet. * Returns: total packet len or TCPEDIT_ERROR */ int dlt_user_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, tcpr_dir_t dir) { user_config_t *config; tcpeditdlt_plugin_t *plugin; u_char tmpbuff[MAXPACKET]; assert(ctx); assert(pktlen > 0); assert(packet); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; /* Make room for our new l2 header if l2len != config->length */ if (ctx->l2len > config->length) { memmove(packet + config->length, packet + ctx->l2len, pktlen - ctx->l2len); } else if (ctx->l2len < config->length) { memcpy(tmpbuff, packet, pktlen); memcpy(packet + config->length, (tmpbuff + ctx->l2len), pktlen - ctx->l2len); } /* update the total packet length */ pktlen += config->length - ctx->l2len; if (dir == TCPR_DIR_C2S) { memcpy(packet, config->l2client, config->length); } else if (dir == TCPR_DIR_S2C) { memcpy(packet, config->l2server, config->length); } else { tcpedit_seterr(ctx->tcpedit, "%s", "Encoders only support C2S or C2S!"); return TCPEDIT_ERROR; } return pktlen; /* success */ }
/* * Since this is used in a library, we should manually clean up after ourselves * Unless you allocated some memory in dlt_user_init(), this is just an stub. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_user_cleanup(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; assert(ctx); if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) { tcpedit_seterr(ctx->tcpedit, "Unable to cleanup unregistered plugin %s", dlt_name); return TCPEDIT_ERROR; } /* FIXME: make this function do something if necessary */ if (ctx->decoded_extra != NULL) { safe_free(ctx->decoded_extra); ctx->decoded_extra = NULL; } if (plugin->config != NULL) { safe_free(plugin->config); plugin->config = NULL; } return TCPEDIT_OK; /* success */ }