-
Notifications
You must be signed in to change notification settings - Fork 274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for LINUX_SLL2 #728
Merged
fklassen
merged 1 commit into
appneta:Feature_#727_linuxsll2
from
btriller:add-linuxsll2-plugin
Sep 3, 2023
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# $Id:$ | ||
# START OF: dlt_linuxsll2 | ||
# Note, if you add any files to your plugin, you will need to edit dlt_<plugin>/Makefile.am | ||
# add your .c files to libtcpedit_a_SOURCES | ||
# add your .h files to noinst_HEADERS | ||
# add any other files (like documentation, notes, etc) to EXTRA_DIST | ||
# add your dependency information (see comment below) | ||
|
||
libtcpedit_a_SOURCES += %reldir%/linuxsll2.c | ||
|
||
noinst_HEADERS += \ | ||
%reldir%/linuxsll2.h \ | ||
%reldir%/linuxsll2_types.h | ||
|
||
EXTRA_DIST += %reldir%/linuxsll2_opts.def | ||
|
||
# dependencies for your plugin source code. Edit as necessary | ||
linuxsll2.c: \ | ||
$(TCPEDIT_PLUGINS_DEPS) \ | ||
%reldir%/../../tcpedit_api.h \ | ||
%reldir%/linuxsll2.h \ | ||
%reldir%/linuxsll2_types.h | ||
|
||
# You probably don't want to touch anything below this line until the end of the plugin | ||
|
||
DLT_STUB_DEPS += %reldir%/linuxsll2_opts.def | ||
|
||
MOSTLYCLEANFILES += *~ | ||
|
||
# END OF: dlt_linuxsll2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,323 @@ | ||
/* $Id$ */ | ||
|
||
/* | ||
* Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net> | ||
* Copyright (c) 2013-2023 Fred Klassen <tcpreplay at appneta dot com> - AppNeta | ||
* | ||
* The Tcpreplay Suite of tools is free software: you can redistribute it | ||
* and/or modify it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or with the authors permission any later version. | ||
* | ||
* The Tcpreplay Suite is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "tcpedit.h" | ||
#include "common.h" | ||
#include "tcpr.h" | ||
#include "dlt_utils.h" | ||
#include "tcpedit_stub.h" | ||
#include "../ethernet.h" | ||
#include "linuxsll2.h" | ||
|
||
|
||
static char dlt_name[] = "linuxsll2"; | ||
static char _U_ dlt_prefix[] = "linuxsll2"; | ||
static uint16_t dlt_value = DLT_LINUX_SLL2; | ||
|
||
/* | ||
* Function to register ourselves. This function is always called, regardless | ||
* of what DLT types are being used, so it shouldn't be allocating extra buffers | ||
* or anything like that (use the dlt_linuxsll2_init() function below for that). | ||
* Tasks: | ||
* - Create a new plugin struct | ||
* - Fill out the provides/requires bit masks. Note: Only specify which fields are | ||
* actually in the header. | ||
* - Add the plugin to the context's plugin chain | ||
* Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN | ||
*/ | ||
int | ||
dlt_linuxsll2_register(tcpeditdlt_t *ctx) | ||
{ | ||
tcpeditdlt_plugin_t *plugin; | ||
assert(ctx); | ||
|
||
/* create a new plugin structure */ | ||
plugin = tcpedit_dlt_newplugin(); | ||
|
||
/* FIXME: set what we provide & require */ | ||
plugin->provides += PLUGIN_MASK_PROTO + PLUGIN_MASK_SRCADDR; | ||
plugin->requires += 0; | ||
|
||
|
||
/* what is our DLT value? */ | ||
plugin->dlt = dlt_value; | ||
|
||
/* set the prefix name of our plugin. This is also used as the prefix for our options */ | ||
plugin->name = safe_strdup(dlt_prefix); | ||
|
||
/* | ||
* Point to our functions, note, you need a function for EVERY method. | ||
* Even if it is only an empty stub returning success. | ||
*/ | ||
plugin->plugin_init = dlt_linuxsll2_init; | ||
plugin->plugin_cleanup = dlt_linuxsll2_cleanup; | ||
plugin->plugin_parse_opts = dlt_linuxsll2_parse_opts; | ||
plugin->plugin_decode = dlt_linuxsll2_decode; | ||
plugin->plugin_encode = dlt_linuxsll2_encode; | ||
plugin->plugin_proto = dlt_linuxsll2_proto; | ||
plugin->plugin_l2addr_type = dlt_linuxsll2_l2addr_type; | ||
plugin->plugin_l2len = dlt_linuxsll2_l2len; | ||
plugin->plugin_get_layer3 = dlt_linuxsll2_get_layer3; | ||
plugin->plugin_merge_layer3 = dlt_linuxsll2_merge_layer3; | ||
plugin->plugin_get_mac = dlt_linuxsll2_get_mac; | ||
|
||
/* add it to the available plugin list */ | ||
return tcpedit_dlt_addplugin(ctx, plugin); | ||
} | ||
|
||
|
||
/* | ||
* 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_linuxsll2_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(linuxsll2_extra_t); | ||
ctx->decoded_extra = safe_malloc(ctx->decoded_extra_size); | ||
|
||
/* allocate memory for our config data */ | ||
plugin->config_size = sizeof(linuxsll2_config_t); | ||
plugin->config = safe_malloc(plugin->config_size); | ||
|
||
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_linuxsll2_init(), this is just an stub. | ||
* Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN | ||
*/ | ||
int | ||
dlt_linuxsll2_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; | ||
ctx->decoded_extra_size = 0; | ||
} | ||
|
||
if (plugin->config != NULL) { | ||
safe_free(plugin->config); | ||
plugin->config = NULL; | ||
plugin->config_size = 0; | ||
} | ||
|
||
return TCPEDIT_OK; /* success */ | ||
} | ||
|
||
/* | ||
* 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_linuxsll2_parse_opts(tcpeditdlt_t *ctx) | ||
{ | ||
assert(ctx); | ||
|
||
/* nothing to parse */ | ||
return TCPEDIT_OK; /* success */ | ||
} | ||
|
||
/* | ||
* Function to decode the layer 2 header in the packet. | ||
* You need to fill out: | ||
* - ctx->l2len | ||
* - ctx->srcaddr | ||
* - ctx->dstaddr | ||
* - ctx->proto | ||
* - ctx->decoded_extra | ||
* Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN | ||
*/ | ||
int | ||
dlt_linuxsll2_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) | ||
{ | ||
int type; | ||
linux_sll2_header_t *linux_sll2; | ||
assert(ctx); | ||
assert(packet); | ||
|
||
if (pktlen < (int)sizeof(linux_sll2_header_t)) | ||
return TCPEDIT_ERROR; | ||
|
||
linux_sll2 = (linux_sll2_header_t *)packet; | ||
ctx->proto = linux_sll2->proto; | ||
ctx->l2len = sizeof(linux_sll2_header_t); | ||
|
||
|
||
type = ntohs(linux_sll2->type); | ||
if (type == ARPHRD_ETHER || type == ARPHRD_LOOPBACK) { /* ethernet or loopback */ | ||
memcpy(&(ctx->srcaddr), linux_sll2->address, ETHER_ADDR_LEN); | ||
} else { | ||
tcpedit_seterr(ctx->tcpedit, "%s", "DLT_LINUX_SLL2 pcap's must contain only ethernet or loopback packets"); | ||
return TCPEDIT_ERROR; | ||
} | ||
|
||
return TCPEDIT_OK; /* success */ | ||
} | ||
|
||
/* | ||
* Function to encode the layer 2 header back into the packet. | ||
* Returns: total packet len or TCPEDIT_ERROR | ||
*/ | ||
int | ||
dlt_linuxsll2_encode(tcpeditdlt_t *ctx, u_char *packet, _U_ int pktlen, | ||
_U_ tcpr_dir_t dir) | ||
{ | ||
assert(ctx); | ||
assert(packet); | ||
|
||
tcpedit_seterr(ctx->tcpedit, "%s", "DLT_LINUX_SLL2 plugin does not support packet encoding"); | ||
return TCPEDIT_ERROR; | ||
} | ||
|
||
/* | ||
* Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error | ||
*/ | ||
int | ||
dlt_linuxsll2_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) | ||
{ | ||
linux_sll2_header_t *linux_sll2; | ||
assert(ctx); | ||
assert(packet); | ||
|
||
if (pktlen < (int)sizeof(linux_sll2_header_t)) | ||
return TCPEDIT_ERROR; | ||
|
||
linux_sll2 = (linux_sll2_header_t *)packet; | ||
|
||
return linux_sll2->proto; | ||
} | ||
|
||
/* | ||
* Function returns a pointer to the layer 3 protocol header or NULL on error | ||
*/ | ||
u_char * | ||
dlt_linuxsll2_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen) | ||
{ | ||
int l2len; | ||
assert(ctx); | ||
assert(packet); | ||
|
||
l2len = dlt_linuxsll2_l2len(ctx, packet, pktlen); | ||
if (l2len == -1 || pktlen < l2len) | ||
return NULL; | ||
|
||
return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len); | ||
} | ||
|
||
/* | ||
* function merges the packet (containing L2 and old L3) with the l3data buffer | ||
* containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the | ||
* same buffer, otherwise there was a memcpy involved on strictly aligned architectures | ||
* like SPARC | ||
*/ | ||
u_char * | ||
dlt_linuxsll2_merge_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen, u_char *l3data) | ||
{ | ||
int l2len; | ||
assert(ctx); | ||
assert(packet); | ||
assert(l3data); | ||
|
||
l2len = dlt_linuxsll2_l2len(ctx, packet, pktlen); | ||
if (l2len == -1 || pktlen < l2len) | ||
return NULL; | ||
|
||
return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, l3data, l2len); | ||
} | ||
|
||
/* | ||
* return the length of the L2 header of the current packet | ||
*/ | ||
int | ||
dlt_linuxsll2_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) | ||
{ | ||
assert(ctx); | ||
assert(packet); | ||
|
||
if (pktlen < (int)sizeof(linux_sll2_header_t)) | ||
return -1; | ||
|
||
return sizeof(linux_sll2_header_t); | ||
} | ||
|
||
/* | ||
* return a static pointer to the source/destination MAC address | ||
* return NULL on error/address doesn't exist | ||
*/ | ||
u_char * | ||
dlt_linuxsll2_get_mac(tcpeditdlt_t *ctx, tcpeditdlt_mac_type_t mac, const u_char *packet, const int pktlen) | ||
{ | ||
assert(ctx); | ||
assert(packet); | ||
|
||
if (pktlen < 14) | ||
return NULL; | ||
|
||
/* FIXME: return a ptr to the source or dest mac address. */ | ||
switch(mac) { | ||
case SRC_MAC: | ||
memcpy(ctx->srcmac, &packet[6], 8); /* linuxssl defines the src mac field to be 8 bytes, not 6 */ | ||
return(ctx->srcmac); | ||
break; | ||
|
||
case DST_MAC: | ||
return(NULL); | ||
break; | ||
|
||
default: | ||
errx(-1, "Invalid tcpeditdlt_mac_type_t: %d", mac); | ||
} | ||
return(NULL); | ||
} | ||
|
||
tcpeditdlt_l2addr_type_t | ||
dlt_linuxsll2_l2addr_type(void) | ||
{ | ||
/* we only support ethernet packets */ | ||
return ETHERNET; | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need copyright stuff here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left out this one, since there's no
Makefile.am
to copy+paste Copyright stuff from.