dect
/
libnl
Archived
13
0
Fork 0

Packet Location Interface

This commit is contained in:
Thomas Graf 2010-07-02 14:06:59 +02:00
parent d378220c96
commit db5bd57899
13 changed files with 475 additions and 5 deletions

View File

@ -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;

View File

@ -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
View 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

View File

@ -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>

View File

@ -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 *);

View 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

View File

@ -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

View File

@ -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
View 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;
}

View 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
View 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; }
;

View File

@ -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
View 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;
}