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

mac_vendor.c

/* ex: set ts=4 noet: */
/**
 *
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* exit */
#include <string.h> /* memcmp */
#include <ctype.h> /* isalnum() and friends */
#include "types.h" /* size_t? */
#ifndef WIN32
      #include <stdint.h> /* size_t */
#endif
#include <limits.h> /* PATH_MAX */
#include "lanmap.h"
#include "debug.h"
#include "misc.h"

#undef DEBUG_MAC_VENDOR

extern int Verbose;

static struct mac_vend *Mac_Vends = NULL;
static size_t Mac_Vends_Len = 0;
static char Mac_Vendor_File[PATH_MAX] = xstr(LANMAP_DATADIR) MAC_VENDOR_FILE;

/**
 * @return 0 on success, 1 on failure
 */
int mac_vend_init(void)
{
      FILE *f;
      char line[128], *c;
      int unsigned pref1, pref2, pref3;
      struct mac_vend *mv = Mac_Vends;
      int err = 0;
      size_t lineno = 0;

      f = fopen(Mac_Vendor_File, "r");
      if (NULL == f) {
            perror(Mac_Vendor_File);
            return 1;
      }
      /* FIXME: flock */
      while (NULL != fgets(line, sizeof line, f)) {
            int scan;
            lineno++;
#if 0
            DEBUGF(__FILE__, __LINE__, "line:%u, \"%s\"", lineno, line);
#endif
            /* check that line is short enough, if not, it is invalid and we bail */
            c = strchr(line, '\0');
            if (NULL == c) {
                  err = 1;
                  break;
            } else if ((c - line > 1 && *(c - 1) != '\n')) {
                  WARNF(__FILE__, __LINE__,
                        "%s:%u is too long! \"%s\" (max line %u chars) skipping...",
                        Mac_Vendor_File, lineno, line, sizeof line - 1);
                  continue;
            }
            if (c == line || '#' == line[0]) /* empty line or comment, skip */
                  continue;
            *(c - 1) = '\0'; /* trim \n */

            /* make sure we have enough room */
            if ((size_t)(mv - Mac_Vends + 1) >= Mac_Vends_Len) {
                  void *tmp;
                  size_t grow = (0 == Mac_Vends_Len ? 8 : Mac_Vends_Len * 2);
                  tmp = realloc(Mac_Vends, sizeof *mv * grow);
                  if (NULL == tmp) {
                        FATALF(__FILE__, __LINE__,
                              "%s:%u: Out of memory error, could not allocate %u vendors",
                              Mac_Vendor_File, lineno, grow);
                        err = 1;
                        break;
                  }
                  Mac_Vends = tmp;
                  mv = Mac_Vends + Mac_Vends_Len - 1;
                  Mac_Vends_Len = grow;
            }

            /* parse line */
            scan = sscanf(line, "%2x%2x%2x %63[^#]",
                  &pref1, &pref2, &pref3, mv->vendor);
            //printf("sscanf: %d, prefix: %s\n", err, mv->prefix);
            if (4 != scan) {
                  ERRORF(__FILE__, __LINE__,
                        "%s:%u: failed parsing \"%s\"... skipping...",
                        Mac_Vendor_File, lineno, line);
                  continue;
            }

            /* convert prefix to binary */
            mv->prefix[0] = (pref1 & 0xFF);
            mv->prefix[1] = (pref2 & 0xFF);
            mv->prefix[2] = (pref3 & 0xFF);

            /* replace any bogus chars with "?" */
            for (c = mv->vendor; '\0' != *c; c++) {
                  /* we get a warning for this in gcc, but apparently in windows character can hold >255?! */
                  int chr = *c;
                  if (chr < 0 || chr > 255 || (!isalnum(*c) && !isspace(*c) && !ispunct(*c)))
                        *c = '?';
            }

            (void)strtrim(mv->vendor);

#if 0
            printf("%s:%u (%s:%s) <- \"%s\"...\n", 
                  Mac_Vendor_File, lineno, mv->prefix, mv->vendor, line);
#endif

            mv++;
      }

      fclose(f);

      if (err) {
            free(Mac_Vends);
            Mac_Vends = NULL;
      } else if (Mac_Vends_Len > (size_t)(mv - Mac_Vends + 1)) {
            /* realloc memory back down, we likely have extra we allocated but don't need */
            void *tmp;
            Mac_Vends_Len = (mv - Mac_Vends);
            tmp = realloc(Mac_Vends, Mac_Vends_Len * sizeof *mv);
            if (NULL != tmp)
                  Mac_Vends = tmp;
      }

      if (!err && Verbose >= 3)
            printf("%lu records loaded from %s\n",
                  (long unsigned)Mac_Vends_Len, Mac_Vendor_File);

      return err;
}

/**
 * reload the our data
 */
int mac_vend_reload(void)
{
      free(Mac_Vends);
      Mac_Vends = NULL;
      Mac_Vends_Len = 0;
      return mac_vend_init();
}

/**
 *
 */
void mac_vend_dump(void)
{
      size_t i;

      if (NULL == Mac_Vends) {
            fprintf(stderr, "No mac vends!\n");
            return;
      }

      for (i = 0; i < Mac_Vends_Len; i++) {
            printf("#%lu %02X%02X%02X (%s)\n",
                  (long unsigned)i, Mac_Vends[i].prefix[0], Mac_Vends[i].prefix[1],
                  Mac_Vends[i].prefix[2], Mac_Vends[i].vendor);
      }
      printf("%lu entries\n", (long unsigned)Mac_Vends_Len);
}

/**
 *
 */
static int mac_vend_cmp(const void *va, const void *vb)
{
      const struct mac_vend *a, *b;
#ifdef _DEBUG
      assert(NULL != va);
      assert(NULL != vb);
#endif
      a = va, b = vb;
#ifdef DEBUG_MAC_VENDOR
      DEBUGF(__FILE__, __LINE__, "\"%02X%02X%02X\" vs. \"%02X%02X%02X\"",
            a->prefix[0], a->prefix[1], a->prefix[2],
            b->prefix[0], b->prefix[1], b->prefix[2]);
#endif
      return memcmp(a->prefix, b->prefix, sizeof a->prefix);
}

/**
 *
 */
const struct mac_vend * mac_addr_vend(const struct mac *mac)
{
      struct mac_vend search;
#ifdef _DEBUG
      assert(NULL != mac);
#endif
      memcpy(search.prefix, mac->addr, sizeof search.prefix);
      return bsearch(&search, Mac_Vends, Mac_Vends_Len,
            sizeof(struct mac_vend), mac_vend_cmp);
}

/**
 *
 */
const char * mac_addr_vend_name(const struct mac *mac)
{
      struct mac_vend search;
      const struct mac_vend *found;
#ifdef _DEBUG
      assert(NULL != mac);
#endif
      memcpy(search.prefix, mac->addr, sizeof search.prefix);
      found = bsearch(&search, Mac_Vends, Mac_Vends_Len,
            sizeof(struct mac_vend), mac_vend_cmp);
      return (NULL == found ? NULL : found->vendor);
}

#ifdef STANDALONE_MAC_VENDOR
/**
 *
 */
int main(void)
{
      const struct mac_vend *search;
      mac_vend_init();
      mac_vend_dump();
      search = mac_addr_vend("\x00\x0C\x41");
      printf("search:%p\n", search);
      return 0;
}
#endif


Generated by  Doxygen 1.6.0   Back to index