|
@@ -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;
|
|
|
+}
|