1 | /*************************************** 2 | $Revision: 1.18 $ 3 | 4 | Socket module - routines facilitating calls to socket library. 5 | 6 | Status: NOT REVUED, TESTED 7 | 8 | Basic code adapted by Chris Ottrey from 9 | http://www.ibrado.com/sock-faq/sfaq.html#faq65 - sample source code. 10 | ******************/ /****************** 11 | Modification History: 12 | ottrey (08/03/1999) Created from sockhelp.c. 13 | ottrey (08/03/1998) Heavily butchered. 14 | joao (22/06/1999) Modified socket creation and accepts. 15 | marek (December 2000) Added connection function w/timeout. 16 | ******************/ /****************** 17 | Copyright (c) 1999, 2000 RIPE NCC 18 | 19 | All Rights Reserved 20 | 21 | Permission to use, copy, modify, and distribute this software and its 22 | documentation for any purpose and without fee is hereby granted, 23 | provided that the above copyright notice appear in all copies and that 24 | both that copyright notice and this permission notice appear in 25 | supporting documentation, and that the name of the author not be 26 | used in advertising or publicity pertaining to distribution of the 27 | software without specific, written prior permission. 28 | 29 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 30 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 31 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 32 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 33 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 34 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 35 | ***************************************/ 36 | 37 | #include "sk.h" 38 | #include "constants.h" 39 | #include "stubs.h" 40 | 41 | #include "memwrap.h" 42 | 43 | /*+ String sizes +*/ 44 | #define STR_S 63 45 | #define STR_XXL 16383 46 | 47 | /* SK_atoport() */ 48 | /*++++++++++++++++++++++++++++++++++++++ 49 | Take a service name, and a service type, and return a port number. If the 50 | service name is not found, it tries it as a decimal number. The number 51 | returned is byte ordered for the network. 52 | 53 | char *service Service name (or port number). 54 | 55 | char *proto Protocol (eg "tcp"). 56 | 57 | Author: 58 | ottrey. 59 | 60 | ++++++++++++++++++++++++++++++++++++++*/ 61 | int SK_atoport(const char *service, const char *proto) { 62 | unsigned port; 63 | long int lport; 64 | struct servent *serv; 65 | char *errpos; 66 | struct servent result; 67 | char buffer[STR_XXL]; 68 | 69 | /* First try to read it from /etc/services */ 70 | 71 | #ifdef __linux__ 72 | if(getservbyname_r(service, proto, &result, buffer, sizeof(buffer), &serv) < 0) serv = NULL; 73 | #else 74 | serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer)); 75 | #endif 76 | 77 | if (serv != NULL) 78 | port = serv->s_port; 79 | else { /* Not in services, maybe a number? */ 80 | lport = strtol(service,&errpos,0); 81 | if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) ) 82 | return -1; /* Invalid port address */ 83 | port = htons(lport); 84 | } 85 | return port; 86 | } /* SK_atoport() */ 87 | 88 | 89 | /* SK_close() */ 90 | /*++++++++++++++++++++++++++++++++++++++ 91 | 92 | int SK_close wrapper around closing the socket. Returns the value 93 | returned by close(2) 94 | 95 | int socket socket to be closed 96 | 97 | Author: 98 | ottrey 99 | ++++++++++++++++++++++++++++++++++++++*/ 100 | int SK_close(int socket) { 101 | ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket); 102 | 103 | return close(socket); 104 | } 105 | 106 | /* SK_getsock() */ 107 | /*++++++++++++++++++++++++++++++++++++++ 108 | 109 | int SK_getsock This function creates a socket and binds to it. 110 | Returns the number of the created 111 | descriptor/listening socket. 112 | 113 | int socket_type SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets) 114 | 115 | unsigned port The port to listen on. Ports < 1024 are 116 | reserved for the root user. Host byte order. 117 | 118 | int backlog Size of the backlog queue to be set on that 119 | socket. 120 | 121 | uint32_t bind_address Address to bind to, in network order. 122 | 123 | Authors: 124 | ottrey, 125 | joao, 126 | marek (added htons conversion for port). 127 | 128 | ++++++++++++++++++++++++++++++++++++++*/ 129 | int SK_getsock(int socket_type, unsigned h_port, int backlog, 130 | uint32_t bind_address) { 131 | struct sockaddr_in address; 132 | int listening_socket; 133 | int reuse_addr = 1; 134 | u_short port = htons(h_port); 135 | 136 | /* Setup internet address information. 137 | This is used with the bind() call */ 138 | memset((char *) &address, 0, sizeof(address)); 139 | address.sin_family = AF_INET; 140 | address.sin_port = port; 141 | address.sin_addr.s_addr = bind_address; 142 | 143 | /* Map all of the signals and exit routine */ 144 | 145 | listening_socket = socket(AF_INET, socket_type, 0); 146 | if (listening_socket < 0) { 147 | perror("socket"); 148 | exit(EXIT_FAILURE); 149 | } 150 | 151 | setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr)); 152 | 153 | if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) { 154 | perror("bind"); 155 | close(listening_socket); 156 | exit(EXIT_FAILURE); 157 | } 158 | 159 | 160 | if (socket_type == SOCK_STREAM) { 161 | listen(listening_socket, backlog); /* Queue up to five connections before 162 | having them automatically rejected. */ 163 | } 164 | 165 | return listening_socket; 166 | } /* SK_getsock() */ 167 | 168 | /*++++++++++++++++++++++++++++++++++++++ 169 | 170 | Wait for an incoming connection on the specified socket 171 | 172 | int SK_accept_connection The socket for communicating to the client 173 | 174 | int listening_socket The socket that the server is bound to 175 | 176 | Authors: 177 | joao, 178 | marek. 179 | ++++++++++++++++++++++++++++++++++++++*/ 180 | int SK_accept_connection(int listening_socket) { 181 | int connected_socket = -1; 182 | int num_errors = 0; 183 | 184 | #define MAX_ACCEPT_ERRORS 3 185 | 186 | for (;;) { 187 | 188 | ER_dbg_va(FAC_SK, ASP_SK_GEN, 189 | "Going to accept connections on socket : %d",listening_socket); 190 | 191 | connected_socket = accept(listening_socket, NULL, NULL); 192 | if (connected_socket < 0) { 193 | /* Either a real error occured, or blocking was interrupted for 194 | some reason. Only abort execution if a real error occured. */ 195 | switch(errno) { 196 | case EINTR: /* Interrupted system call */ 197 | case ECONNABORTED: /* Software caused connection abort */ 198 | /* no warning */ 199 | continue; /* don't return - do the accept again */ 200 | default: 201 | /* special case: shutdown of the server - just return */ 202 | if( CO_get_do_server() == 0 ) { 203 | return -1; 204 | } 205 | else { /* real error */ 206 | if( ++num_errors < MAX_ACCEPT_ERRORS ) { 207 | /* warn */ 208 | ER_perror(FAC_SK, SK_ACERW, "(%d) %s", errno, strerror(errno)); 209 | } 210 | else { 211 | /* crash */ 212 | ER_perror(FAC_SK, SK_ACERF, 213 | "too many accept() errors (maximum is %d)", MAX_ACCEPT_ERRORS); 214 | die; 215 | } 216 | } 217 | } 218 | } 219 | else { /* success */ 220 | ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d", 221 | connected_socket 222 | ); 223 | 224 | return connected_socket; 225 | } 226 | 227 | } 228 | } 229 | 230 | 231 | /*++++++++++++++++++++++++++++++++++++++ 232 | 233 | er_ret_t SK_connect wrapper around connect(), doing non-blocking 234 | connection with timeout 235 | 236 | int *sock pointer to the storage for socket descriptor 237 | 238 | char *hostname host to connect to 239 | 240 | int port port to connect to 241 | 242 | int timeout in seconds 243 | 244 | Author: marek 245 | 246 | ++++++++++++++++++++++++++++++++++++++*/ 247 | er_ret_t SK_connect(int *sock, char *hostname, unsigned int port, unsigned int timeout) 248 | { 249 | struct sockaddr_in sin; 250 | struct hostent *hp; 251 | int s; 252 | int flags; 253 | struct timeval ptm; 254 | fd_set rset, wset; 255 | int gs, sel, er, erlen=sizeof(er); 256 | int error; 257 | struct hostent result; 258 | char aliasbuf[8192]; /* Stevens, UNIX net. prog., p.304 */ 259 | 260 | /* look up the host name */ 261 | #ifdef __linux__ 262 | er = (gethostbyname_r(hostname, &result, aliasbuf, 263 | sizeof(aliasbuf), &hp, &error) < 0 ); 264 | #else /* default is Solaris implementation */ 265 | hp = gethostbyname_r(hostname, &result, aliasbuf, 266 | sizeof(aliasbuf), &error); 267 | er = ( hp == NULL ); 268 | #endif 269 | 270 | if( er ) { 271 | return SK_BADHOST; 272 | } 273 | 274 | /* create a socket */ 275 | s = socket(AF_INET, SOCK_STREAM, 0); 276 | if (s < 0) { 277 | return SK_SOCKET; 278 | } 279 | 280 | /* bind to it */ 281 | bzero((caddr_t)&sin, sizeof (sin)); 282 | sin.sin_family = hp->h_addrtype; 283 | if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 284 | close(s); 285 | return SK_BIND; 286 | } 287 | bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); 288 | sin.sin_port=htons(port); 289 | 290 | /* connect in non-blocking mode */ 291 | flags = fcntl(s, F_GETFL, 0); 292 | fcntl(s, F_SETFL, flags | O_NONBLOCK ); 293 | 294 | if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0 295 | && errno != EINPROGRESS ) { 296 | close(s); 297 | return SK_CONNECT; 298 | } 299 | 300 | /* now wait for success */ 301 | FD_ZERO( &rset ); 302 | FD_SET( s, &rset ); 303 | wset = rset; 304 | ptm.tv_usec = 0; 305 | ptm.tv_sec = timeout; 306 | 307 | if( (sel=select(s+1, &rset, &wset, NULL, &ptm)) == 0 ) { 308 | /* timeout */ 309 | close(s); 310 | return SK_TIMEOUT; 311 | } 312 | if (sel < 0) { 313 | close(s); 314 | return SK_CONNECT; 315 | } 316 | 317 | gs = getsockopt(s, SOL_SOCKET, SO_ERROR, &er, &erlen); 318 | 319 | if( gs < 0 || er ) { /* Stevens code, p.411 is exceptionally crappy */ 320 | close(s); 321 | return SK_CONNECT; 322 | } /* if error */ 323 | 324 | fcntl(s, F_SETFL, flags); 325 | *sock = s; 326 | 327 | return SK_OK; 328 | } 329 | 330 | 331 | /* SK_read() */ 332 | /*++++++++++++++++++++++++++++++++++++++ 333 | 334 | This is just like the read() system call, except that it will make 335 | sure that all your data goes through the socket. 336 | 337 | int SK_read Returns the number of bytes read. 338 | 339 | int sockfd The socket file descriptor. 340 | 341 | char *buf The buffer to be read from the socket. 342 | 343 | size_t count The number of bytes in the buffer. 344 | 345 | Author: 346 | ottrey 347 | 348 | ++++++++++++++++++++++++++++++++++++++*/ 349 | int SK_read(int sockfd, char *buf, size_t count) { 350 | size_t bytes_read = 0; 351 | int this_read; 352 | 353 | while (bytes_read < count) { 354 | do 355 | this_read = read(sockfd, buf, count - bytes_read); 356 | while ( (this_read < 0) && (errno == EINTR) ); 357 | if (this_read < 0) 358 | return this_read; 359 | else if (this_read == 0) 360 | return bytes_read; 361 | bytes_read += this_read; 362 | buf += this_read; 363 | } 364 | 365 | return count; 366 | 367 | } /* SK_read() */ 368 | 369 | 370 | /* SK_write() */ 371 | /*++++++++++++++++++++++++++++++++++++++ 372 | 373 | int SK_write Returns: 374 | -1 on error 375 | 0 on timeout 376 | 1 on success (all bytes written) 377 | 378 | int sockfd The socket file descriptor. 379 | 380 | const char *buf The buffer to be written to the socket. 381 | 382 | int count The number of bytes in the buffer. 383 | 384 | const struct timeval *timeout Maximum time to wait between each 385 | write() call, or NULL for "forever". 386 | 387 | int *count_sent Set to the number of bytes sucessfully 388 | written. This value is always valid, 389 | although it will be less than the 390 | total number of bytes to send if 391 | the function returns -1 or 0. NULL 392 | may be sent if the caller does not 393 | care about the number of bytes sent on 394 | failure. 395 | 396 | ++++++++++++++++++++++++++++++++++++++*/ 397 | 398 | int 399 | SK_write(int sockfd, 400 | const char *buf, 401 | int count, 402 | const struct timeval *timeout, 403 | int *count_sent) 404 | { 405 | int local_count_sent; /* only used if caller passes NULL */ 406 | fd_set fds; 407 | int select_ret; 408 | struct timeval tv; 409 | int write_ret; 410 | 411 | /* copious logging never hurt anybody (well, except people with slow 412 | computers or small hard disks) */ 413 | ER_dbg_va(FAC_SK, ASP_SK_WRIT, 414 | "SK_write = { sockfd=[%d], buf=[%s], count=[%d]", 415 | sockfd, buf, count); 416 | 417 | /* allow caller to pass NULL if it doesn't care about the count sent */ 418 | if (count_sent == NULL) { 419 | count_sent = &local_count_sent; 420 | } 421 | 422 | /* loop around until we send all of our data, or we get a timeout or 423 | disconnect */ 424 | *count_sent = 0; 425 | while (*count_sent < count) { 426 | 427 | /* first, call select() and see if we can write without blocking */ 428 | FD_ZERO(&fds); 429 | FD_SET(sockfd, &fds); 430 | if (timeout == NULL) { 431 | select_ret = select(sockfd+1, NULL, &fds, NULL, NULL); 432 | } else { 433 | /* make a copy of timeout, because it's value is undefined 434 | on return from select() */ 435 | tv = *timeout; 436 | select_ret = select(sockfd+1, NULL, &fds, NULL, &tv); 437 | } 438 | /* check for error */ 439 | if (select_ret < 0) { 440 | /* log the error and return "timeout" */ 441 | ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno)); 442 | return -1; 443 | } 444 | /* check for timeout */ 445 | if ((select_ret == 0) || !FD_ISSET(sockfd, &fds)) { 446 | return -1; 447 | } 448 | 449 | 450 | /* at this point we can safely write */ 451 | write_ret = write(sockfd, buf, count - *count_sent); 452 | 453 | /* if write failed, assume other side disconnected */ 454 | if (write_ret <= 0) { 455 | return 0; 456 | } 457 | 458 | /* update our current status */ 459 | *count_sent += write_ret; 460 | buf += write_ret; 461 | 462 | } 463 | 464 | /* all bytes sent, return success */ 465 | return 1; 466 | } /* SK_write() */ 467 | 468 | 469 | /* SK_gets() */ 470 | /*++++++++++++++++++++++++++++++++++++++ 471 | 472 | This function reads from a socket, until it recieves a linefeed 473 | character. It fills the buffer "str" up to the maximum size "count". 474 | 475 | int SK_gets Returns the total_count of bytes read. 476 | 477 | int sockfd The socket file descriptor. 478 | 479 | char *str The buffer to be written from the socket. 480 | 481 | size_t count The number of bytes in the buffer. 482 | 483 | 484 | Authors: 485 | ottrey, 486 | marek (modified for meaningful error codes). 487 | 488 | Side Effects: 489 | This function will return -1 if the socket is closed during the read operation. 490 | 491 | Note that if a single line exceeds the length of count, the extra data 492 | will be read and discarded! You have been warned. 493 | 494 | ++++++++++++++++++++++++++++++++++++++*/ 495 | int SK_gets(int sockfd, char *str, size_t count) { 496 | int bytes_read; 497 | int total_count = 0; 498 | char *current_position; 499 | char last_read = 0; 500 | 501 | int control_c = 0; 502 | 503 | current_position = str; 504 | while (last_read != 10) { 505 | 506 | bytes_read = read(sockfd, &last_read, 1); 507 | if (bytes_read <= 0) { 508 | /* The other side may have closed unexpectedly */ 509 | return SK_DISCONNECT; 510 | /* Is this effective on other platforms than linux? */ 511 | } 512 | if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) { 513 | *current_position = last_read; 514 | current_position++; 515 | total_count++; 516 | } 517 | 518 | if (last_read == -1) { 519 | bytes_read = read(sockfd, &last_read, 1); 520 | if (last_read == -12) { 521 | ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c"); 522 | control_c = 1; 523 | ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT"); 524 | return SK_INTERRUPT; 525 | } 526 | } 527 | } 528 | if (count > 0) { 529 | *current_position = 0; 530 | } 531 | 532 | return total_count; 533 | 534 | } /* SK_gets() */ 535 | 536 | 537 | /* SK_puts() */ 538 | /*++++++++++++++++++++++++++++++++++++++ 539 | 540 | This function writes a character string out to a socket. 541 | 542 | int SK_puts The total_count of bytes written, 543 | or -1 on hangup, error, or timeout 544 | 545 | int sockfd The socket file descriptor. 546 | 547 | char *str The buffer to be written from the socket. 548 | 549 | const struct timeval *timeout Maximum time to wait between each 550 | write() call, or NULL for "forever". 551 | 552 | ++++++++++++++++++++++++++++++++++++++*/ 553 | int 554 | SK_puts(int sockfd, const char *str, const struct timeval *timeout) 555 | { 556 | int count_sent; 557 | if (SK_write(sockfd, str, strlen(str), timeout, &count_sent) <= 0) { 558 | return -1; 559 | } else { 560 | return count_sent; 561 | } 562 | } /* SK_puts() */ 563 | 564 | /* SK_putc() */ 565 | /*++++++++++++++++++++++++++++++++++++++ 566 | 567 | This function writes a single character out to a socket. 568 | 569 | int SK_putc Returns the number of characters written. 570 | 571 | int sockfd socket 572 | 573 | char ch character 574 | 575 | const struct timeval *timeout Maximum time to wait between each 576 | write() call, or NULL for "forever". 577 | 578 | ++++++++++++++++++++++++++++++++++++++*/ 579 | int 580 | SK_putc(int sockfd, char ch, const struct timeval *timeout) 581 | { 582 | int count_sent; 583 | SK_write(sockfd, &ch, 1, timeout, &count_sent); 584 | return count_sent; 585 | }/* SK_putc() */ 586 | 587 | /*++++++++++++++++++++++++++++++++++++++ 588 | 589 | This function reads a single character from a socket. 590 | 591 | returns EOF when no character can be read. 592 | 593 | ++++++++++++++++++++++++++++++++++++++*/ 594 | int SK_getc(int sockfd) { 595 | char ch; 596 | 597 | if( read(sockfd, &ch, 1) <= 0 ) { 598 | return EOF; 599 | } 600 | else { 601 | return ch; 602 | } 603 | }/* SK_getc() */ 604 | 605 | /* SK_getpeername() */ 606 | /*++++++++++++++++++++++++++++++++++++++ 607 | 608 | This function will tell you who is at the other end of a connected stream socket. 609 | 610 | char *SK_getpeername Returns allocated string with the IP in it, 611 | or "--" if the descriptor is not a socket, 612 | or NULL on error. 613 | 614 | int sockfd The socket or file descriptor. 615 | 616 | +html+ <PRE> 617 | Authors: 618 | ottrey, 619 | marek (modified error handling, made MT-Safe). 620 | +html+ </PRE> 621 | 622 | ++++++++++++++++++++++++++++++++++++++*/ 623 | char *SK_getpeername(int sockfd) 624 | { 625 | char *hostaddress=NULL; 626 | struct sockaddr_in addr_in; 627 | int namelen=sizeof(addr_in); 628 | 629 | if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) == 0) { 630 | 631 | dieif( wr_malloc((void **)&hostaddress, INET_ADDRSTRLEN) != UT_OK); 632 | inet_ntop(AF_INET, &(addr_in.sin_addr), hostaddress, INET_ADDRSTRLEN); 633 | } 634 | else { 635 | int er = errno; 636 | 637 | if( er == ENOTSOCK ) { 638 | hostaddress = wr_string("--"); 639 | } 640 | else { 641 | /* XXX: hack to avoid crash in the case where peer disconnects */ 642 | /* To fix this, the socket interface needs to deal with a structure 643 | containing not only the file descriptor, but also the address of 644 | the host and the peer. Other goodies, like the current time, 645 | time of last operation, and last errno could also be included 646 | for good measure. */ 647 | hostaddress = UT_strdup("127.0.0.1"); 648 | } 649 | } 650 | 651 | return hostaddress; 652 | 653 | } /* SK_getpeername() */ 654 | 655 | 656 | /* SK_getpeerip */ 657 | /*++++++++++++++++++++++++++++++++++++++ 658 | 659 | This function will check the ip of the connected peer and store it in the 660 | ip_addr_t structure defined in the IP module. 661 | 662 | int SK_getpeerip returns 0 on success, -1 on failure. 663 | 664 | int sockfd The socket descriptor (file will result in -1) 665 | 666 | ip_addr_t *ip Pointer to where the address should be stored. 667 | 668 | +html+ <PRE> 669 | Author: 670 | marek 671 | +html+ </PRE> 672 | ++++++++++++++++++++++++++++++++++++++*/ 673 | 674 | int SK_getpeerip(int sockfd, ip_addr_t *ip) { 675 | struct sockaddr_in addr_in; 676 | int namelen=sizeof(addr_in); 677 | int ret=-1; 678 | 679 | memset(& addr_in, 0, sizeof(struct sockaddr_in)); 680 | 681 | if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) { 682 | ret=0; 683 | IP_addr_s2b(ip, &addr_in, namelen); 684 | } else { 685 | /* XXX: hack to avoid crash in the case where peer disconnects */ 686 | /* To fix this, the socket interface needs to deal with a structure 687 | containing not only the file descriptor, but also the address of 688 | the host and the peer. Other goodies, like the current time, 689 | time of last operation, and last errno could also be included 690 | for good measure. */ 691 | ret = 0; 692 | addr_in.sin_family = AF_INET; 693 | addr_in.sin_addr.s_addr = INADDR_LOOPBACK; 694 | addr_in.sin_port = 0; 695 | IP_addr_s2b(ip, &addr_in, namelen); 696 | } 697 | 698 | return ret; 699 | } 700 |