~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to sntp/socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  Copyright (C) 1996, 2000 N.M. Maclaren
 
2
    Copyright (C) 1996, 2000 The University of Cambridge
 
3
 
 
4
This includes all of the code needed to handle Berkeley sockets.  It is way
 
5
outside current POSIX, unfortunately.  It should be easy to convert to a system
 
6
that uses another mechanism.  It does not currently use socklen_t, because
 
7
the only system that the author uses that has it is Linux. */
 
8
 
 
9
 
 
10
 
 
11
#include "header.h"
 
12
#include "internet.h"
 
13
#include <fcntl.h>
 
14
 
 
15
#define SOCKET
 
16
#include "kludges.h"
 
17
#undef SOCKET
 
18
 
 
19
 
 
20
 
 
21
/* The code needs to set some variables during the open, for use by later
 
22
functions. */
 
23
 
 
24
static int initial = 1,
 
25
    descriptors[MAX_SOCKETS];
 
26
 
 
27
#ifdef HAVE_IPV6
 
28
static struct sockaddr_storage here[MAX_SOCKETS], there[MAX_SOCKETS];
 
29
#else
 
30
static struct sockaddr_in here[MAX_SOCKETS], there[MAX_SOCKETS];
 
31
#endif
 
32
 
 
33
void display_in_hex(const void *, int);
 
34
#ifdef HAVE_IPV6
 
35
void display_sock_in_hex(struct sockaddr_storage *);
 
36
#else
 
37
void display_sock_in_hex (struct sockaddr_in *);
 
38
#endif
 
39
 
 
40
/* There needs to be some disgusting grobble for handling timeouts, that is
 
41
identical to the grobble in internet.c. */
 
42
 
 
43
static jmp_buf jump_buffer;
 
44
 
 
45
static void jump_handler (int sig) {
 
46
    longjmp(jump_buffer,1);
 
47
}
 
48
 
 
49
static void clear_alarm (void) {
 
50
    int k;
 
51
 
 
52
    k = errno;
 
53
    alarm(0);
 
54
    errno = 0;
 
55
    if (signal(SIGALRM,SIG_DFL) == SIG_ERR)
 
56
        fatal(1,"unable to reset signal handler",NULL);
 
57
    errno = k;
 
58
}
 
59
 
 
60
 
 
61
 
 
62
void display_in_hex (const void *data, int length) {
 
63
    int i;
 
64
 
 
65
    for (i = 0; i < length; ++i)
 
66
        fprintf(stderr,"%.2x",((const unsigned char *)data)[i]);
 
67
}
 
68
 
 
69
#ifdef HAVE_IPV6
 
70
 
 
71
void display_sock_in_hex (struct sockaddr_storage *sock) {
 
72
    int family;
 
73
    struct sockaddr_in *sin;
 
74
    struct sockaddr_in6 *sin6;
 
75
 
 
76
    family = sock->ss_family;
 
77
    switch(family) {
 
78
    case AF_INET:
 
79
        sin = (struct sockaddr_in *)sock;
 
80
        display_in_hex(&sin->sin_addr, sizeof(struct in_addr));
 
81
        fprintf(stderr,"/");
 
82
        display_in_hex(&sin->sin_port, 2);
 
83
        break;
 
84
    case AF_INET6:
 
85
        sin6 = (struct sockaddr_in6 *)sock;
 
86
        display_in_hex(&sin6->sin6_addr, sizeof(struct in6_addr));
 
87
        fprintf(stderr,"/");
 
88
        display_in_hex(&sin6->sin6_port, 2);
 
89
        break;
 
90
    }
 
91
}
 
92
 
 
93
#else
 
94
 
 
95
void display_sock_in_hex (struct sockaddr_in *sock) {
 
96
    int family, len;
 
97
    struct sockaddr_in *sin;
 
98
 
 
99
    family = sock->sin_family;
 
100
    switch(family) {
 
101
    case AF_INET:
 
102
        sin = (struct sockaddr_in *)sock;
 
103
        display_in_hex(&sin->sin_addr, sizeof(struct in_addr));
 
104
        fprintf(stderr,"/");
 
105
        display_in_hex(&sin->sin_port, 2);
 
106
        break;
 
107
    }
 
108
}
 
109
#endif
 
110
 
 
111
#ifdef HAVE_IPV6
 
112
 
 
113
void open_socket (int which, char *hostname, int timespan) {
 
114
 
 
115
/* Locate the specified NTP server, set up a couple of addresses and open a
 
116
socket. */
 
117
 
 
118
    int port, k, sl;
 
119
    struct sockaddr_storage address, anywhere, everywhere;
 
120
 
 
121
/* Initialise and find out the server and port number.  Note that the port
 
122
number is in network format. */
 
123
 
 
124
    if (initial)
 
125
        for (k = 0; k < MAX_SOCKETS; ++k)
 
126
            descriptors[k] = -1;
 
127
    initial = 0;
 
128
    if (which < 0 || which >= MAX_SOCKETS || descriptors[which] >= 0)
 
129
        fatal(0,"socket index out of range or already open",NULL);
 
130
    if (verbose > 2)
 
131
        fprintf(stderr,"Looking for the socket addresses\n");
 
132
    find_address(&address,&anywhere,&everywhere,&port,hostname,timespan);
 
133
    if (verbose > 2) {
 
134
        fprintf(stderr,"Internet address: address=");
 
135
        display_sock_in_hex(&address);
 
136
        fprintf(stderr," anywhere=");
 
137
        display_sock_in_hex(&anywhere);
 
138
        fprintf(stderr," everywhere=");
 
139
        display_sock_in_hex(&everywhere);
 
140
        fputc('\n',stderr);
 
141
    }
 
142
 
 
143
/* Set up our own and the target addresses.  Note that the target address will
 
144
be reset before use in server mode. */
 
145
 
 
146
    memset(&here[which], 0, sizeof(struct sockaddr_storage));
 
147
    here[which] = anywhere;
 
148
    if (!(operation == op_listen || operation == op_server))
 
149
        ((struct sockaddr_in6 *)&here[which])->sin6_port = 0;
 
150
    memset(&there[which], 0, sizeof(struct sockaddr_storage));
 
151
    there[which] = (operation == op_broadcast ? everywhere : address);
 
152
    if (verbose > 2) {
 
153
        fprintf(stderr,"Initial sockets: here=");
 
154
        display_sock_in_hex(&here[which]);
 
155
        fprintf(stderr," there=");
 
156
        display_sock_in_hex(&there[which]);
 
157
        fputc('\n',stderr);
 
158
    }
 
159
 
 
160
/* Allocate a local UDP socket and configure it. */
 
161
 
 
162
    switch(((struct sockaddr_in *)&there[which])->sin_family) {
 
163
    case AF_INET:
 
164
        sl = sizeof(struct sockaddr_in);
 
165
        break;
 
166
#ifdef HAVE_IPV6
 
167
    case AF_INET6:
 
168
        sl = sizeof(struct sockaddr_in6);
 
169
        break;
 
170
#endif
 
171
    default:
 
172
        sl = 0;
 
173
        break;
 
174
    }
 
175
    errno = 0;
 
176
    if ((descriptors[which] = socket(here[which].ss_family,SOCK_DGRAM,0)) < 0
 
177
        || bind(descriptors[which],(struct sockaddr *)&here[which], sl) < 0)
 
178
        fatal(1,"unable to allocate socket for NTP",NULL);
 
179
    if (operation == op_broadcast) {
 
180
        errno = 0;
 
181
        k = setsockopt(descriptors[which],SOL_SOCKET,SO_BROADCAST,
 
182
                (void *)&k,sizeof(k));
 
183
        if (k != 0) fatal(1,"unable to set permission to broadcast",NULL);
 
184
    }
 
185
}
 
186
 
 
187
#else
 
188
 
 
189
void open_socket (int which, char *hostname, int timespan) {
 
190
 
 
191
/* Locate the specified NTP server, set up a couple of addresses and open a
 
192
socket. */
 
193
 
 
194
    int port, k;
 
195
    struct in_addr address, anywhere, everywhere;
 
196
 
 
197
/* Initialise and find out the server and port number.  Note that the port
 
198
number is in network format. */
 
199
 
 
200
    if (initial) for (k = 0; k < MAX_SOCKETS; ++k) descriptors[k] = -1;
 
201
    initial = 0;
 
202
    if (which < 0 || which >= MAX_SOCKETS || descriptors[which] >= 0)
 
203
        fatal(0,"socket index out of range or already open",NULL);
 
204
    if (verbose > 2) fprintf(stderr,"Looking for the socket addresses\n");
 
205
    find_address(&address,&anywhere,&everywhere,&port,hostname,timespan);
 
206
    if (verbose > 2) {
 
207
        fprintf(stderr,"Internet address: address=");
 
208
        display_in_hex(&address,sizeof(struct in_addr));
 
209
        fprintf(stderr," anywhere=");
 
210
        display_in_hex(&anywhere,sizeof(struct in_addr));
 
211
        fprintf(stderr," everywhere=");
 
212
        display_in_hex(&everywhere,sizeof(struct in_addr));
 
213
        fputc('\n',stderr);
 
214
    }
 
215
 
 
216
/* Set up our own and the target addresses.  Note that the target address will
 
217
be reset before use in server mode. */
 
218
 
 
219
    memset(&here[which],0,sizeof(struct sockaddr_in));
 
220
    here[which].sin_family = AF_INET;
 
221
    here[which].sin_port =
 
222
        (operation == op_listen || operation == op_server ? port : 0);
 
223
    here[which].sin_addr = anywhere;
 
224
    memset(&there[which],0,sizeof(struct sockaddr_in));
 
225
    there[which].sin_family = AF_INET;
 
226
    there[which].sin_port = port;
 
227
    there[which].sin_addr = (operation == op_broadcast ? everywhere : address);
 
228
    if (verbose > 2) {
 
229
        fprintf(stderr,"Initial sockets: here=");
 
230
        display_in_hex(&here[which].sin_addr,sizeof(struct in_addr));
 
231
        fputc('/',stderr);
 
232
        display_in_hex(&here[which].sin_port,sizeof(here[which].sin_port));
 
233
        fprintf(stderr," there=");
 
234
        display_in_hex(&there[which].sin_addr,sizeof(struct in_addr));
 
235
        fputc('/',stderr);
 
236
        display_in_hex(&there[which].sin_port,sizeof(there[which].sin_port));
 
237
        fputc('\n',stderr);
 
238
    }
 
239
 
 
240
/* Allocate a local UDP socket and configure it. */
 
241
 
 
242
    errno = 0;
 
243
    if ((descriptors[which] = socket(AF_INET,SOCK_DGRAM,0)) < 0 ||
 
244
            bind(descriptors[which],(struct sockaddr *)&here[which],
 
245
                    sizeof(here[which]))  < 0)
 
246
        fatal(1,"unable to allocate socket for NTP",NULL);
 
247
    if (operation == op_broadcast) {
 
248
        errno = 0;
 
249
        k = setsockopt(descriptors[which],SOL_SOCKET,SO_BROADCAST,
 
250
                (void *)&k,sizeof(k));
 
251
        if (k != 0) fatal(1,"unable to set permission to broadcast",NULL);
 
252
    }
 
253
}
 
254
 
 
255
#endif
 
256
 
 
257
extern void write_socket (int which, void *packet, int length) {
 
258
 
 
259
/* Any errors in doing this are fatal - including blocking.  Yes, this leaves a
 
260
server vulnerable to a denial of service attack. */
 
261
 
 
262
    int k, sl;
 
263
 
 
264
    switch(((struct sockaddr_in *)&there[which])->sin_family) {
 
265
    case AF_INET:
 
266
        sl = sizeof(struct sockaddr_in);
 
267
        break;
 
268
#ifdef HAVE_IPV6
 
269
    case AF_INET6:
 
270
        sl = sizeof(struct sockaddr_in6);
 
271
        break;
 
272
#endif
 
273
    default:
 
274
        sl = 0;
 
275
        break;
 
276
    }
 
277
    if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0)
 
278
        fatal(0,"socket index out of range or not open",NULL);
 
279
    errno = 0;
 
280
    k = sendto(descriptors[which],packet,(size_t)length,0,
 
281
            (struct sockaddr *)&there[which],sl);
 
282
    if (k != length) fatal(1,"unable to send NTP packet",NULL);
 
283
}
 
284
 
 
285
 
 
286
 
 
287
extern int read_socket (int which, void *packet, int length, int waiting) {
 
288
 
 
289
/* Read a packet and return its length or -1 for failure.  Only incorrect
 
290
length and timeout are not fatal. */
 
291
 
 
292
#ifdef HAVE_IPV6
 
293
    struct sockaddr_storage scratch, *ptr;
 
294
#else
 
295
    struct sockaddr_in scratch, *ptr;
 
296
#endif
 
297
    int n;
 
298
    int k;
 
299
 
 
300
/* Under normal circumstances, set up a timeout. */
 
301
 
 
302
    if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0)
 
303
        fatal(0,"socket index out of range or not open",NULL);
 
304
    if (waiting > 0) {
 
305
        if (setjmp(jump_buffer)) {
 
306
            if (verbose > 2)
 
307
                fprintf(stderr,"Receive timed out\n");
 
308
            else if (verbose > 1)
 
309
                fprintf(stderr,"%s: receive timed out after %d seconds\n",
 
310
                    argv0,waiting);
 
311
            return -1;
 
312
        }
 
313
        errno = 0;
 
314
        if (signal(SIGALRM,jump_handler) == SIG_ERR)
 
315
            fatal(1,"unable to set up signal handler",NULL);
 
316
        alarm((unsigned int)waiting);
 
317
    }
 
318
 
 
319
/* Get the packet and clear the timeout, if any.  */
 
320
 
 
321
    if (operation == op_server)
 
322
        memcpy(ptr = &there[which],&here[which],sizeof(scratch));
 
323
    else
 
324
        memcpy(ptr = &scratch,&there[which],sizeof(scratch));
 
325
    n = sizeof(scratch);
 
326
    errno = 0;
 
327
    k = recvfrom(descriptors[which],packet,(size_t)length,0,
 
328
        (struct sockaddr *)ptr,&n);
 
329
    if (waiting > 0) clear_alarm();
 
330
 
 
331
/* Now issue some low-level diagnostics. */
 
332
 
 
333
    if (k <= 0) fatal(1,"unable to receive NTP packet from server",NULL);
 
334
    if (verbose > 2) {
 
335
        fprintf(stderr,"Packet of length %d received from ",k);
 
336
        display_sock_in_hex(ptr);
 
337
        fputc('\n',stderr);
 
338
    }
 
339
    return k;
 
340
}
 
341
 
 
342
 
 
343
 
 
344
extern int flush_socket (int which) {
 
345
 
 
346
/* Get rid of any outstanding input, because it may have been hanging around
 
347
for a while.  Ignore packet length oddities and return the number of packets
 
348
skipped. */
 
349
 
 
350
#ifdef HAVE_IPV6
 
351
    struct sockaddr_storage scratch;
 
352
#else
 
353
    struct sockaddr_in scratch;
 
354
#endif
 
355
    int n;
 
356
    char buffer[256];
 
357
    int flags, count = 0, total = 0, k;
 
358
 
 
359
/* The code is the obvious. */
 
360
 
 
361
    if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0)
 
362
        fatal(0,"socket index out of range or not open",NULL);
 
363
    if (verbose > 2) fprintf(stderr,"Flushing outstanding packets\n");
 
364
    errno = 0;
 
365
    if ((flags = fcntl(descriptors[which],F_GETFL,0)) < 0 ||
 
366
            fcntl(descriptors[which],F_SETFL,flags|O_NONBLOCK) == -1)
 
367
        fatal(1,"unable to set non-blocking mode",NULL);
 
368
    while (1) {
 
369
        n = sizeof(scratch);
 
370
        errno = 0;
 
371
        k = recvfrom(descriptors[which],buffer,256,0,
 
372
            (struct sockaddr *)&scratch,&n);
 
373
        if (k < 0) {
 
374
            if (errno == EAGAIN || errno == EWOULDBLOCK) break;
 
375
            fatal(1,"unable to flush socket",NULL);
 
376
        }
 
377
        ++count;
 
378
        total += k;
 
379
    }
 
380
    errno = 0;
 
381
    if (fcntl(descriptors[which],F_SETFL,flags) == -1)
 
382
        fatal(1,"unable to restore blocking mode",NULL);
 
383
    if (verbose > 2)
 
384
        fprintf(stderr,"Flushed %d packets totalling %d bytes\n",count,total);
 
385
    return count;
 
386
}
 
387
 
 
388
 
 
389
 
 
390
extern void close_socket (int which) {
 
391
 
 
392
/* There is little point in shielding this with a timeout, because any hangs
 
393
are unlikely to be interruptible.  It can get called when the sockets haven't
 
394
been opened, so ignore that case. */
 
395
 
 
396
    if (which < 0 || which >= MAX_SOCKETS)
 
397
        fatal(0,"socket index out of range",NULL);
 
398
    if (descriptors[which] < 0) return;
 
399
    errno = 0;
 
400
    if (close(descriptors[which])) fatal(1,"unable to close NTP socket",NULL);
 
401
}