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