|
Message-ID: <3016.50.0.224.253.1350776220.squirrel@lavabit.com> Date: Sat, 20 Oct 2012 16:37:00 -0700 (PDT) From: idunham@...abit.com To: musl@...ts.openwall.com Subject: Re: [PATCH 3/4] Import BSD functions defined in <netinet/ether.h> from NetBSD > +#ifndef _NETINET_ETHER_H > +#define _NETINET_ETHER_H > + > +#include <sys/cdefs.h> > +__BEGIN_DECLS musl does not do nested includes unless *necessary*, nor do we define macros unless it simplifies the code significantly. This detail speeds up compilation significantly. #ifdef __cplusplus extern "C" { #endif is NOT something that obscures the code, and it certainly isn't worth adding another nested include. > +char *ether_ntoa(const struct ether_addr *); > +struct ether_addr *ether_aton(const char *); > +int ether_ntohost(char *, const struct ether_addr *); > +int ether_hostton(const char *, struct ether_addr *); > +int ether_line(const char *, struct ether_addr *, char *); > +__END_DECLS Make that #ifdef __cplusplus } #endif > +#endif /* !_NETINET_ETHER_H */ No comments in headers, and certainly not this trivial. > diff --git a/src/network/ethers.c b/src/network/ethers.c > new file mode 100644 > index 0000000..8014581 > --- /dev/null > +++ b/src/network/ethers.c > @@ -0,0 +1,180 @@ > +/* Origin NetBSD: src/lib/libc/net/ethers.c */ > + > +/* > + * ethers(3N) a la Sun. > + * > + * Written by Roland McGrath <roland@...b.com> 10/14/93. > + * Public domain. > + * > + * port for musl by Abdoulaye Walsimou GAYE <awg@...toolkit.org> > 2012/10/15 > + */ > +#define _BSD_SOURCE > +#include <net/ethernet.h> > +#include <netinet/ether.h> > + > +#include <sys/param.h> > +#include <assert.h> > +#include <errno.h> > +#include <paths.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#ifndef _PATH_ETHERS > +#define _PATH_ETHERS "/etc/ethers" > +#endif > + > +/* > + * ether_ntoa(): > + * This function converts this structure into an ASCII string of the form > + * ``xx:xx:xx:xx:xx:xx'', consisting of 6 hexadecimal numbers separated > + * by colons. It returns a pointer to a static buffer that is reused for > + * each call. > + */ > +char *ether_ntoa(const struct ether_addr *e) > +{ > + static char a[18]; > + > + assert(e != NULL); > + > + (void) snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x", > + e->ether_addr_octet[0], e->ether_addr_octet[1], > + e->ether_addr_octet[2], e->ether_addr_octet[3], > + e->ether_addr_octet[4], e->ether_addr_octet[5]); > + return a; > +} > + > +/* > + * ether_aton(): > + * This function converts an ASCII string of the same form and to a > structure > + * containing the 6 octets of the address. It returns a pointer to a > + * static structure that is reused for each call. > + */ > +struct ether_addr *ether_aton(const char *s) > +{ > + static struct ether_addr n; > + unsigned int i[6]; > + > + assert(s != NULL); > + > + if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1], > + &i[2], &i[3], &i[4], &i[5]) == 6) { > + n.ether_addr_octet[0] = (unsigned char)i[0]; > + n.ether_addr_octet[1] = (unsigned char)i[1]; > + n.ether_addr_octet[2] = (unsigned char)i[2]; > + n.ether_addr_octet[3] = (unsigned char)i[3]; > + n.ether_addr_octet[4] = (unsigned char)i[4]; > + n.ether_addr_octet[5] = (unsigned char)i[5]; > + return &n; > + } > + return NULL; > +} > + > +/* > + * ether_ntohost(): > + * This function interrogates the data base mapping host names to > Ethernet > + * addresses, /etc/ethers. > + * It looks up the given Ethernet address and writes the associated host > name > + * into the character buffer passed. > + * It returns zero if it finds the requested host name and -1 if not. > + */ > +int ether_ntohost(char *hostname, const struct ether_addr *e) > +{ > + FILE *f; > + char *p; > + size_t len; > + struct ether_addr try; > + > + assert(hostname != NULL); > + assert(e != NULL); > + > + f = fopen(_PATH_ETHERS, "r"); > + if (f == NULL) > + return -1; > + while ((p = fgetln(f, &len)) != NULL) { > + if (p[len - 1] != '\n') > + continue; /* skip lines w/o \n */ > + p[--len] = '\0'; > + if (ether_line(p, &try, hostname) == 0 && > + memcmp(&try, e, sizeof try) == 0) { > + (void)fclose(f); > + return 0; > + } > + } > + (void)fclose(f); > + errno = ENOENT; > + return -1; > +} > + > +/* > + * ether_hostton(): > + * This function interrogates the data base mapping host names to > Ethernet > + * addresses, /etc/ethers. > + * It looks up the given host name and writes the associated Ethernet > address > + * into the structure passed. > + * It returns zero if it finds the requested address and -1 if not. > + */ > +int ether_hostton(const char *hostname, struct ether_addr *e) > +{ > + FILE *f; > + char *p; > + size_t len; > + char try[MAXHOSTNAMELEN + 1]; > + > + assert(hostname != NULL); > + assert(e != NULL); > + > + f = fopen(_PATH_ETHERS, "r"); > + if (f==NULL) > + return -1; > + > + while ((p = fgetln(f, &len)) != NULL) { > + if (p[len - 1] != '\n') > + continue; /* skip lines w/o \n */ > + p[--len] = '\0'; > + if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0) { > + (void)fclose(f); > + return 0; > + } > + } > + (void)fclose(f); > + errno = ENOENT; > + return -1; > +} > + > +/* > + * ether_line(): > + * This function parses a line from the /etc/ethers file and fills in the > passed > + * ``struct ether_addr'' and character buffer with the Ethernet address > and host > + * name on the line. > + * It returns zero if the line was successfully parsed and -1 if not. > + */ > +int ether_line(const char *l, struct ether_addr *e, char *hostname) > +{ > + unsigned int i[6]; > + > +#define S2(arg) #arg > +#define S1(arg) S2(arg) > + static const char fmt[] = " %x:%x:%x:%x:%x:%x" > + " %" S1(MAXHOSTNAMELEN) "s\n"; > +#undef S2 > +#undef S1 > + > + assert(l != NULL); > + assert(e != NULL); > + assert(hostname != NULL); > + > + if (sscanf(l, fmt, > + &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) { > + e->ether_addr_octet[0] = (unsigned char)i[0]; > + e->ether_addr_octet[1] = (unsigned char)i[1]; > + e->ether_addr_octet[2] = (unsigned char)i[2]; > + e->ether_addr_octet[3] = (unsigned char)i[3]; > + e->ether_addr_octet[4] = (unsigned char)i[4]; > + e->ether_addr_octet[5] = (unsigned char)i[5]; > + return 0; > + } > + errno = EINVAL; > + return -1; > +}
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.