~ubuntu-branches/debian/jessie/openntpd/jessie

« back to all changes in this revision

Viewing changes to .pc/05-pid.patch/ntpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Ulises Vitulli
  • Date: 2010-06-08 16:52:01 UTC
  • Revision ID: james.westby@ubuntu.com-20100608165201-cnnnky72qvx05trp
Tags: 3.9p1+debian-4
* New maintainer (Closes: #543854).
* The 'say-aaaaaaaaaaahh' upload.
* Apply a pidfile patch, upstream doesn't like the idea of pidfiles, but
  sometimes they are useful for quick monitoring (Closes: #354825).
* Avoid stripping by default on their own (Closes: #437691).
* Dies if no peer servername is invalid, and logs badpeers through CRITICAL
  syslog. Thanks SergeyBKirpichev (Closes: #456661).
* Depend on $network at init start and do not go through reloading if there
  is no listening interface declared. Thanks SergeyBKirpichev
  (Closes: #495528, #507586, #529984).
* Explicity set default config file (Closes: #570253).
* Enhance ntpd.conf manpage to verbosely remember we don't listen to any 
  by default (Closes: #575705).
* Switch to 3.0 source format, drop dependency on quilt.
* Use hardening-include to handle gcc Hardening features.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $OpenBSD: ntpd.c,v 1.40 2005/09/06 21:27:10 wvdputte 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 MIND, USE, DATA OR PROFITS, WHETHER
 
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
17
 */
 
18
 
 
19
#include "includes.h"
 
20
 
 
21
RCSID("$Release: OpenNTPD "OPENNTPD_VERSION" $");
 
22
 
 
23
#include <sys/types.h>
 
24
#include <sys/socket.h>
 
25
#include <sys/wait.h>
 
26
#include <netinet/in.h>
 
27
#include <errno.h>
 
28
#ifdef HAVE_POLL_H
 
29
# include <poll.h>
 
30
#endif
 
31
#include <pwd.h>
 
32
#include <resolv.h>
 
33
#include <signal.h>
 
34
#include <stdio.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
#include <unistd.h>
 
38
 
 
39
#include "ntpd.h"
 
40
 
 
41
void            sighdlr(int);
 
42
__dead void     usage(void);
 
43
int             main(int, char *[]);
 
44
int             check_child(pid_t, const char *);
 
45
int             dispatch_imsg(struct ntpd_conf *);
 
46
int             ntpd_adjtime(double);
 
47
void            ntpd_settime(double);
 
48
 
 
49
volatile sig_atomic_t    quit = 0;
 
50
volatile sig_atomic_t    reconfig = 0;
 
51
volatile sig_atomic_t    sigchld = 0;
 
52
struct imsgbuf          *ibuf;
 
53
 
 
54
void
 
55
sighdlr(int sig)
 
56
{
 
57
        switch (sig) {
 
58
        case SIGTERM:
 
59
        case SIGINT:
 
60
                quit = 1;
 
61
                break;
 
62
        case SIGCHLD:
 
63
                sigchld = 1;
 
64
                break;
 
65
        case SIGHUP:
 
66
                reconfig = 1;
 
67
                break;
 
68
        }
 
69
}
 
70
 
 
71
__dead void
 
72
usage(void)
 
73
{
 
74
        extern char *__progname;
 
75
 
 
76
        fprintf(stderr, "usage: %s [-dSs] [-f file]\n", __progname);
 
77
        exit(1);
 
78
}
 
79
 
 
80
#define POLL_MAX                8
 
81
#define PFD_PIPE                0
 
82
 
 
83
int
 
84
main(int argc, char *argv[])
 
85
{
 
86
        struct ntpd_conf         conf;
 
87
        struct pollfd            pfd[POLL_MAX];
 
88
        pid_t                    chld_pid = 0, pid;
 
89
        const char              *conffile;
 
90
        int                      ch, nfds, timeout = INFTIM;
 
91
        int                      pipe_chld[2];
 
92
        extern char             *__progname;
 
93
 
 
94
        __progname = _compat_get_progname(argv[0]);
 
95
 
 
96
        conffile = CONFFILE;
 
97
 
 
98
        bzero(&conf, sizeof(conf));
 
99
 
 
100
        log_init(1);            /* log to stderr until daemonized */
 
101
        res_init();             /* XXX */
 
102
 
 
103
        while ((ch = getopt(argc, argv, "df:sS")) != -1) {
 
104
                switch (ch) {
 
105
                case 'd':
 
106
                        conf.debug = 1;
 
107
                        break;
 
108
                case 'f':
 
109
                        conffile = optarg;
 
110
                        break;
 
111
                case 's':
 
112
                        conf.settime = 1;
 
113
                        break;
 
114
                case 'S':
 
115
                        conf.settime = 0;
 
116
                        break;
 
117
                default:
 
118
                        usage();
 
119
                        /* NOTREACHED */
 
120
                }
 
121
        }
 
122
 
 
123
        if (parse_config(conffile, &conf))
 
124
                exit(1);
 
125
 
 
126
        if (geteuid()) {
 
127
                fprintf(stderr, "ntpd: need root privileges\n");
 
128
                exit(1);
 
129
        }
 
130
 
 
131
        if (getpwnam(NTPD_USER) == NULL) {
 
132
                fprintf(stderr, "ntpd: unknown user %s\n", NTPD_USER);
 
133
                exit(1);
 
134
        }
 
135
        endpwent();
 
136
 
 
137
#ifndef HAVE_ARC4RANDOM
 
138
        seed_rng();
 
139
#endif
 
140
 
 
141
        if (!conf.settime) {
 
142
                log_init(conf.debug);
 
143
                if (!conf.debug)
 
144
                        if (daemon(1, 0))
 
145
                                fatal("daemon");
 
146
        } else
 
147
                timeout = SETTIME_TIMEOUT * 1000;
 
148
 
 
149
        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
 
150
                fatal("socketpair");
 
151
 
 
152
        /* fork child process */
 
153
        chld_pid = ntp_main(pipe_chld, &conf);
 
154
 
 
155
        setproctitle("[priv]");
 
156
 
 
157
        signal(SIGTERM, sighdlr);
 
158
        signal(SIGINT, sighdlr);
 
159
        signal(SIGCHLD, sighdlr);
 
160
        signal(SIGHUP, sighdlr);
 
161
 
 
162
        close(pipe_chld[1]);
 
163
 
 
164
        if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
 
165
                fatal(NULL);
 
166
        imsg_init(ibuf, pipe_chld[0]);
 
167
 
 
168
        while (quit == 0) {
 
169
                pfd[PFD_PIPE].fd = ibuf->fd;
 
170
                pfd[PFD_PIPE].events = POLLIN;
 
171
                if (ibuf->w.queued)
 
172
                        pfd[PFD_PIPE].events |= POLLOUT;
 
173
 
 
174
                if ((nfds = poll(pfd, 1, timeout)) == -1)
 
175
                        if (errno != EINTR) {
 
176
                                log_warn("poll error");
 
177
                                quit = 1;
 
178
                        }
 
179
 
 
180
                if (nfds == 0 && conf.settime) {
 
181
                        conf.settime = 0;
 
182
                        timeout = INFTIM;
 
183
                        log_init(conf.debug);
 
184
                        log_debug("no reply received in time, skipping initial "
 
185
                            "time setting");
 
186
                        if (!conf.debug)
 
187
                                if (daemon(1, 0))
 
188
                                        fatal("daemon");
 
189
                }
 
190
 
 
191
                if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
 
192
                        if (msgbuf_write(&ibuf->w) < 0) {
 
193
                                log_warn("pipe write error (to child)");
 
194
                                quit = 1;
 
195
                        }
 
196
 
 
197
                if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
 
198
                        nfds--;
 
199
                        if (dispatch_imsg(&conf) == -1)
 
200
                                quit = 1;
 
201
                }
 
202
 
 
203
                if (sigchld) {
 
204
                        if (check_child(chld_pid, "child")) {
 
205
                                quit = 1;
 
206
                                chld_pid = 0;
 
207
                        }
 
208
                        sigchld = 0;
 
209
                }
 
210
 
 
211
        }
 
212
 
 
213
        signal(SIGCHLD, SIG_DFL);
 
214
 
 
215
        if (chld_pid)
 
216
                kill(chld_pid, SIGTERM);
 
217
 
 
218
        do {
 
219
                if ((pid = wait(NULL)) == -1 &&
 
220
                    errno != EINTR && errno != ECHILD)
 
221
                        fatal("wait");
 
222
        } while (pid != -1 || (pid == -1 && errno == EINTR));
 
223
 
 
224
        msgbuf_clear(&ibuf->w);
 
225
        free(ibuf);
 
226
        log_info("Terminating");
 
227
        return (0);
 
228
}
 
229
 
 
230
int
 
231
check_child(pid_t pid, const char *pname)
 
232
{
 
233
        int      status, sig;
 
234
        char    *signame;
 
235
 
 
236
        if (waitpid(pid, &status, WNOHANG) > 0) {
 
237
                if (WIFEXITED(status)) {
 
238
                        log_warnx("Lost child: %s exited", pname);
 
239
                        return (1);
 
240
                }
 
241
                if (WIFSIGNALED(status)) {
 
242
                        sig = WTERMSIG(status);
 
243
                        signame = strsignal(sig) ? strsignal(sig) : "unknown";
 
244
                        log_warnx("Lost child: %s terminated; signal %d (%s)",
 
245
                            pname, sig, signame);
 
246
                        return (1);
 
247
                }
 
248
        }
 
249
 
 
250
        return (0);
 
251
}
 
252
 
 
253
int
 
254
dispatch_imsg(struct ntpd_conf *conf)
 
255
{
 
256
        struct imsg              imsg;
 
257
        int                      n, cnt;
 
258
        double                   d;
 
259
        char                    *name;
 
260
        struct ntp_addr         *h, *hn;
 
261
        struct buf              *buf;
 
262
 
 
263
        if ((n = imsg_read(ibuf)) == -1)
 
264
                return (-1);
 
265
 
 
266
        if (n == 0) {   /* connection closed */
 
267
                log_warnx("dispatch_imsg in main: pipe closed");
 
268
                return (-1);
 
269
        }
 
270
 
 
271
        for (;;) {
 
272
                if ((n = imsg_get(ibuf, &imsg)) == -1)
 
273
                        return (-1);
 
274
 
 
275
                if (n == 0)
 
276
                        break;
 
277
 
 
278
                switch (imsg.hdr.type) {
 
279
                case IMSG_ADJTIME:
 
280
                        if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
 
281
                                fatalx("invalid IMSG_ADJTIME received");
 
282
                        memcpy(&d, imsg.data, sizeof(d));
 
283
                        n = ntpd_adjtime(d);
 
284
                        imsg_compose(ibuf, IMSG_ADJTIME, 0, 0, &n, sizeof(n));
 
285
                        break;
 
286
                case IMSG_SETTIME:
 
287
                        if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
 
288
                                fatalx("invalid IMSG_SETTIME received");
 
289
                        if (!conf->settime)
 
290
                                break;
 
291
                        log_init(conf->debug);
 
292
                        memcpy(&d, imsg.data, sizeof(d));
 
293
                        ntpd_settime(d);
 
294
                        /* daemonize now */
 
295
                        if (!conf->debug)
 
296
                                if (daemon(1, 0))
 
297
                                        fatal("daemon");
 
298
                        conf->settime = 0;
 
299
                        break;
 
300
                case IMSG_HOST_DNS:
 
301
                        name = imsg.data;
 
302
                        if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
 
303
                                fatalx("invalid IMSG_HOST_DNS received");
 
304
                        imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
 
305
                        if (name[imsg.hdr.len] != '\0' ||
 
306
                            strlen(name) != imsg.hdr.len)
 
307
                                fatalx("invalid IMSG_HOST_DNS received");
 
308
                        cnt = host_dns(name, &hn);
 
309
                        buf = imsg_create(ibuf, IMSG_HOST_DNS,
 
310
                            imsg.hdr.peerid, 0,
 
311
                            cnt * sizeof(struct sockaddr_storage));
 
312
                        if (buf == NULL)
 
313
                                break;
 
314
                        if (cnt > 0)
 
315
                                for (h = hn; h != NULL; h = h->next)
 
316
                                        imsg_add(buf, &h->ss, sizeof(h->ss));
 
317
 
 
318
                        imsg_close(ibuf, buf);
 
319
                        break;
 
320
                default:
 
321
                        break;
 
322
                }
 
323
                imsg_free(&imsg);
 
324
        }
 
325
        return (0);
 
326
}
 
327
 
 
328
int
 
329
ntpd_adjtime(double d)
 
330
{
 
331
        struct timeval  tv, olddelta;
 
332
        int             synced = 0;
 
333
        static int      firstadj = 1;
 
334
 
 
335
        if (d >= (double)LOG_NEGLIGEE / 1000 ||
 
336
            d <= -1 * (double)LOG_NEGLIGEE / 1000)
 
337
                log_info("adjusting local clock by %fs", d);
 
338
        else
 
339
                log_debug("adjusting local clock by %fs", d);
 
340
        d_to_tv(d, &tv);
 
341
        if (adjtime(&tv, &olddelta) == -1)
 
342
                log_warn("adjtime failed");
 
343
        else if (!firstadj && olddelta.tv_sec == 0 && olddelta.tv_usec == 0)
 
344
                synced = 1;
 
345
        firstadj = 0;
 
346
        return (synced);
 
347
}
 
348
 
 
349
void
 
350
ntpd_settime(double d)
 
351
{
 
352
        struct timeval  tv, curtime;
 
353
        char            buf[80];
 
354
        time_t          tval;
 
355
 
 
356
        /* if the offset is small, don't call settimeofday */
 
357
        if (d < SETTIME_MIN_OFFSET && d > -SETTIME_MIN_OFFSET)
 
358
                return;
 
359
 
 
360
        if (gettimeofday(&curtime, NULL) == -1) {
 
361
                log_warn("gettimeofday");
 
362
                return;
 
363
        }
 
364
        d_to_tv(d, &tv);
 
365
        curtime.tv_usec += tv.tv_usec + 1000000;
 
366
        curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
 
367
        curtime.tv_usec %= 1000000;
 
368
 
 
369
        if (settimeofday(&curtime, NULL) == -1) {
 
370
                log_warn("settimeofday");
 
371
                return;
 
372
        }
 
373
        tval = curtime.tv_sec;
 
374
        strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
 
375
            localtime(&tval));
 
376
        log_info("set local clock to %s (offset %fs)", buf, d);
 
377
}