xref: /dragonfly/contrib/dhcpcd/src/common.c (revision 7c4f4eee)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * dhcpcd - DHCP client daemon
4  * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
5  * All rights reserved
6 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #ifdef __sun
32 #include <sys/sysmacros.h>
33 #endif
34 
35 #include <assert.h>
36 #include <ctype.h>
37 #include <err.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <limits.h>
41 #ifdef BSD
42 #  include <paths.h>
43 #endif
44 #include <stdarg.h>
45 #include <stdint.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <time.h>
50 #include <unistd.h>
51 
52 #include "common.h"
53 #include "dhcpcd.h"
54 #include "if-options.h"
55 #include "logerr.h"
56 
57 /* Most route(4) messages are less than 256 bytes. */
58 #define IOVEC_BUFSIZ	256
59 
60 const char *
61 hwaddr_ntoa(const void *hwaddr, size_t hwlen, char *buf, size_t buflen)
62 {
63 	const unsigned char *hp, *ep;
64 	char *p;
65 
66 	if (buf == NULL)
67 		return NULL;
68 
69 	if (hwlen * 3 > buflen) {
70 		errno = ENOBUFS;
71 		return NULL;
72 	}
73 
74 	hp = hwaddr;
75 	ep = hp + hwlen;
76 	p = buf;
77 
78 	while (hp < ep) {
79 		if (hp != hwaddr)
80 			*p ++= ':';
81 		p += snprintf(p, 3, "%.2x", *hp++);
82 	}
83 	*p ++= '\0';
84 	return buf;
85 }
86 
87 size_t
88 hwaddr_aton(uint8_t *buffer, const char *addr)
89 {
90 	char c[3];
91 	const char *p = addr;
92 	uint8_t *bp = buffer;
93 	size_t len = 0;
94 
95 	c[2] = '\0';
96 	while (*p != '\0') {
97 		/* Skip separators */
98 		c[0] = *p++;
99 		switch (c[0]) {
100 		case '\n':	/* long duid split on lines */
101 		case ':':	/* typical mac address */
102 		case '-':	/* uuid */
103 			continue;
104 		}
105 		c[1] = *p++;
106 		/* Ensure that digits are hex */
107 		if (isxdigit((unsigned char)c[0]) == 0 ||
108 		    isxdigit((unsigned char)c[1]) == 0)
109 		{
110 			errno = EINVAL;
111 			return 0;
112 		}
113 		/* We should have at least two entries 00:01 */
114 		if (len == 0 && *p == '\0') {
115 			errno = EINVAL;
116 			return 0;
117 		}
118 		if (bp)
119 			*bp++ = (uint8_t)strtol(c, NULL, 16);
120 		len++;
121 	}
122 	return len;
123 }
124 
125 size_t
126 read_hwaddr_aton(uint8_t **data, const char *path)
127 {
128 	FILE *fp;
129 	char *buf;
130 	size_t buf_len, len;
131 
132 	if ((fp = fopen(path, "r")) == NULL)
133 		return 0;
134 
135 	buf = NULL;
136 	buf_len = len = 0;
137 	*data = NULL;
138 	while (getline(&buf, &buf_len, fp) != -1) {
139 		if ((len = hwaddr_aton(NULL, buf)) != 0) {
140 			if (buf_len >= len)
141 				*data = (uint8_t *)buf;
142 			else {
143 				if ((*data = malloc(len)) == NULL)
144 					len = 0;
145 			}
146 			if (len != 0)
147 				(void)hwaddr_aton(*data, buf);
148 			if (buf_len < len)
149 				free(buf);
150 			break;
151 		}
152 	}
153 	fclose(fp);
154 	return len;
155 }
156