blob: 857e5d165cb55062a73b4093424668fe65ce828e [file] [log] [blame]
/*
* 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;
}