1132451Sroberto/* Copyright (C) 1996, 2000 N.M. Maclaren 2132451Sroberto Copyright (C) 1996, 2000 The University of Cambridge 3132451Sroberto 4132451SrobertoThis includes all of the code needed to handle Berkeley sockets. It is way 5132451Srobertooutside current POSIX, unfortunately. It should be easy to convert to a system 6132451Srobertothat uses another mechanism. It does not currently use socklen_t, because 7132451Srobertothe only system that the author uses that has it is Linux. */ 8132451Sroberto 9132451Sroberto 10132451Sroberto 11182007Sroberto#include "config.h" 12182007Sroberto 13132451Sroberto#include "header.h" 14132451Sroberto#include "internet.h" 15132451Sroberto#include <fcntl.h> 16132451Sroberto 17132451Sroberto#define SOCKET 18132451Sroberto#include "kludges.h" 19132451Sroberto#undef SOCKET 20132451Sroberto 21132451Sroberto 22132451Sroberto 23132451Sroberto/* The code needs to set some variables during the open, for use by later 24132451Srobertofunctions. */ 25132451Sroberto 26132451Srobertostatic int initial = 1, 27132451Sroberto descriptors[MAX_SOCKETS]; 28132451Sroberto 29132451Sroberto#ifdef HAVE_IPV6 30132451Srobertostatic struct sockaddr_storage here[MAX_SOCKETS], there[MAX_SOCKETS]; 31132451Sroberto#else 32132451Srobertostatic struct sockaddr_in here[MAX_SOCKETS], there[MAX_SOCKETS]; 33132451Sroberto#endif 34132451Sroberto 35182007Srobertovoid display_in_hex(const void *, int); 36182007Sroberto#ifdef HAVE_IPV6 37182007Srobertovoid display_sock_in_hex(struct sockaddr_storage *); 38182007Sroberto#else 39182007Srobertovoid display_sock_in_hex (struct sockaddr_in *); 40182007Sroberto#endif 41132451Sroberto 42132451Sroberto/* There needs to be some disgusting grobble for handling timeouts, that is 43132451Srobertoidentical to the grobble in internet.c. */ 44132451Sroberto 45132451Srobertostatic jmp_buf jump_buffer; 46132451Sroberto 47132451Srobertostatic void jump_handler (int sig) { 48132451Sroberto longjmp(jump_buffer,1); 49132451Sroberto} 50132451Sroberto 51132451Srobertostatic void clear_alarm (void) { 52132451Sroberto int k; 53132451Sroberto 54132451Sroberto k = errno; 55132451Sroberto alarm(0); 56132451Sroberto errno = 0; 57132451Sroberto if (signal(SIGALRM,SIG_DFL) == SIG_ERR) 58132451Sroberto fatal(1,"unable to reset signal handler",NULL); 59132451Sroberto errno = k; 60132451Sroberto} 61132451Sroberto 62132451Sroberto 63132451Sroberto 64132451Srobertovoid display_in_hex (const void *data, int length) { 65132451Sroberto int i; 66132451Sroberto 67132451Sroberto for (i = 0; i < length; ++i) 68132451Sroberto fprintf(stderr,"%.2x",((const unsigned char *)data)[i]); 69132451Sroberto} 70132451Sroberto 71132451Sroberto#ifdef HAVE_IPV6 72132451Sroberto 73132451Srobertovoid display_sock_in_hex (struct sockaddr_storage *sock) { 74182007Sroberto int family; 75132451Sroberto struct sockaddr_in *sin; 76132451Sroberto struct sockaddr_in6 *sin6; 77132451Sroberto 78132451Sroberto family = sock->ss_family; 79132451Sroberto switch(family) { 80132451Sroberto case AF_INET: 81132451Sroberto sin = (struct sockaddr_in *)sock; 82132451Sroberto display_in_hex(&sin->sin_addr, sizeof(struct in_addr)); 83132451Sroberto fprintf(stderr,"/"); 84132451Sroberto display_in_hex(&sin->sin_port, 2); 85132451Sroberto break; 86132451Sroberto case AF_INET6: 87132451Sroberto sin6 = (struct sockaddr_in6 *)sock; 88132451Sroberto display_in_hex(&sin6->sin6_addr, sizeof(struct in6_addr)); 89132451Sroberto fprintf(stderr,"/"); 90132451Sroberto display_in_hex(&sin6->sin6_port, 2); 91132451Sroberto break; 92132451Sroberto } 93132451Sroberto} 94132451Sroberto 95132451Sroberto#else 96132451Sroberto 97132451Srobertovoid display_sock_in_hex (struct sockaddr_in *sock) { 98132451Sroberto int family, len; 99132451Sroberto struct sockaddr_in *sin; 100132451Sroberto 101132451Sroberto family = sock->sin_family; 102132451Sroberto switch(family) { 103132451Sroberto case AF_INET: 104132451Sroberto sin = (struct sockaddr_in *)sock; 105132451Sroberto display_in_hex(&sin->sin_addr, sizeof(struct in_addr)); 106132451Sroberto fprintf(stderr,"/"); 107132451Sroberto display_in_hex(&sin->sin_port, 2); 108132451Sroberto break; 109132451Sroberto } 110132451Sroberto} 111132451Sroberto#endif 112132451Sroberto 113182007Srobertoextern int unprivport; 114182007Sroberto 115132451Sroberto#ifdef HAVE_IPV6 116132451Sroberto 117132451Srobertovoid open_socket (int which, char *hostname, int timespan) { 118132451Sroberto 119132451Sroberto/* Locate the specified NTP server, set up a couple of addresses and open a 120132451Srobertosocket. */ 121132451Sroberto 122132451Sroberto int port, k, sl; 123182007Sroberto struct sockaddr_storage address, anywhere; 124132451Sroberto 125132451Sroberto/* Initialise and find out the server and port number. Note that the port 126132451Srobertonumber is in network format. */ 127132451Sroberto 128132451Sroberto if (initial) 129132451Sroberto for (k = 0; k < MAX_SOCKETS; ++k) 130132451Sroberto descriptors[k] = -1; 131132451Sroberto initial = 0; 132132451Sroberto if (which < 0 || which >= MAX_SOCKETS || descriptors[which] >= 0) 133132451Sroberto fatal(0,"socket index out of range or already open",NULL); 134132451Sroberto if (verbose > 2) 135132451Sroberto fprintf(stderr,"Looking for the socket addresses\n"); 136182007Sroberto find_address(&address,&anywhere,&port,hostname,timespan); 137132451Sroberto if (verbose > 2) { 138132451Sroberto fprintf(stderr,"Internet address: address="); 139132451Sroberto display_sock_in_hex(&address); 140132451Sroberto fprintf(stderr," anywhere="); 141132451Sroberto display_sock_in_hex(&anywhere); 142132451Sroberto fputc('\n',stderr); 143132451Sroberto } 144132451Sroberto 145132451Sroberto/* Set up our own and the target addresses. Note that the target address will 146132451Srobertobe reset before use in server mode. */ 147132451Sroberto 148132451Sroberto memset(&here[which], 0, sizeof(struct sockaddr_storage)); 149132451Sroberto here[which] = anywhere; 150182007Sroberto if (operation != op_listen || unprivport) 151132451Sroberto ((struct sockaddr_in6 *)&here[which])->sin6_port = 0; 152132451Sroberto memset(&there[which], 0, sizeof(struct sockaddr_storage)); 153182007Sroberto there[which] = address; 154132451Sroberto if (verbose > 2) { 155132451Sroberto fprintf(stderr,"Initial sockets: here="); 156132451Sroberto display_sock_in_hex(&here[which]); 157132451Sroberto fprintf(stderr," there="); 158132451Sroberto display_sock_in_hex(&there[which]); 159132451Sroberto fputc('\n',stderr); 160132451Sroberto } 161132451Sroberto 162132451Sroberto/* Allocate a local UDP socket and configure it. */ 163132451Sroberto 164132451Sroberto switch(((struct sockaddr_in *)&there[which])->sin_family) { 165132451Sroberto case AF_INET: 166132451Sroberto sl = sizeof(struct sockaddr_in); 167132451Sroberto break; 168132451Sroberto#ifdef HAVE_IPV6 169132451Sroberto case AF_INET6: 170132451Sroberto sl = sizeof(struct sockaddr_in6); 171132451Sroberto break; 172132451Sroberto#endif 173132451Sroberto default: 174132451Sroberto sl = 0; 175132451Sroberto break; 176132451Sroberto } 177132451Sroberto errno = 0; 178132451Sroberto if ((descriptors[which] = socket(here[which].ss_family,SOCK_DGRAM,0)) < 0 179132451Sroberto || bind(descriptors[which],(struct sockaddr *)&here[which], sl) < 0) 180132451Sroberto fatal(1,"unable to allocate socket for NTP",NULL); 181132451Sroberto} 182132451Sroberto 183132451Sroberto#else 184132451Sroberto 185132451Srobertovoid open_socket (int which, char *hostname, int timespan) { 186132451Sroberto 187132451Sroberto/* Locate the specified NTP server, set up a couple of addresses and open a 188132451Srobertosocket. */ 189132451Sroberto 190132451Sroberto int port, k; 191182007Sroberto struct in_addr address, anywhere; 192132451Sroberto 193132451Sroberto/* Initialise and find out the server and port number. Note that the port 194132451Srobertonumber is in network format. */ 195132451Sroberto 196132451Sroberto if (initial) for (k = 0; k < MAX_SOCKETS; ++k) descriptors[k] = -1; 197132451Sroberto initial = 0; 198132451Sroberto if (which < 0 || which >= MAX_SOCKETS || descriptors[which] >= 0) 199132451Sroberto fatal(0,"socket index out of range or already open",NULL); 200132451Sroberto if (verbose > 2) fprintf(stderr,"Looking for the socket addresses\n"); 201182007Sroberto find_address(&address,&anywhere,&port,hostname,timespan); 202132451Sroberto if (verbose > 2) { 203132451Sroberto fprintf(stderr,"Internet address: address="); 204132451Sroberto display_in_hex(&address,sizeof(struct in_addr)); 205132451Sroberto fprintf(stderr," anywhere="); 206132451Sroberto display_in_hex(&anywhere,sizeof(struct in_addr)); 207132451Sroberto fputc('\n',stderr); 208132451Sroberto } 209132451Sroberto 210182007Sroberto/* Set up our own and the target addresses. */ 211132451Sroberto 212132451Sroberto memset(&here[which],0,sizeof(struct sockaddr_in)); 213132451Sroberto here[which].sin_family = AF_INET; 214132451Sroberto here[which].sin_port = 215182007Sroberto (operation == op_listen || !unprivport ? port : 0); 216132451Sroberto here[which].sin_addr = anywhere; 217132451Sroberto memset(&there[which],0,sizeof(struct sockaddr_in)); 218132451Sroberto there[which].sin_family = AF_INET; 219132451Sroberto there[which].sin_port = port; 220182007Sroberto there[which].sin_addr = address; 221132451Sroberto if (verbose > 2) { 222132451Sroberto fprintf(stderr,"Initial sockets: here="); 223132451Sroberto display_in_hex(&here[which].sin_addr,sizeof(struct in_addr)); 224132451Sroberto fputc('/',stderr); 225132451Sroberto display_in_hex(&here[which].sin_port,sizeof(here[which].sin_port)); 226132451Sroberto fprintf(stderr," there="); 227132451Sroberto display_in_hex(&there[which].sin_addr,sizeof(struct in_addr)); 228132451Sroberto fputc('/',stderr); 229132451Sroberto display_in_hex(&there[which].sin_port,sizeof(there[which].sin_port)); 230132451Sroberto fputc('\n',stderr); 231132451Sroberto } 232132451Sroberto 233132451Sroberto/* Allocate a local UDP socket and configure it. */ 234132451Sroberto 235132451Sroberto errno = 0; 236132451Sroberto if ((descriptors[which] = socket(AF_INET,SOCK_DGRAM,0)) < 0 || 237132451Sroberto bind(descriptors[which],(struct sockaddr *)&here[which], 238132451Sroberto sizeof(here[which])) < 0) 239132451Sroberto fatal(1,"unable to allocate socket for NTP",NULL); 240132451Sroberto} 241132451Sroberto 242132451Sroberto#endif 243132451Sroberto 244132451Srobertoextern void write_socket (int which, void *packet, int length) { 245132451Sroberto 246132451Sroberto/* Any errors in doing this are fatal - including blocking. Yes, this leaves a 247132451Srobertoserver vulnerable to a denial of service attack. */ 248132451Sroberto 249132451Sroberto int k, sl; 250132451Sroberto 251132451Sroberto switch(((struct sockaddr_in *)&there[which])->sin_family) { 252132451Sroberto case AF_INET: 253132451Sroberto sl = sizeof(struct sockaddr_in); 254132451Sroberto break; 255132451Sroberto#ifdef HAVE_IPV6 256132451Sroberto case AF_INET6: 257132451Sroberto sl = sizeof(struct sockaddr_in6); 258132451Sroberto break; 259132451Sroberto#endif 260132451Sroberto default: 261132451Sroberto sl = 0; 262132451Sroberto break; 263132451Sroberto } 264132451Sroberto if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0) 265132451Sroberto fatal(0,"socket index out of range or not open",NULL); 266132451Sroberto errno = 0; 267132451Sroberto k = sendto(descriptors[which],packet,(size_t)length,0, 268132451Sroberto (struct sockaddr *)&there[which],sl); 269132451Sroberto if (k != length) fatal(1,"unable to send NTP packet",NULL); 270132451Sroberto} 271132451Sroberto 272132451Sroberto 273132451Sroberto 274132451Srobertoextern int read_socket (int which, void *packet, int length, int waiting) { 275132451Sroberto 276132451Sroberto/* Read a packet and return its length or -1 for failure. Only incorrect 277132451Srobertolength and timeout are not fatal. */ 278132451Sroberto 279132451Sroberto#ifdef HAVE_IPV6 280132451Sroberto struct sockaddr_storage scratch, *ptr; 281132451Sroberto#else 282132451Sroberto struct sockaddr_in scratch, *ptr; 283132451Sroberto#endif 284132451Sroberto int n; 285132451Sroberto int k; 286132451Sroberto 287132451Sroberto/* Under normal circumstances, set up a timeout. */ 288132451Sroberto 289132451Sroberto if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0) 290132451Sroberto fatal(0,"socket index out of range or not open",NULL); 291132451Sroberto if (waiting > 0) { 292132451Sroberto if (setjmp(jump_buffer)) { 293132451Sroberto if (verbose > 2) 294132451Sroberto fprintf(stderr,"Receive timed out\n"); 295132451Sroberto else if (verbose > 1) 296132451Sroberto fprintf(stderr,"%s: receive timed out after %d seconds\n", 297132451Sroberto argv0,waiting); 298132451Sroberto return -1; 299132451Sroberto } 300132451Sroberto errno = 0; 301132451Sroberto if (signal(SIGALRM,jump_handler) == SIG_ERR) 302132451Sroberto fatal(1,"unable to set up signal handler",NULL); 303132451Sroberto alarm((unsigned int)waiting); 304132451Sroberto } 305132451Sroberto 306132451Sroberto/* Get the packet and clear the timeout, if any. */ 307132451Sroberto 308182007Sroberto memcpy(ptr = &scratch,&there[which],sizeof(scratch)); 309132451Sroberto n = sizeof(scratch); 310132451Sroberto errno = 0; 311132451Sroberto k = recvfrom(descriptors[which],packet,(size_t)length,0, 312132451Sroberto (struct sockaddr *)ptr,&n); 313132451Sroberto if (waiting > 0) clear_alarm(); 314132451Sroberto 315132451Sroberto/* Now issue some low-level diagnostics. */ 316132451Sroberto 317132451Sroberto if (k <= 0) fatal(1,"unable to receive NTP packet from server",NULL); 318132451Sroberto if (verbose > 2) { 319132451Sroberto fprintf(stderr,"Packet of length %d received from ",k); 320132451Sroberto display_sock_in_hex(ptr); 321132451Sroberto fputc('\n',stderr); 322132451Sroberto } 323132451Sroberto return k; 324132451Sroberto} 325132451Sroberto 326132451Sroberto 327132451Sroberto 328132451Srobertoextern int flush_socket (int which) { 329132451Sroberto 330132451Sroberto/* Get rid of any outstanding input, because it may have been hanging around 331132451Srobertofor a while. Ignore packet length oddities and return the number of packets 332132451Srobertoskipped. */ 333132451Sroberto 334132451Sroberto#ifdef HAVE_IPV6 335132451Sroberto struct sockaddr_storage scratch; 336132451Sroberto#else 337132451Sroberto struct sockaddr_in scratch; 338132451Sroberto#endif 339132451Sroberto int n; 340132451Sroberto char buffer[256]; 341132451Sroberto int flags, count = 0, total = 0, k; 342132451Sroberto 343132451Sroberto/* The code is the obvious. */ 344132451Sroberto 345132451Sroberto if (which < 0 || which >= MAX_SOCKETS || descriptors[which] < 0) 346132451Sroberto fatal(0,"socket index out of range or not open",NULL); 347132451Sroberto if (verbose > 2) fprintf(stderr,"Flushing outstanding packets\n"); 348132451Sroberto errno = 0; 349132451Sroberto if ((flags = fcntl(descriptors[which],F_GETFL,0)) < 0 || 350132451Sroberto fcntl(descriptors[which],F_SETFL,flags|O_NONBLOCK) == -1) 351132451Sroberto fatal(1,"unable to set non-blocking mode",NULL); 352132451Sroberto while (1) { 353132451Sroberto n = sizeof(scratch); 354132451Sroberto errno = 0; 355132451Sroberto k = recvfrom(descriptors[which],buffer,256,0, 356132451Sroberto (struct sockaddr *)&scratch,&n); 357132451Sroberto if (k < 0) { 358132451Sroberto if (errno == EAGAIN || errno == EWOULDBLOCK) break; 359132451Sroberto fatal(1,"unable to flush socket",NULL); 360132451Sroberto } 361132451Sroberto ++count; 362132451Sroberto total += k; 363132451Sroberto } 364132451Sroberto errno = 0; 365132451Sroberto if (fcntl(descriptors[which],F_SETFL,flags) == -1) 366132451Sroberto fatal(1,"unable to restore blocking mode",NULL); 367132451Sroberto if (verbose > 2) 368132451Sroberto fprintf(stderr,"Flushed %d packets totalling %d bytes\n",count,total); 369132451Sroberto return count; 370132451Sroberto} 371132451Sroberto 372132451Sroberto 373132451Sroberto 374132451Srobertoextern void close_socket (int which) { 375132451Sroberto 376132451Sroberto/* There is little point in shielding this with a timeout, because any hangs 377132451Srobertoare unlikely to be interruptible. It can get called when the sockets haven't 378132451Srobertobeen opened, so ignore that case. */ 379132451Sroberto 380132451Sroberto if (which < 0 || which >= MAX_SOCKETS) 381132451Sroberto fatal(0,"socket index out of range",NULL); 382132451Sroberto if (descriptors[which] < 0) return; 383132451Sroberto errno = 0; 384132451Sroberto if (close(descriptors[which])) fatal(1,"unable to close NTP socket",NULL); 385132451Sroberto} 386