Implementation of ether_line, ether_hostton and ether_ntohost
Carmelo Amoroso
carmelo73 at gmail.com
Tue Feb 12 19:10:41 UTC 2008
Matthew Wilcox wrote:
> I want to be able to etherwake by hostname. Since I've gone to the
> trouble of putting that information in /etc/ethers, I think my computer
> should jolly well not force me to type in meaningless strings of hex.
>
> So here's an implementation (ethers.c) and two test programs
> (ethers-line-test.c and ethers-test.c) which exercise it a little.
> I'm not sure how to integrate all this into your build framework; seems
> to me you guys would be the experts at that ;-)
>
> I hope you find my contribution useful.
>
Let me see.... indeed I'm interested into etherwake too
Cheers,
Carmelo
> (Oh, and in case anyone's wondering, I have an agreement with my
> employer that this work I did in my own time belongs to me.)
>
>
>
> ------------------------------------------------------------------------
>
> /*
> * libc/inet/ethers.c
> *
> * Programmatic interface for the /etc/ethers file
> *
> * Copyright 2007 by Matthew Wilcox <matthew at 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>
>
> #ifndef ETHER_FILE_NAME
> #define ETHER_FILE_NAME "/etc/ethers"
> #endif
> #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;
> }
>
>
> ------------------------------------------------------------------------
>
> #include <netinet/ether.h>
> #include <stdio.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
>
> #include "ethers.c"
>
> int main(void)
> {
> struct ether_addr addr;
> char hostname[1024];
> int fd = open("ethers", O_RDONLY);
> const char *ethers = mmap(NULL, 100000, PROT_READ, MAP_SHARED, fd, 0);
>
> ether_line(ethers, &addr, hostname);
>
> printf("%s\n", hostname);
>
> return 0;
> }
>
>
> ------------------------------------------------------------------------
>
> #define ETHER_FILE_NAME "ethers"
> #include "ethers.c"
>
> int main(void)
> {
> struct ether_addr addr;
> char host[256];
> int i, 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(" ");
> else
> printf(":");
> }
>
> res = ether_ntohost(host, &addr);
> if (res)
> return 1;
> printf("%s\n", host);
>
> return 0;
> }
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://busybox.net/cgi-bin/mailman/listinfo/uclibc
More information about the uClibc
mailing list