/* * 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; }