00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <netlink-local.h>
00034 #include <netlink-tc.h>
00035 #include <netlink/netlink.h>
00036 #include <netlink/utils.h>
00037 #include <netlink/route/pktloc.h>
00038
00039 #include "pktloc_syntax.h"
00040 #include "pktloc_grammar.h"
00041
00042
00043 #define PKTLOC_NAME_HT_SIZ 256
00044
00045 static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ];
00046
00047
00048 unsigned int pktloc_hash(const char *str)
00049 {
00050 unsigned long hash = 5381;
00051 int c;
00052
00053 while ((c = *str++))
00054 hash = ((hash << 5) + hash) + c;
00055
00056 return hash % PKTLOC_NAME_HT_SIZ;
00057 }
00058
00059 static int __pktloc_lookup(const char *name, struct rtnl_pktloc **result)
00060 {
00061 struct rtnl_pktloc *loc;
00062 int hash;
00063
00064 hash = pktloc_hash(name);
00065 nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) {
00066 if (!strcasecmp(loc->name, name)) {
00067 loc->refcnt++;
00068 *result = loc;
00069 return 0;
00070 }
00071 }
00072
00073 return -NLE_OBJ_NOTFOUND;
00074 }
00075
00076 extern int pktloc_parse(void *scanner);
00077
00078 static void rtnl_pktloc_free(struct rtnl_pktloc *loc)
00079 {
00080 if (!loc)
00081 return;
00082
00083 free(loc->name);
00084 free(loc);
00085 }
00086
00087 static int read_pktlocs(void)
00088 {
00089 YY_BUFFER_STATE buf = NULL;
00090 yyscan_t scanner = NULL;
00091 static time_t last_read;
00092 struct stat st = {0};
00093 char *path;
00094 int i, err;
00095 FILE *fd;
00096
00097 asprintf(&path, "%s/pktloc", SYSCONFDIR);
00098
00099
00100 if (stat(path, &st) == 0) {
00101
00102 if (last_read == st.st_mtime)
00103 return 0;
00104 }
00105
00106 NL_DBG(2, "Reading packet location file \"%s\"\n", path);
00107
00108 if (!(fd = fopen(path, "r"))) {
00109 err = -NLE_PKTLOC_FILE;
00110 goto errout;
00111 }
00112
00113 for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) {
00114 struct rtnl_pktloc *loc, *n;
00115
00116 nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list)
00117 rtnl_pktloc_put(loc);
00118
00119 nl_init_list_head(&pktloc_name_ht[i]);
00120 }
00121
00122 if ((err = pktloc_lex_init(&scanner)) < 0) {
00123 err = -NLE_FAILURE;
00124 goto errout_close;
00125 }
00126
00127 buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner);
00128 pktloc__switch_to_buffer(buf, scanner);
00129
00130 if ((err = pktloc_parse(scanner)) != 0) {
00131 pktloc__delete_buffer(buf, scanner);
00132 err = -NLE_PARSE_ERR;
00133 goto errout_scanner;
00134 }
00135
00136 last_read = st.st_mtime;
00137
00138 errout_scanner:
00139 if (scanner)
00140 pktloc_lex_destroy(scanner);
00141 errout_close:
00142 fclose(fd);
00143 errout:
00144 free(path);
00145
00146 return 0;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 int rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result)
00170 {
00171 int err;
00172
00173 if ((err = read_pktlocs()) < 0)
00174 return err;
00175
00176 return __pktloc_lookup(name, result);
00177 }
00178
00179
00180
00181
00182 struct rtnl_pktloc *rtnl_pktloc_alloc(void)
00183 {
00184 struct rtnl_pktloc *loc;
00185
00186 if (!(loc = calloc(1, sizeof(*loc))))
00187 return NULL;
00188
00189 loc->refcnt = 1;
00190 nl_init_list_head(&loc->list);
00191
00192 return loc;
00193 }
00194
00195
00196
00197
00198
00199 void rtnl_pktloc_put(struct rtnl_pktloc *loc)
00200 {
00201 if (!loc)
00202 return;
00203
00204 loc->refcnt--;
00205 if (loc->refcnt <= 0)
00206 rtnl_pktloc_free(loc);
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 int rtnl_pktloc_add(struct rtnl_pktloc *loc)
00216 {
00217 struct rtnl_pktloc *l;
00218
00219 if (__pktloc_lookup(loc->name, &l) == 0) {
00220 rtnl_pktloc_put(l);
00221 return -NLE_EXIST;
00222 }
00223
00224 NL_DBG(2, "New packet location entry \"%s\" align=%u layer=%u "
00225 "offset=%u mask=%#x shift=%u refnt=%u\n",
00226 loc->name, loc->align, loc->layer, loc->offset,
00227 loc->mask, loc->shift, loc->refcnt);
00228
00229 nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]);
00230
00231 return 0;
00232 }
00233
00234 void rtnl_pktloc_foreach(void (*cb)(struct rtnl_pktloc *, void *), void *arg)
00235 {
00236 struct rtnl_pktloc *loc;
00237 int i;
00238
00239
00240 read_pktlocs();
00241
00242 for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++)
00243 nl_list_for_each_entry(loc, &pktloc_name_ht[i], list)
00244 cb(loc, arg);
00245 }
00246
00247 static int __init pktloc_init(void)
00248 {
00249 int i;
00250
00251 for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++)
00252 nl_init_list_head(&pktloc_name_ht[i]);
00253
00254 return 0;
00255 }
00256
00257