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