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