/* * Copyright (c) 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] = "@(#) $Id: ec.c,v 1.28 2000/10/13 22:49:15 leres Exp $ (LBL)"; #endif /* * ec - manufactures ethernet code routines */ #include #include #include #if __STDC__ struct mbuf; struct rtentry; #endif #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif #include #include #include #include #include "gnuc.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #include "arpwatch.h" #include "ec.h" #include "util.h" /* Basic data structure */ struct ecent { u_int32_t o; /* first 3 octets */ char *text; /* associated text */ }; static struct ecent *list; static u_int ec_last = 0; static u_int ec_len = 0; /* Forwards */ static int ec_a2o(char *, u_int32_t *); /* Convert an 3 octets from an ethernet address to a u_int32_t */ static int ec_a2o(register char *cp, register u_int32_t *op) { char xbuf[128]; u_char e[6]; (void)sprintf(xbuf, "%.32s:0:0:0", cp); if (!str2e(xbuf, e)) return (0); *op = 0; BCOPY(e, op, 3); return (1); } /* Add a ethernet code to the database */ int ec_add(register u_int32_t o, register char *text) { if (ec_last >= ec_len) { if (list == NULL) { ec_len = 512; list = malloc(ec_len * sizeof(*list)); } else { ec_len *= 2; list = realloc(list, ec_len * sizeof(*list)); } if (list == NULL) { syslog(LOG_ERR, "ec_add(): malloc: %m"); exit(1); } } list[ec_last].o = o; list[ec_last].text = savestr(text); ++ec_last; return (1); } /* Find the manufacture for a given ethernet address */ char * ec_find(register u_char *e) { u_int32_t o; register int i; o = 0; BCOPY(e, &o, 3); for (i = 0; i < ec_last; ++i) if (list[i].o == o) return (list[i].text); return (NULL); } /* Loop through the ethernet code database */ int ec_loop(register FILE *f, ec_process fn, register const char *nm) { register int n; register char *cp, *cp2, *text; register int sawblank; u_int32_t o; char line[1024]; n = 0; while (fgets(line, sizeof(line), f)) { ++n; cp = line; cp2 = cp + strlen(cp) - 1; if (cp2 >= cp && *cp2 == '\n') *cp2++ = '\0'; if (*cp == '#') continue; if ((cp2 = strchr(cp, '\t')) == 0) { syslog(LOG_ERR, "ec_loop(): %s:%d missing tab", nm, n); continue; } /* 3 octets come first */ *cp2++ = '\0'; text = cp2; if (!ec_a2o(cp, &o)) { syslog(LOG_ERR, "ec_loop(): %s:%d bad octets", nm, n); continue; } /* Compress blanks */ cp = cp2 = text; sawblank = 0; while (*cp != '\0') { if (sawblank) { *cp2++ = ' '; sawblank = 0; } *cp2++ = *cp++; while (isspace((int)*cp)) { ++cp; sawblank = 1; } } *cp2 = '\0'; if (!(*fn)(o, text)) return (0); } return (1); } /* DECnet local logical address prefix */ static u_char decnet[3] = { 0xaa, 0x0, 0x4 }; /* Returns true if an ethernet address is decnet, else false */ int isdecnet(register u_char *e) { return (MEMCMP(e, decnet, sizeof(decnet)) == 0); } /* Convert an ascii ethernet string to ethernet address */ int str2e(register char *str, register u_char *e) { register int i; u_int n[6]; MEMSET(n, 0, sizeof(n)); if (sscanf(str, "%x:%x:%x:%x:%x:%x", &n[0], &n[1], &n[2], &n[3], &n[4], &n[5]) != 6) return (0); for (i = 0; i < 6; ++i) { if (n[i] > 0xff) return (0); e[i] = n[i]; } return (1); } /* Convert an ethernet address to an ascii ethernet string */ char * e2str(register u_char *e) { static char str[32]; (void)sprintf(str, "%x:%x:%x:%x:%x:%x", e[0], e[1], e[2], e[3], e[4], e[5]); return (str); }