1/* Copyright (C) 1996, 2000 N.M. Maclaren 2 Copyright (C) 1996, 2000 The University of Cambridge 3 4This includes all of the code needed to handle Berkeley sockets. It is way 5outside current POSIX, unfortunately. It should be easy to convert to a system 6that uses another mechanism. It does not currently use socklen_t, because 7the only system that the author uses that has it is Linux. */ 8 9 10 11#include "config.h" 12 13#include "header.h" 14#include "internet.h" 15#include <fcntl.h> 16 17#define SOCKET 18#include "kludges.h" 19#undef SOCKET 20 21 22 23/* The code needs to set some variables during the open, for use by later 24functions. */ 25 26static int initial = 1, 27 descriptors[MAX_SOCKETS]; 28 29#ifdef HAVE_IPV6 30static struct sockaddr_storage here[MAX_SOCKETS], there[MAX_SOCKETS]; 31#else 32static struct sockaddr_in here[MAX_SOCKETS], there[MAX_SOCKETS]; 33#endif 34 35void display_in_hex(const void *, int); 36#ifdef HAVE_IPV6 37void display_sock_in_hex(struct sockaddr_storage *); 38#else 39void display_sock_in_hex (struct sockaddr_in *); 40#endif 41 42/* There needs to be some disgusting grobble for handling timeouts, that is 43identical to the grobble in internet.c. */ 44 45static jmp_buf jump_buffer; 46 47static void jump_handler (int sig) { 48 longjmp(jump_buffer,1); 49} 50 51static void clear_alarm (void) { 52 int k; 53 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; 60} 61 62 63 64void display_in_hex (const void *data, int length) { 65 int i; 66 67 for (i = 0; i < length; ++i) 68 fprintf(stderr,"%.2x",((const unsigned char *)data)[i]); 69} 70 71#ifdef HAVE_IPV6 72 73void display_sock_in_hex (struct sockaddr_storage *sock) { 74 int family; 75 struct sockaddr_in *sin; 76 struct sockaddr_in6 *sin6; 77 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; 92 } 93} 94 95#else 96 97void display_sock_in_hex (struct sockaddr_in *sock) { 98 int family, len; 99 struct sockaddr_in *sin; 100 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; 109 } 110} 111#endif 112 113extern int unprivport; 114 115#ifdef HAVE_IPV6 116 117void open_socket (int which, char *hostname, int timespan) { 118 119/* Locate the specified NTP server, set up a couple of addresses and open a 120socket. */ 121 122 int port, k, sl; 123 struct sockaddr_storage address, anywhere; 124 125/* Initialise and find out the server and port number. Note that the port 126number is in network format. */ 127 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); 143 } 144 145/* Set up our own and the target addresses. Note that the target address will 146be reset before use in server mode. */ 147 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); 160 } 161 162/* Allocate a local UDP socket and configure it. */ 163 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; 176 } 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); 181} 182 183#else 184 185void open_socket (int which, char *hostname, int timespan) { 186 187/* Locate the specified NTP server, set up a couple of addresses and open a 188socket. */ 189 190 int port, k; 191 struct in_addr address, anywhere; 192 193/* Initialise and find out the server and port number. Note that the port 194number is in network format. */ 195 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); 208 } 209 210/* Set up our own and the target addresses. */ 211 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); 231 } 232 233/* Allocate a local UDP socket and configure it. */ 234 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); 240} 241 242#endif 243 244extern void write_socket (int which, void *packet, int length) { 245 246/* Any errors in doing this are fatal - including blocking. Yes, this leaves a 247server vulnerable to a denial of service attack. */ 248 249 int k, sl; 250 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; 263 } 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); 270} 271 272 273 274extern int read_socket (int which, void *packet, int length, int waiting) { 275 276/* Read a packet and return its length or -1 for failure. Only incorrect 277length and timeout are not fatal. */ 278 279#ifdef HAVE_IPV6 280 struct sockaddr_storage scratch, *ptr; 281#else 282 struct sockaddr_in scratch, *ptr; 283#endif 284 int n; 285 int k; 286 287/* Under normal circumstances, set up a timeout. */ 288 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; 299 } 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); 304 } 305 306/* Get the packet and clear the timeout, if any. */ 307 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(); 314 315/* Now issue some low-level diagnostics. */ 316 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); 322 } 323 return k; 324} 325 326 327 328extern int flush_socket (int which) { 329 330/* Get rid of any outstanding input, because it may have been hanging around 331for a while. Ignore packet length oddities and return the number of packets 332skipped. */ 333 334#ifdef HAVE_IPV6 335 struct sockaddr_storage scratch; 336#else 337 struct sockaddr_in scratch; 338#endif 339 int n; 340 char buffer[256]; 341 int flags, count = 0, total = 0, k; 342 343/* The code is the obvious. */ 344 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); 360 } 361 ++count; 362 total += k; 363 } 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; 370} 371 372 373 374extern void close_socket (int which) { 375 376/* There is little point in shielding this with a timeout, because any hangs 377are unlikely to be interruptible. It can get called when the sockets haven't 378been opened, so ignore that case. */ 379 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); 385} 386