1 /* $OpenBSD: config.c,v 1.19 2006/05/27 17:01:07 henning 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 #include <arpa/nameser.h> 25 26 #include <errno.h> 27 #include <resolv.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 32 #include "ntpd.h" 33 34 struct ntp_addr *host_v4(const char *); 35 struct ntp_addr *host_v6(const char *); 36 37 static u_int32_t maxid = 0; 38 39 int 40 host(const char *s, struct ntp_addr **hn) 41 { 42 struct ntp_addr *h = NULL; 43 44 if (!strcmp(s, "*")) 45 if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL) 46 fatal(NULL); 47 48 /* IPv4 address? */ 49 if (h == NULL) 50 h = host_v4(s); 51 52 /* IPv6 address? */ 53 if (h == NULL) 54 h = host_v6(s); 55 56 if (h == NULL) 57 return (0); 58 59 *hn = h; 60 61 return (1); 62 } 63 64 struct ntp_addr * 65 host_v4(const char *s) 66 { 67 struct in_addr ina; 68 struct sockaddr_in *sa_in; 69 struct ntp_addr *h; 70 71 bzero(&ina, sizeof(struct in_addr)); 72 if (inet_pton(AF_INET, s, &ina) != 1) 73 return (NULL); 74 75 if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL) 76 fatal(NULL); 77 sa_in = (struct sockaddr_in *)&h->ss; 78 sa_in->sin_len = sizeof(struct sockaddr_in); 79 sa_in->sin_family = AF_INET; 80 sa_in->sin_addr.s_addr = ina.s_addr; 81 82 return (h); 83 } 84 85 struct ntp_addr * 86 host_v6(const char *s) 87 { 88 struct addrinfo hints, *res; 89 struct sockaddr_in6 *sa_in6; 90 struct ntp_addr *h = NULL; 91 92 bzero(&hints, sizeof(hints)); 93 hints.ai_family = AF_INET6; 94 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 95 hints.ai_flags = AI_NUMERICHOST; 96 if (getaddrinfo(s, "0", &hints, &res) == 0) { 97 if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL) 98 fatal(NULL); 99 sa_in6 = (struct sockaddr_in6 *)&h->ss; 100 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 101 sa_in6->sin6_family = AF_INET6; 102 memcpy(&sa_in6->sin6_addr, 103 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 104 sizeof(sa_in6->sin6_addr)); 105 sa_in6->sin6_scope_id = 106 ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 107 108 freeaddrinfo(res); 109 } 110 111 return (h); 112 } 113 114 int 115 host_dns(const char *s, struct ntp_addr **hn) 116 { 117 struct addrinfo hints, *res0, *res; 118 int error, cnt = 0; 119 struct sockaddr_in *sa_in; 120 struct sockaddr_in6 *sa_in6; 121 struct ntp_addr *h, *hh = NULL; 122 123 bzero(&hints, sizeof(hints)); 124 hints.ai_family = PF_UNSPEC; 125 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 126 error = getaddrinfo(s, NULL, &hints, &res0); 127 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 128 return (0); 129 if (error) { 130 log_warnx("could not parse \"%s\": %s", s, 131 gai_strerror(error)); 132 return (-1); 133 } 134 135 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) { 136 if (res->ai_family != AF_INET && 137 res->ai_family != AF_INET6) 138 continue; 139 if ((h = calloc(1, sizeof(struct ntp_addr))) == NULL) 140 fatal(NULL); 141 h->ss.ss_family = res->ai_family; 142 if (res->ai_family == AF_INET) { 143 sa_in = (struct sockaddr_in *)&h->ss; 144 sa_in->sin_len = sizeof(struct sockaddr_in); 145 sa_in->sin_addr.s_addr = ((struct sockaddr_in *) 146 res->ai_addr)->sin_addr.s_addr; 147 } else { 148 sa_in6 = (struct sockaddr_in6 *)&h->ss; 149 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 150 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *) 151 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 152 } 153 154 h->next = hh; 155 hh = h; 156 cnt++; 157 } 158 freeaddrinfo(res0); 159 160 *hn = hh; 161 return (cnt); 162 } 163 164 struct ntp_peer * 165 new_peer(void) 166 { 167 struct ntp_peer *p; 168 169 if ((p = calloc(1, sizeof(struct ntp_peer))) == NULL) 170 fatal("new_peer calloc"); 171 p->id = ++maxid; 172 173 return (p); 174 } 175 176 struct ntp_conf_sensor * 177 new_sensor(char *device) 178 { 179 struct ntp_conf_sensor *s; 180 181 if ((s = calloc(1, sizeof(struct ntp_conf_sensor))) == NULL) 182 fatal("new_sensor calloc"); 183 if ((s->device = strdup(device)) == NULL) 184 fatal("new_sensor strdup"); 185 186 return (s); 187 } 188