diff options
-rw-r--r-- | include/netinet/ether.h | 2 | ||||
-rw-r--r-- | libc/inet/Makefile.in | 2 | ||||
-rwxr-xr-x | libc/inet/ethers.c | 122 | ||||
-rwxr-xr-x | test/inet/tst-ethers-line.c | 45 | ||||
-rwxr-xr-x | test/inet/tst-ethers.c | 28 |
5 files changed, 198 insertions, 1 deletions
diff --git a/include/netinet/ether.h b/include/netinet/ether.h index ca780e2d0..a16255037 100644 --- a/include/netinet/ether.h +++ b/include/netinet/ether.h @@ -25,6 +25,8 @@ /* Get definition of `struct ether_addr'. */ #include <netinet/if_ether.h> +#define ETHER_FILE_NAME "/etc/ethers" + __BEGIN_DECLS /* Convert 48 bit Ethernet ADDRess to ASCII. */ diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in index 8cb8661c4..b1ea25b26 100644 --- a/libc/inet/Makefile.in +++ b/libc/inet/Makefile.in @@ -23,7 +23,7 @@ CSRC += encodeh.c decodeh.c encoded.c decoded.c lengthd.c encodeq.c \ res_query.c gethostbyaddr.c read_etc_hosts_r.c get_hosts_byname_r.c \ get_hosts_byaddr_r.c gethostbyname2.c getnameinfo.c gethostent.c \ gethostbyname_r.c gethostbyname2_r.c gethostbyaddr_r.c \ - res_comp.c ns_name.c + res_comp.c ns_name.c ethers.c # unused ATM CSRC += encodep.c decodep.c formquery.c diff --git a/libc/inet/ethers.c b/libc/inet/ethers.c new file mode 100755 index 000000000..857e5d165 --- /dev/null +++ b/libc/inet/ethers.c @@ -0,0 +1,122 @@ +/* + * libc/inet/ethers.c + * + * Programmatic interface for the /etc/ethers file + * + * Copyright 2007 by Matthew Wilcox <matthew@wil.cx> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <netinet/ether.h> + +#define ETHER_LINE_LEN 256 + +/* + * Internal function which returns a pointer to the part of the line + * with the start of the hostname, or NULL if we couldn't parse the line. + * Note that this line may have a comment symbol on it somewhere; if so + * it will return NULL if the # is before or within the ether_addr, and + * succeed if the # is before or within the host. It's up to the callers + * to be aware of this. + * + * I would have preferred to write a NUL to the location of the comment + * character, but ether_line takes a const argument. See __ether_line_w. + */ +static const char *__ether_line(const char *line, struct ether_addr *addr) +{ + struct ether_addr *res = ether_aton_r(line, addr); + if (!res) + return NULL; + + while (*line && (*line != ' ') && (*line != '\t')) + line++; + while (*line && ((*line == ' ') || (*line == '\t'))) + line++; + return (*line) ? line : NULL; +} + +/* + * Strips out the comment before calling __ether_line. We can do this, + * since we know the buffer is writable. + */ +static const char *__ether_line_w(char *line, struct ether_addr *addr) +{ + char *end = strchr(line, '#'); + if (!end) + end = strchr(line, '\n'); + if (end) + *end = '\0'; + return __ether_line(line, addr); +} + +int ether_line(const char *line, struct ether_addr *addr, char *hostname) +{ + const char *name = __ether_line(line, addr); + if (!name) + return -1; + + while (*name) { + if ((*name == '#') || isspace(*name)) + break; + *hostname++ = *name++; + } + *hostname = '\0'; + + return 0; +} + +int ether_ntohost(char *hostname, const struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + struct ether_addr tmp_addr; + const char *cp = __ether_line_w(buf, &tmp_addr); + if (!cp) + continue; + if (memcmp(addr, &tmp_addr, sizeof(tmp_addr))) + continue; + + strcpy(hostname, cp); + res = 0; + break; + } + + fclose(fp); + return res; +} + +int ether_hostton(const char *hostname, struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + const char *cp = __ether_line_w(buf, addr); + if (!cp) + continue; + if (strcasecmp(hostname, cp)) + continue; + + res = 0; + break; + } + + fclose(fp); + return res; +} diff --git a/test/inet/tst-ethers-line.c b/test/inet/tst-ethers-line.c new file mode 100755 index 000000000..d4835b546 --- /dev/null +++ b/test/inet/tst-ethers-line.c @@ -0,0 +1,45 @@ +#include <netinet/ether.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> + +#define ETHER_LINE_LEN 256 + +int main(void) +{ + struct ether_addr addr; + char hostname[ETHER_LINE_LEN]; + int fd, i; + const char *ethers; + struct stat statb; + + if ((fd = open(ETHER_FILE_NAME, O_RDONLY)) == -1) { + perror ("Cannot open file"); + exit(1); + } + + if (fstat(fd, &statb)) { + perror("Stat failed"); + exit(1); + } + ethers = mmap(NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0); + + if (ethers == MAP_FAILED) { + perror("File mapping failed"); + exit(1); + } + + ether_line(ethers, &addr, hostname); + + for (i = 0; i < 6; i++) { + printf("%02x", addr.ether_addr_octet[i]); + if (i < 5) + printf(":"); + } + printf(" %s\n", hostname); + + return 0; +} diff --git a/test/inet/tst-ethers.c b/test/inet/tst-ethers.c new file mode 100755 index 000000000..eb6280c3f --- /dev/null +++ b/test/inet/tst-ethers.c @@ -0,0 +1,28 @@ +#include <netinet/ether.h> +#include <stdio.h> + +#define ETHER_LINE_LEN 256 + +int main(void) +{ + struct ether_addr addr; + char host[ETHER_LINE_LEN]; + int i; + int res = ether_hostton("teeth", &addr); + + if (res) + return 1; + + for (i = 0; i < 6; i++) { + printf("%02x", addr.ether_addr_octet[i]); + if (i < 5) + printf(":"); + } + + res = ether_ntohost(host, &addr); + if (res) + return 1; + printf(" %s\n", host); + + return 0; +} |