GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ntpd/server.c Lines: 0 99 0.0 %
Date: 2017-11-13 Branches: 0 76 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: server.c,v 1.44 2016/09/03 11:52:06 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 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/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 if_data		*ifd;
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 = 0;
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 || SA_LEN(sa) == 0)
53
					continue;
54
				if (sa->sa_family == AF_LINK) {
55
					ifd = ifap->ifa_data;
56
					rdomain = ifd->ifi_rdomain;
57
				}
58
				if (sa->sa_family != AF_INET &&
59
				    sa->sa_family != AF_INET6)
60
					continue;
61
				if (lap->rtable != -1 && rdomain != lap->rtable)
62
					continue;
63
64
				if (sa->sa_family == AF_INET &&
65
				    ((struct sockaddr_in *)sa)->sin_addr.s_addr ==
66
				    INADDR_ANY)
67
					continue;
68
69
				if (sa->sa_family == AF_INET6) {
70
					a6 = ((struct sockaddr_in6 *)sa)->
71
					    sin6_addr.s6_addr;
72
					if (memcmp(a6, &in6addr_any, sa6len) == 0)
73
						continue;
74
				}
75
76
				if ((la = calloc(1, sizeof(struct listen_addr))) ==
77
				    NULL)
78
					fatal("setup_listeners calloc");
79
80
				memcpy(&la->sa, sa, SA_LEN(sa));
81
				la->rtable = rdomain;
82
83
				TAILQ_INSERT_TAIL(&lconf->listen_addrs, la, entry);
84
			}
85
86
			freeifaddrs(ifa);
87
		default:
88
			continue;
89
		}
90
	}
91
92
93
	for (la = TAILQ_FIRST(&lconf->listen_addrs); la; ) {
94
		switch (la->sa.ss_family) {
95
		case AF_INET:
96
			if (((struct sockaddr_in *)&la->sa)->sin_port == 0)
97
				((struct sockaddr_in *)&la->sa)->sin_port =
98
				    se->s_port;
99
			break;
100
		case AF_INET6:
101
			if (((struct sockaddr_in6 *)&la->sa)->sin6_port == 0)
102
				((struct sockaddr_in6 *)&la->sa)->sin6_port =
103
				    se->s_port;
104
			break;
105
		case AF_UNSPEC:
106
			nla = TAILQ_NEXT(la, entry);
107
			TAILQ_REMOVE(&lconf->listen_addrs, la, entry);
108
			free(la);
109
			la = nla;
110
			continue;
111
		default:
112
			fatalx("king bula sez: af borked");
113
		}
114
115
		log_info("listening on %s %s",
116
		    log_sockaddr((struct sockaddr *)&la->sa),
117
		    print_rtable(la->rtable));
118
119
		if ((la->fd = socket(la->sa.ss_family, SOCK_DGRAM, 0)) == -1)
120
			fatal("socket");
121
122
		if (la->sa.ss_family == AF_INET && setsockopt(la->fd,
123
		    IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1)
124
			log_warn("setsockopt IPTOS_LOWDELAY");
125
126
		if (la->rtable != -1 &&
127
		    setsockopt(la->fd, SOL_SOCKET, SO_RTABLE, &la->rtable,
128
		    sizeof(la->rtable)) == -1)
129
			fatal("setup_listeners setsockopt SO_RTABLE");
130
131
		if (bind(la->fd, (struct sockaddr *)&la->sa,
132
		    SA_LEN((struct sockaddr *)&la->sa)) == -1) {
133
			log_warn("bind on %s failed, skipping",
134
			    log_sockaddr((struct sockaddr *)&la->sa));
135
			close(la->fd);
136
			nla = TAILQ_NEXT(la, entry);
137
			TAILQ_REMOVE(&lconf->listen_addrs, la, entry);
138
			free(la);
139
			la = nla;
140
			continue;
141
		}
142
		new_cnt++;
143
		la = TAILQ_NEXT(la, entry);
144
	}
145
146
	*cnt = new_cnt;
147
148
	return (0);
149
}
150
151
int
152
server_dispatch(int fd, struct ntpd_conf *lconf)
153
{
154
	ssize_t			 size;
155
	double			 rectime;
156
	struct sockaddr_storage	 fsa;
157
	socklen_t		 fsa_len;
158
	struct ntp_msg		 query, reply;
159
	char			 buf[NTP_MSGSIZE];
160
161
	fsa_len = sizeof(fsa);
162
	if ((size = recvfrom(fd, &buf, sizeof(buf), 0,
163
	    (struct sockaddr *)&fsa, &fsa_len)) == -1) {
164
		if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
165
		    errno == ENETUNREACH || errno == ENETDOWN) {
166
			log_warn("recvfrom %s",
167
			    log_sockaddr((struct sockaddr *)&fsa));
168
			return (0);
169
		} else
170
			fatal("recvfrom");
171
	}
172
173
	rectime = gettime_corrected();
174
175
	if (ntp_getmsg((struct sockaddr *)&fsa, buf, size, &query) == -1)
176
		return (0);
177
178
	memset(&reply, 0, sizeof(reply));
179
	if (lconf->status.synced)
180
		reply.status = lconf->status.leap;
181
	else
182
		reply.status = LI_ALARM;
183
	reply.status |= (query.status & VERSIONMASK);
184
	if ((query.status & MODEMASK) == MODE_CLIENT)
185
		reply.status |= MODE_SERVER;
186
	else if ((query.status & MODEMASK) == MODE_SYM_ACT)
187
		reply.status |= MODE_SYM_PAS;
188
	else /* ignore packets of different type (e.g. bcast) */
189
		return (0);
190
191
	reply.stratum =	lconf->status.stratum;
192
	reply.ppoll = query.ppoll;
193
	reply.precision = lconf->status.precision;
194
	reply.rectime = d_to_lfp(rectime);
195
	reply.reftime = d_to_lfp(lconf->status.reftime);
196
	reply.xmttime = d_to_lfp(gettime_corrected());
197
	reply.orgtime = query.xmttime;
198
	reply.rootdelay = d_to_sfp(lconf->status.rootdelay);
199
	reply.refid = lconf->status.refid;
200
201
	ntp_sendmsg(fd, (struct sockaddr *)&fsa, &reply);
202
	return (0);
203
}