pktloc.c revision db5bd57899affbcaf42ac0b93c5c7be8f51ca390
1db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/* 2db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * lib/route/pktloc.c Packet Location Aliasing 3db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 4db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * This library is free software; you can redistribute it and/or 5db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * modify it under the terms of the GNU General Public License as 6db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * published by the Free Software Foundation version 2 of the License. 7db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 8db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch> 9db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf */ 10db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 11db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/** 12db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @ingroup tc 13db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @defgroup pktloc Packet Location Aliasing 14db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * Packet Location Aliasing 15db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 16db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * The packet location aliasing interface eases the use of offset definitions 17db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * inside packets by allowing them to be referenced by name. Known positions 18db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * of protocol fields are stored in a configuration file and associated with 19db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * a name for later reference. The configuration file is distributed with the 20db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * library and provides a well defined set of definitions for most common 21db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * protocol fields. 22db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 23db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @subsection pktloc_examples Examples 24db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @par Example 1.1 Looking up a packet location 25db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @code 26db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * struct rtnl_pktloc *loc; 27db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 28db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * rtnl_pktloc_lookup("ip.src", &loc); 29db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @endcode 30db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @{ 31db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf */ 32db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 33db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include <netlink-local.h> 34db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include <netlink-tc.h> 35db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include <netlink/netlink.h> 36db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include <netlink/utils.h> 37db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include <netlink/route/pktloc.h> 38db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 39db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include "pktloc_syntax.h" 40db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#include "pktloc_grammar.h" 41db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 42db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/** @cond */ 43db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf#define PKTLOC_NAME_HT_SIZ 256 44db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 45db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafstatic struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ]; 46db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 47db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/* djb2 */ 48db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafunsigned int pktloc_hash(const char *str) 49db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 50db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf unsigned long hash = 5381; 51db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf int c; 52db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 53db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf while ((c = *str++)) 54db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 55db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 56db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return hash % PKTLOC_NAME_HT_SIZ; 57db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 58db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 59db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 60db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafvoid rtnl_pktloc_add(struct rtnl_pktloc *loc) 61db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 62db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]); 63db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 64db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 65db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafextern int pktloc_parse(void *scanner); 66db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 67db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/** @endcond */ 68db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 69db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafstatic void rtnl_pktloc_free(struct rtnl_pktloc *loc) 70db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 71db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (!loc) 72db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return; 73db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 74db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf free(loc->name); 75db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf free(loc); 76db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 77db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 78db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafstatic int read_pktlocs(void) 79db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 80db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf YY_BUFFER_STATE buf; 81db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf yyscan_t scanner = NULL; 82db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf static time_t last_read; 83db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf struct stat st = {0}; 84db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf char *path; 85db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf int i, err; 86db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf FILE *fd; 87db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 88db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf asprintf(&path, "%s/pktloc", SYSCONFDIR); 89db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 90db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf /* if stat fails, just try to read the file */ 91db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (stat(path, &st) == 0) { 92db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf /* Don't re-read file if file is unchanged */ 93db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (last_read == st.st_mtime) 94db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return 0; 95db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf } 96db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 97db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (!(fd = fopen(path, "r"))) 98db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return -NLE_PKTLOC_FILE; 99db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 100db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) { 101db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf struct rtnl_pktloc *loc, *n; 102db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 103db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list) 104db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf rtnl_pktloc_free(loc); 105db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 106db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf nl_init_list_head(&pktloc_name_ht[i]); 107db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf } 108db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 109db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if ((err = pktloc_lex_init(&scanner)) < 0) 110db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return -NLE_FAILURE; 111db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 112db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner); 113db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf pktloc__switch_to_buffer(buf, scanner); 114db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 115db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if ((err = pktloc_parse(scanner)) < 0) 116db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return -NLE_FAILURE; 117db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 118db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (scanner) 119db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf pktloc_lex_destroy(scanner); 120db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 121db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf free(path); 122db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf last_read = st.st_mtime; 123db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 124db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return 0; 125db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 126db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 127db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf/** 128db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * Lookup packet location alias 129db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @arg name Name of packet location. 130db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 131db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * Tries to find a matching packet location alias for the supplied 132db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * packet location name. 133db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 134db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * The file containing the packet location definitions is automatically 135db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * re-read if its modification time has changed since the last call. 136db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * 137db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @return 0 on success or a negative error code. 138db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @retval NLE_PKTLOC_FILE Unable to open packet location file. 139db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf * @retval NLE_OBJ_NOTFOUND No matching packet location alias found. 140db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf */ 141db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafint rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result) 142db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 143db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf struct rtnl_pktloc *loc; 144db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf int hash, err; 145db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 146db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if ((err = read_pktlocs()) < 0) 147db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return err; 148db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 149db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf hash = pktloc_hash(name); 150db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) { 151db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf if (!strcasecmp(loc->name, name)) { 152db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf *result = loc; 153db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return 0; 154db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf } 155db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf } 156db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 157db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return -NLE_OBJ_NOTFOUND; 158db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 159db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 160db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Grafstatic int __init pktloc_init(void) 161db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf{ 162db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf int i; 163db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 164db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) 165db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf nl_init_list_head(&pktloc_name_ht[i]); 166db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf 167db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf return 0; 168db5bd57899affbcaf42ac0b93c5c7be8f51ca390Thomas Graf} 169