xref: /openbsd/usr.sbin/ntpd/config.c (revision a257dd04)
1 /*	$OpenBSD: config.c,v 1.28 2015/10/12 06:50:08 reyk Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/stat.h>
22 
23 #include <netinet/in.h>
24 
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "ntpd.h"
31 
32 struct ntp_addr	*host_v4(const char *);
33 struct ntp_addr	*host_v6(const char *);
34 
35 static u_int32_t		 maxid = 0;
36 static u_int32_t		 constraint_maxid = 0;
37 
38 void
39 host(const char *s, struct ntp_addr **hn)
40 {
41 	struct ntp_addr	*h = NULL;
42 
43 	if (!strcmp(s, "*"))
44 		if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL)
45 			fatal(NULL);
46 
47 	/* IPv4 address? */
48 	if (h == NULL)
49 		h = host_v4(s);
50 
51 	/* IPv6 address? */
52 	if (h == NULL)
53 		h = host_v6(s);
54 
55 	if (h == NULL)
56 		return;
57 
58 	*hn = h;
59 }
60 
61 struct ntp_addr	*
62 host_v4(const char *s)
63 {
64 	struct in_addr		 ina;
65 	struct sockaddr_in	*sa_in;
66 	struct ntp_addr		*h;
67 
68 	memset(&ina, 0, sizeof(struct in_addr));
69 	if (inet_pton(AF_INET, s, &ina) != 1)
70 		return (NULL);
71 
72 	if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL)
73 		fatal(NULL);
74 	sa_in = (struct sockaddr_in *)&h->ss;
75 	sa_in->sin_len = sizeof(struct sockaddr_in);
76 	sa_in->sin_family = AF_INET;
77 	sa_in->sin_addr.s_addr = ina.s_addr;
78 
79 	return (h);
80 }
81 
82 struct ntp_addr	*
83 host_v6(const char *s)
84 {
85 	struct addrinfo		 hints, *res;
86 	struct sockaddr_in6	*sa_in6;
87 	struct ntp_addr		*h = NULL;
88 
89 	memset(&hints, 0, sizeof(hints));
90 	hints.ai_family = AF_INET6;
91 	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
92 	hints.ai_flags = AI_NUMERICHOST;
93 	if (getaddrinfo(s, "0", &hints, &res) == 0) {
94 		if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL)
95 			fatal(NULL);
96 		sa_in6 = (struct sockaddr_in6 *)&h->ss;
97 		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
98 		sa_in6->sin6_family = AF_INET6;
99 		memcpy(&sa_in6->sin6_addr,
100 		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
101 		    sizeof(sa_in6->sin6_addr));
102 		sa_in6->sin6_scope_id =
103 		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
104 
105 		freeaddrinfo(res);
106 	}
107 
108 	return (h);
109 }
110 
111 void
112 host_dns_free(struct ntp_addr *hn)
113 {
114 	struct ntp_addr	*h = hn, *tmp;
115 	while (h) {
116 		tmp = h;
117 		h = h->next;
118 		free(tmp);
119 	}
120 }
121 
122 int
123 host_dns(const char *s, struct ntp_addr **hn)
124 {
125 	struct addrinfo		 hints, *res0, *res;
126 	int			 error, cnt = 0;
127 	struct sockaddr_in	*sa_in;
128 	struct sockaddr_in6	*sa_in6;
129 	struct ntp_addr		*h, *hh = NULL;
130 
131 	memset(&hints, 0, sizeof(hints));
132 	hints.ai_family = PF_UNSPEC;
133 	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
134 	/* ntpd MUST NOT use AI_ADDRCONFIG here */
135 	error = getaddrinfo(s, NULL, &hints, &res0);
136 	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
137 			return (0);
138 	if (error) {
139 		log_warnx("could not parse \"%s\": %s", s,
140 		    gai_strerror(error));
141 		return (-1);
142 	}
143 
144 	for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
145 		if (res->ai_family != AF_INET &&
146 		    res->ai_family != AF_INET6)
147 			continue;
148 		if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL)
149 			fatal(NULL);
150 		h->ss.ss_family = res->ai_family;
151 		if (res->ai_family == AF_INET) {
152 			sa_in = (struct sockaddr_in *)&h->ss;
153 			sa_in->sin_len = sizeof(struct sockaddr_in);
154 			sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
155 			    res->ai_addr)->sin_addr.s_addr;
156 		} else {
157 			sa_in6 = (struct sockaddr_in6 *)&h->ss;
158 			sa_in6->sin6_len = sizeof(struct sockaddr_in6);
159 			memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
160 			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
161 		}
162 
163 		h->next = hh;
164 		hh = h;
165 		cnt++;
166 	}
167 	freeaddrinfo(res0);
168 
169 	*hn = hh;
170 	return (cnt);
171 }
172 
173 struct ntp_peer *
174 new_peer(void)
175 {
176 	struct ntp_peer	*p;
177 
178 	if ((p = calloc(1, sizeof(struct ntp_peer))) == NULL)
179 		fatal("new_peer calloc");
180 	p->id = ++maxid;
181 
182 	return (p);
183 }
184 
185 struct ntp_conf_sensor *
186 new_sensor(char *device)
187 {
188 	struct ntp_conf_sensor	*s;
189 
190 	if ((s = calloc(1, sizeof(struct ntp_conf_sensor))) == NULL)
191 		fatal("new_sensor calloc");
192 	if ((s->device = strdup(device)) == NULL)
193 		fatal("new_sensor strdup");
194 
195 	return (s);
196 }
197 
198 struct constraint *
199 new_constraint(void)
200 {
201 	struct constraint	*p;
202 
203 	if ((p = calloc(1, sizeof(struct constraint))) == NULL)
204 		fatal("new_constraint calloc");
205 	p->id = ++constraint_maxid;
206 	p->fd = -1;
207 
208 	return (p);
209 }
210 
211