Logo Search packages:      
Sourcecode: libnl2 version File versions  Download package

pktloc.c

/*
 * 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 */

00069 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.
 */
00141 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;
}

Generated by  Doxygen 1.6.0   Back to index