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