1 /* $OpenBSD: server.c,v 1.41 2015/02/10 11:46:39 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2004 Alexander Guy <alexander@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 MIND, USE, DATA OR PROFITS, WHETHER 16 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 17 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/ioctl.h> 22 #include <sys/socket.h> 23 #include <net/if.h> 24 #include <errno.h> 25 #include <ifaddrs.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include "ntpd.h" 31 32 int 33 setup_listeners(struct servent *se, struct ntpd_conf *lconf, u_int *cnt) 34 { 35 struct listen_addr *la, *nla, *lap; 36 struct ifaddrs *ifa, *ifap; 37 struct sockaddr *sa; 38 struct ifreq ifr; 39 u_int8_t *a6; 40 size_t sa6len = sizeof(struct in6_addr); 41 u_int new_cnt = 0; 42 int tos = IPTOS_LOWDELAY, rdomain, fd; 43 44 TAILQ_FOREACH(lap, &lconf->listen_addrs, entry) { 45 switch (lap->sa.ss_family) { 46 case AF_UNSPEC: 47 if (getifaddrs(&ifa) == -1) 48 fatal("getifaddrs"); 49 50 for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { 51 sa = ifap->ifa_addr; 52 if (sa == NULL || 53 (sa->sa_family != AF_INET && 54 sa->sa_family != AF_INET6)) 55 continue; 56 if (SA_LEN(sa) == 0) 57 continue; 58 59 strlcpy(ifr.ifr_name, ifap->ifa_name, 60 sizeof(ifr.ifr_name)); 61 62 fd = socket(AF_INET, SOCK_DGRAM, 0); 63 if (ioctl(fd, SIOCGIFRDOMAIN, 64 (caddr_t)&ifr) == -1) 65 rdomain = 0; 66 else 67 rdomain = ifr.ifr_rdomainid; 68 close(fd); 69 70 if (lap->rtable != -1 && rdomain != lap->rtable) 71 continue; 72 73 if (sa->sa_family == AF_INET && 74 ((struct sockaddr_in *)sa)->sin_addr.s_addr == 75 INADDR_ANY) 76 continue; 77 78 if (sa->sa_family == AF_INET6) { 79 a6 = ((struct sockaddr_in6 *)sa)-> 80 sin6_addr.s6_addr; 81 if (memcmp(a6, &in6addr_any, sa6len) == 0) 82 continue; 83 } 84 85 if ((la = calloc(1, sizeof(struct listen_addr))) == 86 NULL) 87 fatal("setup_listeners calloc"); 88 89 memcpy(&la->sa, sa, SA_LEN(sa)); 90 la->rtable = rdomain; 91 92 TAILQ_INSERT_TAIL(&lconf->listen_addrs, la, entry); 93 } 94 95 freeifaddrs(ifa); 96 default: 97 continue; 98 } 99 } 100 101 102 for (la = TAILQ_FIRST(&lconf->listen_addrs); la; ) { 103 switch (la->sa.ss_family) { 104 case AF_INET: 105 if (((struct sockaddr_in *)&la->sa)->sin_port == 0) 106 ((struct sockaddr_in *)&la->sa)->sin_port = 107 se->s_port; 108 break; 109 case AF_INET6: 110 if (((struct sockaddr_in6 *)&la->sa)->sin6_port == 0) 111 ((struct sockaddr_in6 *)&la->sa)->sin6_port = 112 se->s_port; 113 break; 114 case AF_UNSPEC: 115 nla = TAILQ_NEXT(la, entry); 116 TAILQ_REMOVE(&lconf->listen_addrs, la, entry); 117 free(la); 118 la = nla; 119 continue; 120 default: 121 fatalx("king bula sez: af borked"); 122 } 123 124 log_info("listening on %s %s", 125 log_sockaddr((struct sockaddr *)&la->sa), 126 print_rtable(la->rtable)); 127 128 if ((la->fd = socket(la->sa.ss_family, SOCK_DGRAM, 0)) == -1) 129 fatal("socket"); 130 131 if (la->sa.ss_family == AF_INET && setsockopt(la->fd, 132 IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) 133 log_warn("setsockopt IPTOS_LOWDELAY"); 134 135 if (la->rtable != -1 && 136 setsockopt(la->fd, SOL_SOCKET, SO_RTABLE, &la->rtable, 137 sizeof(la->rtable)) == -1) 138 fatal("setup_listeners setsockopt SO_RTABLE"); 139 140 if (bind(la->fd, (struct sockaddr *)&la->sa, 141 SA_LEN((struct sockaddr *)&la->sa)) == -1) { 142 log_warn("bind on %s failed, skipping", 143 log_sockaddr((struct sockaddr *)&la->sa)); 144 close(la->fd); 145 nla = TAILQ_NEXT(la, entry); 146 TAILQ_REMOVE(&lconf->listen_addrs, la, entry); 147 free(la); 148 la = nla; 149 continue; 150 } 151 new_cnt++; 152 la = TAILQ_NEXT(la, entry); 153 } 154 155 *cnt = new_cnt; 156 157 return (0); 158 } 159 160 int 161 server_dispatch(int fd, struct ntpd_conf *lconf) 162 { 163 ssize_t size; 164 double rectime; 165 struct sockaddr_storage fsa; 166 socklen_t fsa_len; 167 struct ntp_msg query, reply; 168 char buf[NTP_MSGSIZE]; 169 170 fsa_len = sizeof(fsa); 171 if ((size = recvfrom(fd, &buf, sizeof(buf), 0, 172 (struct sockaddr *)&fsa, &fsa_len)) == -1) { 173 if (errno == EHOSTUNREACH || errno == EHOSTDOWN || 174 errno == ENETUNREACH || errno == ENETDOWN) { 175 log_warn("recvfrom %s", 176 log_sockaddr((struct sockaddr *)&fsa)); 177 return (0); 178 } else 179 fatal("recvfrom"); 180 } 181 182 rectime = gettime_corrected(); 183 184 if (ntp_getmsg((struct sockaddr *)&fsa, buf, size, &query) == -1) 185 return (0); 186 187 bzero(&reply, sizeof(reply)); 188 if (lconf->status.synced) 189 reply.status = lconf->status.leap; 190 else 191 reply.status = LI_ALARM; 192 reply.status |= (query.status & VERSIONMASK); 193 if ((query.status & MODEMASK) == MODE_CLIENT) 194 reply.status |= MODE_SERVER; 195 else if ((query.status & MODEMASK) == MODE_SYM_ACT) 196 reply.status |= MODE_SYM_PAS; 197 else /* ignore packets of different type (e.g. bcast) */ 198 return (0); 199 200 reply.stratum = lconf->status.stratum; 201 reply.ppoll = query.ppoll; 202 reply.precision = lconf->status.precision; 203 reply.rectime = d_to_lfp(rectime); 204 reply.reftime = d_to_lfp(lconf->status.reftime); 205 reply.xmttime = d_to_lfp(gettime_corrected()); 206 reply.orgtime = query.xmttime; 207 reply.rootdelay = d_to_sfp(lconf->status.rootdelay); 208 reply.refid = lconf->status.refid; 209 210 ntp_sendmsg(fd, (struct sockaddr *)&fsa, &reply); 211 return (0); 212 } 213