Packet Location Interface
This commit is contained in:
parent
d378220c96
commit
db5bd57899
13 changed files with 475 additions and 5 deletions
|
@ -6,6 +6,9 @@ SUBDIRS = include lib src doc
|
|||
|
||||
pkgconfig_DATA = libnl-2.0.pc
|
||||
|
||||
sysconfdir = @sysconfdir@/libnl
|
||||
sysconf_DATA = etc/pktloc
|
||||
|
||||
.PHONY: cscope
|
||||
cscope:
|
||||
cscope -b -q -R -Iinclude -slib -ssrc;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# License as published by the Free Software Foundation version 2.1
|
||||
# of the License.
|
||||
#
|
||||
# Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
# Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
|
||||
#
|
||||
|
||||
AC_INIT(libnl, 2.0, tgraf@suug.ch)
|
||||
|
@ -18,6 +18,8 @@ AC_PROG_CC
|
|||
AM_PROG_CC_C_O
|
||||
AC_PROG_INSTALL
|
||||
AM_PROG_LIBTOOL
|
||||
AM_PROG_LEX
|
||||
AC_PROG_YACC
|
||||
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
|
|
44
etc/pktloc
Normal file
44
etc/pktloc
Normal file
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# Location definitions for packet matching
|
||||
#
|
||||
|
||||
# name alignment offset mask
|
||||
ip.version u8 net+0 0xF0
|
||||
ip.hdrlen u8 net+0 0x0F
|
||||
ip.diffserv u8 net+1
|
||||
ip.length u16 net+2
|
||||
ip.id u16 net+4
|
||||
ip.df u8 net+6 0x40
|
||||
ip.mf u8 net+6 0x20
|
||||
ip.offset u16 net+6 0x1FFF
|
||||
ip.ttl u8 net+8
|
||||
ip.proto u8 net+9
|
||||
ip.chksum u16 net+10
|
||||
ip.src u32 net+12
|
||||
ip.dst u32 net+16
|
||||
|
||||
|
||||
#
|
||||
# Transmission Control Protocol (TCP)
|
||||
#
|
||||
# name alignment offset mask
|
||||
tcp.sport u16 tcp+0
|
||||
tcp.dport u16 tcp+2
|
||||
tcp.seq u32 tcp+4
|
||||
tcp.ack u32 tcp+8
|
||||
tcp.off u8 tcp+12 0xF0
|
||||
tcp.reserved u8 tcp+12 0x0F
|
||||
# FLAGS
|
||||
tcp.win u16 tcp+14
|
||||
tcp.csum u16 tcp+16
|
||||
tcp.urg u16 tcp+18
|
||||
tcp.opts u32 tcp+20
|
||||
|
||||
#
|
||||
# User Datagram Protocol (UDP)
|
||||
#
|
||||
# name alignment offset mask
|
||||
udp.sport u16 tcp+0
|
||||
udp.dport u16 tcp+2
|
||||
udp.length u16 tcp+4
|
||||
udp.csum u16 tcp+6
|
|
@ -23,6 +23,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -45,8 +45,9 @@ extern "C" {
|
|||
#define NLE_PROTO_MISMATCH 26
|
||||
#define NLE_NOACCESS 27
|
||||
#define NLE_PERM 28
|
||||
#define NLE_PKTLOC_FILE 29
|
||||
|
||||
#define NLE_MAX NLE_PERM
|
||||
#define NLE_MAX NLE_PKTLOC_FILE
|
||||
|
||||
extern const char * nl_geterror(int);
|
||||
extern void nl_perror(int, const char *);
|
||||
|
|
44
include/netlink/route/pktloc.h
Normal file
44
include/netlink/route/pktloc.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* netlink/route/pktloc.h Packet Location Aliasing
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_PKTLOC_H_
|
||||
#define NETLINK_PKTLOC_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
||||
#include <linux/tc_ematch/tc_em_cmp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct rtnl_pktloc
|
||||
{
|
||||
char * name;
|
||||
uint8_t align:4;
|
||||
uint8_t layer:4;
|
||||
uint8_t flags;
|
||||
uint16_t offset;
|
||||
uint32_t mask;
|
||||
|
||||
struct nl_list_head list;
|
||||
};
|
||||
|
||||
extern int rtnl_pktloc_lookup(const char *, struct rtnl_pktloc **);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
# -*- Makefile -*-
|
||||
|
||||
AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE
|
||||
AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\"
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libnl.la libnl-genl.la libnl-route.la libnl-nf.la
|
||||
|
@ -23,6 +23,19 @@ libnl_nf_la_SOURCES = \
|
|||
netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \
|
||||
netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c
|
||||
|
||||
BUILT_SOURCES = route/pktloc_syntax.h
|
||||
CLEANFILES = \
|
||||
route/pktloc_grammar.c route/pktloc_grammar.h \
|
||||
route/pktloc_syntax.c route/pktloc_syntax.h
|
||||
|
||||
# Hack to avoid using ylwrap. It does not function correctly in combination
|
||||
# with --header-file=
|
||||
route/pktloc_grammar.c: route/pktloc_grammar.l
|
||||
$(LEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^
|
||||
|
||||
route/pktloc_syntax.c: route/pktloc_syntax.y
|
||||
$(YACC) -d $(YFLAGS) -o $@ $^
|
||||
|
||||
libnl_route_la_LDFLAGS = -version-info 2:0:0
|
||||
libnl_route_la_LIBADD = libnl.la
|
||||
libnl_route_la_SOURCES = \
|
||||
|
@ -40,4 +53,6 @@ libnl_route_la_SOURCES = \
|
|||
route/sch/fifo.c route/sch/htb.c route/sch/netem.c route/sch/prio.c \
|
||||
route/sch/red.c route/sch/sfq.c route/sch/tbf.c \
|
||||
\
|
||||
fib_lookup/lookup.c fib_lookup/request.c
|
||||
fib_lookup/lookup.c fib_lookup/request.c \
|
||||
\
|
||||
route/pktloc_syntax.c route/pktloc_grammar.c route/pktloc.c
|
||||
|
|
|
@ -42,6 +42,7 @@ static const char *errmsg[NLE_MAX+1] = {
|
|||
[NLE_PROTO_MISMATCH] = "Protocol mismatch",
|
||||
[NLE_NOACCESS] = "No Access",
|
||||
[NLE_PERM] = "Operation not permitted",
|
||||
[NLE_PKTLOC_FILE] = "Unable to open packet location file",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
168
lib/route/pktloc.c
Normal file
168
lib/route/pktloc.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* lib/route/pktloc.c Packet Location Aliasing
|
||||
*
|
||||
* This library 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 version 2 of the License.
|
||||
*
|
||||
* Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tc
|
||||
* @defgroup pktloc Packet Location Aliasing
|
||||
* Packet Location Aliasing
|
||||
*
|
||||
* The packet location aliasing interface eases the use of offset definitions
|
||||
* inside packets by allowing them to be referenced by name. Known positions
|
||||
* of protocol fields are stored in a configuration file and associated with
|
||||
* a name for later reference. The configuration file is distributed with the
|
||||
* library and provides a well defined set of definitions for most common
|
||||
* protocol fields.
|
||||
*
|
||||
* @subsection pktloc_examples Examples
|
||||
* @par Example 1.1 Looking up a packet location
|
||||
* @code
|
||||
* struct rtnl_pktloc *loc;
|
||||
*
|
||||
* rtnl_pktloc_lookup("ip.src", &loc);
|
||||
* @endcode
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/pktloc.h>
|
||||
|
||||
#include "pktloc_syntax.h"
|
||||
#include "pktloc_grammar.h"
|
||||
|
||||
/** @cond */
|
||||
#define PKTLOC_NAME_HT_SIZ 256
|
||||
|
||||
static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ];
|
||||
|
||||
/* djb2 */
|
||||
unsigned int pktloc_hash(const char *str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
|
||||
while ((c = *str++))
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
|
||||
return hash % PKTLOC_NAME_HT_SIZ;
|
||||
}
|
||||
|
||||
|
||||
void rtnl_pktloc_add(struct rtnl_pktloc *loc)
|
||||
{
|
||||
nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]);
|
||||
}
|
||||
|
||||
extern int pktloc_parse(void *scanner);
|
||||
|
||||
/** @endcond */
|
||||
|
||||
static void rtnl_pktloc_free(struct rtnl_pktloc *loc)
|
||||
{
|
||||
if (!loc)
|
||||
return;
|
||||
|
||||
free(loc->name);
|
||||
free(loc);
|
||||
}
|
||||
|
||||
static int read_pktlocs(void)
|
||||
{
|
||||
YY_BUFFER_STATE buf;
|
||||
yyscan_t scanner = NULL;
|
||||
static time_t last_read;
|
||||
struct stat st = {0};
|
||||
char *path;
|
||||
int i, err;
|
||||
FILE *fd;
|
||||
|
||||
asprintf(&path, "%s/pktloc", SYSCONFDIR);
|
||||
|
||||
/* if stat fails, just try to read the file */
|
||||
if (stat(path, &st) == 0) {
|
||||
/* Don't re-read file if file is unchanged */
|
||||
if (last_read == st.st_mtime)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fd = fopen(path, "r")))
|
||||
return -NLE_PKTLOC_FILE;
|
||||
|
||||
for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) {
|
||||
struct rtnl_pktloc *loc, *n;
|
||||
|
||||
nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list)
|
||||
rtnl_pktloc_free(loc);
|
||||
|
||||
nl_init_list_head(&pktloc_name_ht[i]);
|
||||
}
|
||||
|
||||
if ((err = pktloc_lex_init(&scanner)) < 0)
|
||||
return -NLE_FAILURE;
|
||||
|
||||
buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner);
|
||||
pktloc__switch_to_buffer(buf, scanner);
|
||||
|
||||
if ((err = pktloc_parse(scanner)) < 0)
|
||||
return -NLE_FAILURE;
|
||||
|
||||
if (scanner)
|
||||
pktloc_lex_destroy(scanner);
|
||||
|
||||
free(path);
|
||||
last_read = st.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup packet location alias
|
||||
* @arg name Name of packet location.
|
||||
*
|
||||
* Tries to find a matching packet location alias for the supplied
|
||||
* packet location name.
|
||||
*
|
||||
* The file containing the packet location definitions is automatically
|
||||
* re-read if its modification time has changed since the last call.
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
* @retval NLE_PKTLOC_FILE Unable to open packet location file.
|
||||
* @retval NLE_OBJ_NOTFOUND No matching packet location alias found.
|
||||
*/
|
||||
int rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result)
|
||||
{
|
||||
struct rtnl_pktloc *loc;
|
||||
int hash, err;
|
||||
|
||||
if ((err = read_pktlocs()) < 0)
|
||||
return err;
|
||||
|
||||
hash = pktloc_hash(name);
|
||||
nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) {
|
||||
if (!strcasecmp(loc->name, name)) {
|
||||
*result = loc;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -NLE_OBJ_NOTFOUND;
|
||||
}
|
||||
|
||||
static int __init pktloc_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++)
|
||||
nl_init_list_head(&pktloc_name_ht[i]);
|
||||
|
||||
return 0;
|
||||
}
|
42
lib/route/pktloc_grammar.l
Normal file
42
lib/route/pktloc_grammar.l
Normal file
|
@ -0,0 +1,42 @@
|
|||
%{
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/pktloc.h>
|
||||
#include "pktloc_syntax.h"
|
||||
%}
|
||||
|
||||
%option 8bit
|
||||
%option reentrant
|
||||
%option warn
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option bison-bridge
|
||||
%option bison-locations
|
||||
%option prefix="pktloc_"
|
||||
|
||||
%%
|
||||
|
||||
[ \t\r\n]+
|
||||
|
||||
"#".*
|
||||
|
||||
[[:digit:]]+ |
|
||||
0[xX][[:xdigit:]]+ {
|
||||
yylval->i = strtoul(yytext, NULL, 0);
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
"+" { return yylval->i = yytext[0]; }
|
||||
|
||||
[lL][iI][nN][kK] { yylval->i = TCF_LAYER_LINK; return LAYER; }
|
||||
[nN][eE][tT] { yylval->i = TCF_LAYER_NETWORK; return LAYER; }
|
||||
[tT][cC][pP] { yylval->i = TCF_LAYER_TRANSPORT; return LAYER; }
|
||||
|
||||
[^ \t\r\n+]+ {
|
||||
yylval->s = strdup(yytext);
|
||||
if (yylval->s == NULL)
|
||||
return ERROR;
|
||||
return NAME;
|
||||
}
|
108
lib/route/pktloc_syntax.y
Normal file
108
lib/route/pktloc_syntax.y
Normal file
|
@ -0,0 +1,108 @@
|
|||
%{
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/pktloc.h>
|
||||
%}
|
||||
|
||||
%locations
|
||||
%error-verbose
|
||||
%define api.pure
|
||||
%name-prefix "pktloc_"
|
||||
|
||||
%parse-param {void *scanner}
|
||||
%lex-param {void *scanner}
|
||||
|
||||
%union {
|
||||
struct rtnl_pktloc *l;
|
||||
uint32_t i;
|
||||
char *s;
|
||||
}
|
||||
|
||||
%{
|
||||
extern int pktloc_lex(YYSTYPE *, YYLTYPE *, void *);
|
||||
extern void rtnl_pktloc_add(struct rtnl_pktloc *);
|
||||
|
||||
static void yyerror(YYLTYPE *locp, void *scanner, const char *msg)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
%}
|
||||
|
||||
%token <i> ERROR NUMBER LAYER
|
||||
%token <s> NAME
|
||||
|
||||
%type <i> mask layer
|
||||
%type <l> location
|
||||
|
||||
%destructor { free($$); } NAME
|
||||
|
||||
%start input
|
||||
|
||||
%%
|
||||
|
||||
input:
|
||||
def
|
||||
{ }
|
||||
;
|
||||
|
||||
def:
|
||||
/* empty */
|
||||
{ }
|
||||
| location def
|
||||
{ }
|
||||
;
|
||||
|
||||
location:
|
||||
NAME NAME layer NUMBER mask
|
||||
{
|
||||
struct rtnl_pktloc *loc;
|
||||
|
||||
if (!(loc = calloc(1, sizeof(*loc)))) {
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
if (!strcasecmp($2, "u8"))
|
||||
loc->align = TCF_EM_ALIGN_U8;
|
||||
else if (!strcasecmp($2, "h8")) {
|
||||
loc->align = TCF_EM_ALIGN_U8;
|
||||
loc->flags = TCF_EM_CMP_TRANS;
|
||||
} else if (!strcasecmp($2, "u16"))
|
||||
loc->align = TCF_EM_ALIGN_U16;
|
||||
else if (!strcasecmp($2, "h16")) {
|
||||
loc->align = TCF_EM_ALIGN_U16;
|
||||
loc->flags = TCF_EM_CMP_TRANS;
|
||||
} else if (!strcasecmp($2, "u32"))
|
||||
loc->align = TCF_EM_ALIGN_U32;
|
||||
else if (!strcasecmp($2, "h32")) {
|
||||
loc->align = TCF_EM_ALIGN_U32;
|
||||
loc->flags = TCF_EM_CMP_TRANS;
|
||||
}
|
||||
|
||||
free($2);
|
||||
|
||||
loc->name = $1;
|
||||
loc->layer = $3;
|
||||
loc->offset = $4;
|
||||
loc->mask = $5;
|
||||
|
||||
rtnl_pktloc_add(loc);
|
||||
|
||||
$$ = loc;
|
||||
}
|
||||
;
|
||||
|
||||
layer:
|
||||
/* empty */
|
||||
{ $$ = TCF_LAYER_NETWORK; }
|
||||
| LAYER '+'
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
mask:
|
||||
/* empty */
|
||||
{ $$ = 0; }
|
||||
| NUMBER
|
||||
{ $$ = $1; }
|
||||
;
|
|
@ -20,7 +20,8 @@ noinst_PROGRAMS = \
|
|||
nl-route-add nl-route-delete nl-route-get nl-route-list \
|
||||
nl-fib-lookup \
|
||||
nl-list-caches nl-list-sockets \
|
||||
nl-util-addr
|
||||
nl-util-addr \
|
||||
nl-pktloc-lookup
|
||||
|
||||
genl_ctrl_list_SOURCES = genl-ctrl-list.c
|
||||
genl_ctrl_list_LDADD = -lnl-genl -lnl-route
|
||||
|
@ -95,3 +96,6 @@ nl_list_sockets_LDADD = -lnl-route
|
|||
|
||||
nl_util_addr_SOURCES = nl-util-addr.c
|
||||
nl_util_addr_LDADD = -lnl-route
|
||||
|
||||
nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c
|
||||
nl_pktloc_lookup_LDADD = -lnl-route
|
||||
|
|
37
src/nl-pktloc-lookup.c
Normal file
37
src/nl-pktloc-lookup.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* src/nl-pktloc-lookup.c Lookup packet location alias
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <netlink/cli/utils.h>
|
||||
#include <netlink/route/pktloc.h>
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf("Usage: nl-pktloc-lookup <name>\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct rtnl_pktloc *loc;
|
||||
int err;
|
||||
|
||||
if (argc < 2)
|
||||
print_usage();
|
||||
|
||||
if ((err = rtnl_pktloc_lookup(argv[1], &loc)) < 0)
|
||||
nl_cli_fatal(err, "Unable to lookup packet location: %s",
|
||||
nl_geterror(err));
|
||||
|
||||
printf("%s: %u %u+%u 0x%x %u\n", loc->name, loc->align,
|
||||
loc->layer, loc->offset, loc->mask, loc->flags);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue