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