2 * lib/route/pktloc.c Packet Location Aliasing
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
14 * @defgroup pktloc Packet Location Aliasing
15 * Packet Location Aliasing
17 * The packet location aliasing interface eases the use of offset definitions
18 * inside packets by allowing them to be referenced by name. Known positions
19 * of protocol fields are stored in a configuration file and associated with
20 * a name for later reference. The configuration file is distributed with the
21 * library and provides a well defined set of definitions for most common
24 * @subsection pktloc_examples Examples
25 * @par Example 1.1 Looking up a packet location
27 * struct rtnl_pktloc *loc;
29 * rtnl_pktloc_lookup("ip.src", &loc);
34 #include <netlink-local.h>
35 #include <netlink-tc.h>
36 #include <netlink/netlink.h>
37 #include <netlink/utils.h>
38 #include <netlink/route/pktloc.h>
40 #include "pktloc_syntax.h"
41 #include "pktloc_grammar.h"
44 #define PKTLOC_NAME_HT_SIZ 256
46 static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ];
49 unsigned int pktloc_hash(const char *str)
51 unsigned long hash = 5381;
55 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
57 return hash % PKTLOC_NAME_HT_SIZ;
61 void rtnl_pktloc_add(struct rtnl_pktloc *loc)
63 nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]);
66 extern int pktloc_parse(void *scanner);
70 static void rtnl_pktloc_free(struct rtnl_pktloc *loc)
79 static int read_pktlocs(void)
82 yyscan_t scanner = NULL;
83 static time_t last_read;
89 asprintf(&path, "%s/pktloc", SYSCONFDIR);
91 /* if stat fails, just try to read the file */
92 if (stat(path, &st) == 0) {
93 /* Don't re-read file if file is unchanged */
94 if (last_read == st.st_mtime) {
100 if (!(fd = fopen(path, "r"))) {
101 err = -NLE_PKTLOC_FILE;
105 for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) {
106 struct rtnl_pktloc *loc, *n;
108 nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list)
109 rtnl_pktloc_free(loc);
111 nl_init_list_head(&pktloc_name_ht[i]);
114 if ((err = pktloc_lex_init(&scanner)) < 0) {
119 buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner);
120 pktloc__switch_to_buffer(buf, scanner);
122 if ((err = pktloc_parse(scanner)) < 0) {
127 last_read = st.st_mtime;
131 pktloc_lex_destroy(scanner);
141 * Lookup packet location alias
142 * @arg name Name of packet location.
144 * Tries to find a matching packet location alias for the supplied
145 * packet location name.
147 * The file containing the packet location definitions is automatically
148 * re-read if its modification time has changed since the last call.
150 * @return 0 on success or a negative error code.
151 * @retval NLE_PKTLOC_FILE Unable to open packet location file.
152 * @retval NLE_OBJ_NOTFOUND No matching packet location alias found.
154 int rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result)
156 struct rtnl_pktloc *loc;
159 if ((err = read_pktlocs()) < 0)
162 hash = pktloc_hash(name);
163 nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) {
164 if (!strcasecmp(loc->name, name)) {
170 return -NLE_OBJ_NOTFOUND;
173 static int __init pktloc_init(void)
177 for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++)
178 nl_init_list_head(&pktloc_name_ht[i]);