1/* ***************************************************************************** 2 3libcsc: BSD Network Socket Subsystem 4 5 ---------------------------------------------------------------- 6 7Copyright (c) 1999, 2000, 2001, 2002 Douglas R. Jerome, Peoria, AZ USA 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU Library General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU Library General Public 20 License along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 ---------------------------------------------------------------- 24 25FILE NAME 26 27 $RCSfile: csc_sock.c,v $ 28 $Revision: 1.5 $ 29 $Date: 2002/05/13 04:26:05 $ 30 31PROGRAM INFORMATION 32 33 Developed by: libcsc project 34 Developer: Douglas R. Jerome, drj, <jerome@primenet.com> 35 36FILE DESCRIPTION 37 38<SUBSYSTEM NAME="csc_sock"> 39 40NAME 41 csc_sock 42 43DESCRIPTION 44 BSD Network Socket Subsystem 45 46FUNCTIONS 47 CSCsockConnectTCP - initiate a socket connection 48 CSCsockConnectUDP - initiate a socket connection 49 CSCsockPassiveTCP - listen for connections on a socket 50 CSCsockPassiveUCP - listen for connections on a socket 51</SUBSYSTEM> 52 53CHANGE LOG 54 55 12may02 drj Small changes to support Solaris. 56 57 02may02 drj Small changes to support Solaris. 58 59 21apr02 drj Small comment changes. 60 Readded support for VxWorks. 61 62 11apr02 drj Changed `CSCgenfnType' to `CSCgenFnType'. 63 -- -- 64 65 25jun01 drj Converted to libcsc: renamed everything from rt to csc, 66 removed some debug message printing code. 67 68 11may00 drj Free()'d the piePtr calloc()'d in the local 69 getprotobyname(). 70 71 29apr99 drj Rebaselined from librt version 0.3.1. 72 73***************************************************************************** */ 74 75 76/* ************************************************************************* */ 77/* */ 78/* F e a t u r e S w i t c h e s */ 79/* */ 80/* ************************************************************************* */ 81 82/* 83 * Select these feature by moving them from the `if UNDEF' into the `else' 84 * section. 85 */ 86#ifdef UNDEF 87# define _POSIX_SOURCE 1 /* posix.1 */ 88# define _POSIX_C_SOURCE 199309L /* posix.1 and posix.4 */ 89# define _POSIX_C_SOURCE 199506L /* posix.1 and posix.4 and MORE */ 90#else 91# define _BSD_SOURCE 1 /* 4.3+bsd socket subsystem */ 92# ifndef _REENTRANT 93# define _REENTRANT /* thread-safe for glibc */ 94# endif 95#endif 96 97 98/* ************************************************************************* */ 99/* */ 100/* I n c l u d e d F i l e s */ 101/* */ 102/* ************************************************************************* */ 103 104/* 105 * OS Specific Header Files 106 */ 107#ifdef __vxworks__ 108# include <vxWorks.h> 109#endif 110#ifdef SOLARIS 111# include <strings.h> /* for bzero, bcopy */ 112#endif 113 114/* 115 * Standard C (ANSI) Header Files 116 */ 117#include <errno.h> 118#include <stdio.h> 119#include <stdlib.h> 120#include <string.h> 121 122/* 123 * Posix Header Files 124 */ 125#include <unistd.h> 126 127/* 128 * 4.3+BSD Header Files 129 */ 130#ifdef __vxworks__ 131# include <inetLib.h> 132# include <sockLib.h> 133#else 134# include <sys/socket.h> /* for BSD socket functions */ 135# include <netinet/in.h> /* for struct sockaddr_in */ 136# include <netdb.h> 137#endif 138 139/* 140 * Project Specific Header Files 141 */ 142#include "libcsc_debug.h" 143#include "libcsc.h" 144 145 146/* ************************************************************************* */ 147/* */ 148/* M a n i f e s t C o n s t a n t s */ 149/* */ 150/* ************************************************************************* */ 151 152/* (None.) */ 153 154 155/* ************************************************************************* */ 156/* */ 157/* E x t e r n a l R e f e r e n c e s */ 158/* */ 159/* ************************************************************************* */ 160 161#ifndef INADDR_NONE 162#define INADDR_NONE (0xFFFFFFFF) 163#endif 164 165#ifndef USHRT_MAX 166#define USHRT_MAX (65535) 167#endif 168 169/* 170 * This 4.3+bsd socket subsystem function is prototyped in arpa/in.h, but I 171 * don't want to include such an old header file. This sort of usage is also 172 * seen in Douglas E. Comer, David L. Stevens "Internetworking with TCP/IP 173 * Vol. III", bsd socket version, (Englewood Cliffs: Prentice Hall, 1993). 174 */ 175extern unsigned long inet_addr (const char*); 176 177 178/* ************************************************************************* */ 179/* */ 180/* S c a l a r D a t a T y p e s */ 181/* */ 182/* ************************************************************************* */ 183 184/* (None.) */ 185 186 187/* ************************************************************************* */ 188/* */ 189/* N o n - S c a l a r D a t a S t r u c t u r e s */ 190/* */ 191/* ************************************************************************* */ 192 193#ifdef __vxworks__ 194struct protoent 195 { 196 char* p_name; /* official protocol name */ 197 char** p_aliases; /* alias list */ 198 int p_proto; /* protocol number */ 199 }; 200struct servent 201 { 202 char* s_name; /* official service name */ 203 char** s_aliases; /* alias list */ 204 int s_port; /* port number */ 205 char* s_proto; /* protocol to use */ 206 }; 207#endif 208 209 210/* ************************************************************************* */ 211/* */ 212/* P u b l i c G l o b a l V a r i a b l e s */ 213/* */ 214/* ************************************************************************* */ 215 216/* (None.) */ 217 218 219/* ************************************************************************* */ 220/* */ 221/* P r i v a t e G l o b a l V a r i a b l e s */ 222/* */ 223/* ************************************************************************* */ 224 225#ifdef __vxworks__ 226PRIVATE char* tcpName = "tcp"; 227PRIVATE char* tcpAliases[] = { "TCP", "" }; 228PRIVATE char* udpName = "udp"; 229PRIVATE char* udpAliases[] = { "UDP", "" }; 230#endif 231 232 233/* ************************************************************************* */ 234/* */ 235/* E x e c u t a b l e C o d e (Locally Used Functions) */ 236/* */ 237/* ************************************************************************* */ 238 239 240/************************************************************************** 241 * Private Function Prototypes 242 **************************************************************************/ 243 244#ifdef __vxworks__ 245PRIVATE struct protoent* getprotobyname (char* name); 246PRIVATE struct servent* getservbyname (char* name, char* proto); 247#endif 248 249PRIVATE int connectSocket ( 250 int* const sPtr, 251 const char* host, 252 const char* service, 253 const char* protocol, 254 CSCgenFnType callbackFn 255 ); 256 257PRIVATE int passiveSocket ( 258 int* const sPtr, 259 const char* service, 260 const char* protocol, 261 int backlog, 262 CSCgenFnType callbackFn 263 ); 264 265 266/* ---------------------------------------------------------------------- */ 267 268 269#ifdef __vxworks__ 270 271/************************************************************************** 272 * Private Function getprotobyname 273 **************************************************************************/ 274 275PRIVATE struct protoent* getprotobyname (char* name) 276 { 277 struct protoent* retPtr = NULL; 278 279 retPtr = calloc (1, sizeof(struct protoent)); 280 if (strcmp(name,"tcp") == 0) /* transmission control protocol */ 281 { 282 retPtr->p_name = tcpName; 283 retPtr->p_aliases = tcpAliases; 284 retPtr->p_proto = 6; 285 } 286 if (strcmp(name,"ucp") == 0) /* user datagram protocol */ 287 { 288 retPtr->p_name = udpName; 289 retPtr->p_aliases = udpAliases; 290 retPtr->p_proto = 17; 291 } 292 293 return (retPtr); 294 } 295 296 297/************************************************************************** 298 * Private Function getservbyname 299 **************************************************************************/ 300 301PRIVATE struct servent* getservbyname (char* name, char* proto) 302 { 303 struct servent* retPtr = NULL; 304 305/* 306 * These assignments avoid compiler warnings about unused things. 307 */ 308 name = name; 309 proto = proto; 310 311 return (retPtr); 312 } 313 314#endif 315 316 317/************************************************************************** 318 * Private Function connectSocket 319 **************************************************************************/ 320 321PRIVATE int connectSocket ( 322 int* const sPtr, 323 const char* host, 324 const char* service, 325 const char* protocol, 326 CSCgenFnType callbackFn 327 ) 328 { 329 struct sockaddr_in sin; /* Internet Endpoint Address */ 330#ifndef __vxworks__ 331 struct hostent* hiePtr; /* Host Name Information Entry Pointer */ 332#endif 333 struct servent* siePtr; /* Service Information Entry Pointer */ 334 struct protoent* piePtr; /* Protocol Information Entry Pointer */ 335 int sFd; /* Socket Descriptor */ 336 int sType; /* Socket Descriptor Type */ 337 int sSize; /* Socket Descriptor Size */ 338 int port; /* Temporary Port Number */ 339 int myErrNo; /* Temporary errno */ 340 char errBuf[80]; 341 342 ASSERT_RTN (sPtr != NULL, "connectSocket: NULL sPtr", CSC_BADARG); 343 ASSERT_RTN (host != NULL, "connectSocket: NULL host", CSC_BADARG); 344 ASSERT_RTN (service != NULL, "connectSocket: NULL service", CSC_BADARG); 345 ASSERT_RTN (protocol != NULL, "connectSocket: NULL protocol", CSC_BADARG); 346 347 /* 348 * Assume failure. 349 */ 350 *sPtr = -1; 351 352 /* 353 * Clear the IP address endpoint structure then set it (correctly) with an 354 * Internet Address Family. 355 */ 356 bzero ((char *)&sin, sizeof(struct sockaddr_in)); 357 sin.sin_family = AF_INET; 358 359 /* 360 * Use the host as a name to get the host's IP address; if this fails, then 361 * assume the host is an ASCII-Z string of the host IP address itself. 362 */ 363#ifndef __vxworks__ 364 if ((hiePtr=gethostbyname(host)) != NULL) 365 bcopy (hiePtr->h_addr, (char*)&sin.sin_addr, hiePtr->h_length); 366 else 367#endif 368 { 369 sin.sin_addr.s_addr = inet_addr (host); 370 if (sin.sin_addr.s_addr == INADDR_NONE) 371 { 372 myErrNo = errno; 373 sprintf (errBuf, "can't get %s host entry (errno %d)", host, myErrNo); 374 if (callbackFn != NULL) (*callbackFn) (CSC_NOSOCK, myErrNo, errBuf); 375 return (CSC_NOTFOUND); 376 } 377 } 378 379 /* 380 * Use the service as a name to get the port number; if this fails, then 381 * assume the service is an ASCII-Z string of the port number itself. 382 */ 383 if ((siePtr=getservbyname((char*)service,(char*)protocol)) != NULL) 384 sin.sin_port = siePtr->s_port; /* This already is in host format. */ 385 else 386 { 387 port = atoi (service); 388 if (port > USHRT_MAX) 389 { 390 sprintf ( 391 errBuf, 392 "using service entry %s as port number; it is too big", 393 service 394 ); 395 if (callbackFn != NULL) (*callbackFn) (CSC_NOSVC, CSC_ERROR, errBuf); 396 return (CSC_NOSVC); 397 } 398 if (port != 0) 399 sin.sin_port = htons (port); 400 else 401 { 402 sprintf (errBuf, "can't make sense of service entry %s", service); 403 if (callbackFn != NULL) 404 (*callbackFn) (CSC_NOSVC, CSC_ERROR, errBuf); 405 return (CSC_NOSVC); 406 } 407 } 408 409 /* 410 * Map the protocol name to its protocol number. 411 */ 412 if ((piePtr=getprotobyname((char*)protocol)) == 0) 413 { 414 sprintf (errBuf, "can't make sense of protocol entry %s", protocol); 415 if (callbackFn != NULL) (*callbackFn) (CSC_NOPROT, CSC_ERROR, errBuf); 416#ifdef __vxworks__ 417 (void)free (piePtr); /* it was calloc()'d in the local getprotobyname() */ 418#endif 419 return (CSC_NOPROT); 420 } 421 422 /* 423 * Use protocol to choose a socket type. NOTE: if protocol is not correct, 424 * then the code above would have returned false from this function. 425 */ 426 sType = SOCK_STREAM; 427 if (strcmp(protocol,"udp")==0) sType = SOCK_DGRAM; 428 429 /* 430 * Allocate a socket. Notice the correct use of PF_INET (Protocol Family: 431 * InterNET). 432 */ 433 sFd = socket (PF_INET, sType, piePtr->p_proto); 434#ifdef __vxworks__ 435 (void)free (piePtr); /* it was calloc()'d in the local getprotobyname() */ 436#endif 437 if (sFd < 0) 438 { 439 myErrNo = errno; 440 sprintf (errBuf, "can't create socket (errno %d)", myErrNo); 441 if (callbackFn != NULL) (*callbackFn) (CSC_NOSOCK, myErrNo, errBuf); 442 return (CSC_NOSOCK); 443 } 444 445 /* 446 * bind() is not required: the port number on this machine, through 447 * which the connection is made, is dynamically allocated by the 448 * operating system's BSD network socket subsystem. 449 */ 450 451 /* 452 * Make the connection 453 */ 454 sSize = sizeof (struct sockaddr_in); 455 if (connect(sFd,(struct sockaddr*)&sin,sSize) < 0) 456 { 457 myErrNo = errno; 458 sprintf (errBuf, "can't make connection (errno %d)", myErrNo); 459 if (callbackFn != NULL) (*callbackFn) (CSC_NOSOCK, myErrNo, errBuf); 460 return (CSC_NOSOCK); 461 } 462 463 /* 464 * Return OK 465 */ 466 *sPtr = sFd; 467 return (CSC_OK); 468 } 469 470 471/************************************************************************** 472 * Private Function passiveSocket 473 **************************************************************************/ 474 475PRIVATE int passiveSocket ( 476 int* const sPtr, 477 const char* service, 478 const char* protocol, 479 int backlog, 480 CSCgenFnType callbackFn 481 ) 482 { 483 struct sockaddr_in sin; /* Internet Endpoint Address */ 484 struct protoent* piePtr; /* Protocol Information Entry Pointer */ 485 struct servent* siePtr; /* Service Information Entry Pointer */ 486 int sFd; /* Socket Descriptor */ 487 int sType; /* Socket Descriptor Type */ 488 int sSize; /* Socket Descriptor Size */ 489 int port; /* Temporary Port Number */ 490 int myErrNo; 491 char errBuf[80]; 492 493 ASSERT_RTN (sPtr != NULL, "passiveSocket: NULL sPtr", CSC_BADARG); 494 ASSERT_RTN (service != NULL, "passiveSocket: NULL service", CSC_BADARG); 495 ASSERT_RTN (protocol != NULL, "passiveSocket: NULL protocol", CSC_BADARG); 496 ASSERT_RTN (backlog != 0, "passiveSocket: no backlog", CSC_BADARG); 497 498 /* 499 * Assume failure. 500 */ 501 *sPtr = -1; 502 503 /* 504 * Clear the IP address endpoint structure, then set it with an Internet 505 * Address Family and set it to accept a connection from any IP. Notice the 506 * correct use of AF_INET (Address Family: InterNET). 507 */ 508 bzero ((char *)&sin, sizeof(struct sockaddr_in)); 509 sin.sin_family = AF_INET; 510 sin.sin_addr.s_addr = htonl (INADDR_ANY); 511 512 /* 513 * Use the service as a name to get the port number; if this fails, then 514 * assume the service is an ASCII-Z string of the port number itself. 515 */ 516 if ((siePtr=getservbyname((char*)service,(char*)protocol)) != NULL) 517 sin.sin_port = siePtr->s_port; /* This already is in host format. */ 518 else 519 { 520 port = atoi (service); 521 if (port > USHRT_MAX) 522 { 523 sprintf ( 524 errBuf, 525 "using service entry %s as port number; it is too big", 526 service 527 ); 528 if (callbackFn != NULL) (*callbackFn) (CSC_NOSVC, CSC_ERROR, errBuf); 529 return (CSC_NOSVC); 530 } 531 if ((sin.sin_port=htons(port)) == 0) 532 { 533 sprintf (errBuf, "can't make sense of service entry %s", service); 534 if (callbackFn != NULL) (*callbackFn) (CSC_NOSVC, CSC_ERROR, errBuf); 535 return (CSC_NOSVC); 536 } 537 } 538 port = sin.sin_port; 539 540 /* 541 * Map the protocol name to its protocol number. 542 */ 543 if ((piePtr=getprotobyname((char*)protocol)) == 0) 544 { 545 sprintf (errBuf, "can't make sense of protocol entry %s", protocol); 546 if (callbackFn != NULL) (*callbackFn) (CSC_NOPROT, CSC_ERROR, errBuf); 547 return (CSC_NOPROT); 548 } 549 550 /* 551 * Use protocol to choose a socket type. NOTE: if protocol is not correct, 552 * then the code above would have returned false from this function. 553 */ 554 sType = SOCK_STREAM; 555 if (strcmp(protocol,"udp")==0) sType = SOCK_DGRAM; 556 557 /* 558 * Allocate a socket. Notice the correct use of PF_INET (Protocol Family: 559 * InterNET). 560 */ 561 sFd = socket (PF_INET, sType, piePtr->p_proto); 562 if (sFd < 0) 563 { 564 myErrNo = errno; 565 sprintf (errBuf, "can't create socket (errno %d)", myErrNo); 566 if (callbackFn != NULL) (*callbackFn) (CSC_NOSOCK, myErrNo, errBuf); 567 return (CSC_NOSOCK); 568 } 569 570 /* 571 * Allow this server to be quickly brought back up. The socket is set to be 572 * able to reuse the same port; otherwise, the TIME_WAIT phenomenon will 573 * prevent binding to the local address. 574 * 575 * This is particularly useful when the server has been shut down and then 576 * quickly restarted (while the sockets are still active on its port). 577 * Unexpected data may come in and it may confuse the server; but while this 578 * is possible, it is very not likely: 579 * 580 * "A socket is a 5-tuple (protocol, local address, local port, 581 * remote address, remote port). SO_REUSEADDR just says that 582 * you can reuse local addresses. The 5-tuple still must be 583 * unique!" -- Michael Hunter (mphunter@qnx.com) 584 * 585 * This is why it is very unlikely that unexpected data will ever be seen by 586 * the server. The danger is that such a 5-tuple is still floating around on 587 * the network, and while it is bouncing around a new connection from the 588 * same client (on the same system) happens to get the same remote port. 589 * 590 * Thanks to Vic Metcalfe (vic@acm.org) et. al. Most of this data in this 591 * comment block came from his FAQ: 592 * ``Programming UNIX Sockets in C - Frequently Asked Questions'' 593 * dated March 28, 1998. The FAQ was found at 594 * http://www.ibrado.com/sock-faq/ 595 */ 596 { 597 int on = 1; 598 if (setsockopt(sFd,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on)) < 0) 599 { 600 myErrNo = errno; 601 sprintf (errBuf, "can't set SO_REUSEADDR on socket (errno %d)", myErrNo); 602 if (callbackFn != NULL) (*callbackFn) (CSC_NOSOCK, myErrNo, errBuf); 603 return (CSC_NOSOCK); 604 } 605 } 606 607 /* 608 * Bind the socket. 609 */ 610 sSize = sizeof (struct sockaddr_in); 611 if (bind(sFd,(struct sockaddr*)&sin,sSize) < 0) 612 { 613 myErrNo = errno; 614 sprintf ( 615 errBuf, 616 "can't bind service %s to port %d (errno %d)", 617 service, port, myErrNo 618 ); 619 if (callbackFn != NULL) (*callbackFn) (CSC_NOBIND, myErrNo, errBuf); 620 return (CSC_NOBIND); 621 } 622 623 /* 624 * Listen for something on the port. I've found out that a client's 625 * connect() can succeed at this point (before the server's accept())! 626 */ 627 if (sType == SOCK_STREAM) 628 if (listen(sFd,backlog) < 0) 629 { 630 myErrNo = errno; 631 sprintf ( 632 errBuf, 633 "can't listen on service %s port %d (errno %d)", 634 service, port, myErrNo 635 ); 636 if (callbackFn != NULL) (*callbackFn) (CSC_NOLISTEN, myErrNo, errBuf); 637 return (CSC_NOLISTEN); 638 } 639 640 /* 641 * Return OK 642 */ 643 *sPtr = sFd; 644 return (CSC_OK); 645 } 646 647 648 649/* ************************************************************************* */ 650/* */ 651/* E x e c u t a b l e C o d e (External Interface Functions) */ 652/* */ 653/* ************************************************************************* */ 654 655 656/*************************************************************************** 657 * Public Function CSCsockConnectTCP 658 *************************************************************************** 659 660<SUBROUTINE NAME="CSCsockConnectUDP"> 661 662NAME 663 CSCsockConnectTCP - initiate a socket connection 664 665SYNOPSYS 666 #include "libcsc.h" 667 668 int CSCsockConnectTCP ( 669 int* const socketPtr, 670 const char* host, 671 const char* service, 672 CSCgenFnType errorCallback 673 ); 674 675RETURN VALUE 676 CSC_OK .......... successful, and the integer pointed to by socketPtr 677 will be updated with the new socket descriptor 678 679 CSC_NOTFOUND .... can't make sense of host 680 681 CSC_NOSVC ....... can't make sense of service 682 683 CSC_NOPROT ...... can't make any sense out of the UDP protocol 684 685 CSC_NOSOCK ...... can't allocate a new socket or can't set a socket 686 option 687 688 CSC_BADARG ...... socketPtr or service is NULL or connectCount is zero 689 690DESCRIPTION 691 CSCsockConnectTCP() attempts to create a PF_INET (IPv4) protocol 692 socket and make a TCP (SOCK_STREAM) connection to another socket. 693 694 The other socket to which to connect is expected to be on `host' and 695 `service', where `host' is the hostname or IP address, and `service' is 696 the service or port number. If `service' specifies port number, then the 697 integer value must fit in an unsigned 16 bit variable 698 (0 <= sevice <= 65535). For example: 699 700 host service 701 ---- ------- 702 "batman" "telnet" 703 "spidergirl" "5200" 704 "198.168.0.2" "finger" 705 "198.168.0.2" "5200" 706 707 Error conditions are announced via `errorCallback', if it is not NULL. 708 The `errorCallback' function is called with the CSCsockConnectTCP() 709 return value, errno, and a string describing the error e.g., 710 711 (*errorCallback) (CSC_NOSOCK, errno, "can't create socket"); 712 713SEE ALSO 714 CSCsockConnectUDP(3) 715 CSCsockPassiveTCP(3) 716 CSCsockPassiveUDP(3) 717</SUBROUTINE> 718 719 ***************************************************************************/ 720 721PUBLIC int (CSCsockConnectTCP) ( 722 int* const socketPtr, 723 const char* host, 724 const char* service, 725 CSCgenFnType errorCallback 726 ) 727 { 728 ASSERT_RTN ( \ 729 socketPtr != NULL, \ 730 "CSCsockPassiveTCP: NULL socketPtr", \ 731 CSC_BADARG \ 732 ); 733 ASSERT_RTN ( \ 734 host != NULL, \ 735 "CSCsockPassiveTCP: NULL host", \ 736 CSC_BADARG \ 737 ); 738 ASSERT_RTN ( \ 739 service != NULL, \ 740 "CSCsockPassiveTCP: NULL service", \ 741 CSC_BADARG \ 742 ); 743 return (connectSocket(socketPtr,host,service,"tcp",errorCallback)); 744 } 745 746/*************************************************************************** 747 * Public Function CSCsockConnectUDP 748 *************************************************************************** 749 750<SUBROUTINE NAME="CSCsockConnectUDP"> 751 752NAME 753 CSCsockConnectUDP - initiate a socket connection 754 755SYNOPSYS 756 #include "libcsc.h" 757 758 int CSCsockConnectUDP ( 759 int* const socketPtr, 760 const char* host, 761 const char* service, 762 CSCgenFnType errorCallback 763 ); 764 765RETURN VALUE 766 CSC_OK .......... successful, and the integer pointed to by socketPtr 767 will be updated with the new socket descriptor 768 769 CSC_NOTFOUND .... can't make sense of host 770 771 CSC_NOSVC ....... can't make sense of service 772 773 CSC_NOPROT ...... can't make any sense out of the UDP protocol 774 775 CSC_NOSOCK ...... can't allocate a new socket or can't set a socket 776 option 777 778 CSC_BADARG ...... socketPtr or service is NULL or connectCount is zero 779 780DESCRIPTION 781 CSCsockConnectUDP() attempts to create a PF_INET (IPv4) protocol 782 socket and make a UDP (SOCK_DGRAM) connection to another socket. 783 784 The other socket to which to connect is expected to be on `host' and 785 `service', where `host' is the hostname or IP address, and `service' is 786 the service or port number. If `service' specifies port number, then the 787 integer value must fit in an unsigned 16 bit variable 788 (0 <= sevice <= 65535). For example: 789 790 host service 791 ---- ------- 792 "batman" "telnet" 793 "spidergirl" "5200" 794 "198.168.0.2" "finger" 795 "198.168.0.2" "5200" 796 797 Error conditions are announced via `errorCallback', if it is not NULL. 798 The `errorCallback' function is called with the CSCsockConnectUDP() 799 return value, errno, and a string describing the error e.g., 800 801 (*errorCallback) (CSC_NOSOCK, errno, "can't create socket"); 802 803BUGS 804 There's no "connection" in UDP! CSCsockConnectUDP() probably shouldn't 805 call connect() to make a connection. 806 807SEE ALSO 808 CSCsockConnectTCP(3) 809 CSCsockPassiveTCP(3) 810 CSCsockPassiveUDP(3) 811</SUBROUTINE> 812 813 ***************************************************************************/ 814 815PUBLIC int (CSCsockConnectUDP) ( 816 int* const socketPtr, 817 const char* host, 818 const char* service, 819 CSCgenFnType errorCallback 820 ) 821 { 822 ASSERT_RTN ( \ 823 socketPtr != NULL, \ 824 "CSCsockPassiveUDP: NULL socketPtr", \ 825 CSC_BADARG \ 826 ); 827 ASSERT_RTN ( \ 828 host != NULL, \ 829 "CSCsockPassiveUDP: NULL host", \ 830 CSC_BADARG \ 831 ); 832 ASSERT_RTN ( \ 833 service != NULL, \ 834 "CSCsockPassiveUDP: NULL service", \ 835 CSC_BADARG \ 836 ); 837 return (connectSocket(socketPtr,host,service,"udp",errorCallback)); 838 } 839 840 841/*************************************************************************** 842 * Public Function CSCsockPassiveTCP 843 *************************************************************************** 844 845<SUBROUTINE NAME="CSCsockPassiveTCP"> 846 847NAME 848 CSCsockPassiveTCP - listen for connections on a socket 849 850SYNOPSYS 851 #include "libcsc.h" 852 853 int CSCsockPassiveTCP ( 854 int* const socketPtr, 855 const char* service, 856 int connectCount, 857 CSCgenFnType errorCallback 858 ); 859 860RETURN VALUE 861 CSC_OK .......... successful, and the integer pointed to by socketPtr 862 will be updated with the new socket descriptor 863 864 CSC_NOSVC ....... can't make sense of service 865 866 CSC_NOPROT ...... can't make any sense out of the UDP protocol 867 868 CSC_NOSOCK ...... can't allocate a new socket or can't set a socket 869 option 870 871 CSC_NOBIND ...... can't bind socket to service 872 873 CSC_NOLISTEN .... can't listen to socket 874 875 CSC_BADARG ...... socketPtr or service is NULL or connectCount is zero 876 877DESCRIPTION 878 CSCsockPassiveTCP() attempts to create a PF_INET (IPv4) protocol socket 879 and prepares it to accept TCP (SOCK_STREAM) connections. No accept() is 880 actually tried, this must be done after calling CSCsockPassiveTCP(). 881 882 If successful, CSCsockPassiveTCP() creates a socket that is prepared 883 to accept a connection from any IP. 884 885 The `service' argument is a string that represents the the service (see 886 /etc/services) or port number. If `service' specifies port number, then 887 the integer value must fit in an unsigned 16 bit variable 888 (0 <= sevice <= 65535). For example: 889 890 service 891 ------- 892 "echo" 893 "5200" 894 "fsp" 895 "7200" 896 897 The socket is set with the SO_REUSEADDR option to enable quick reuse of 898 the same port. 899 900 `connectCount' is the connection backlog (the number of allowed 901 concurrent connections). 902 903 Error conditions are announced via `errorCallback', if it is not NULL. 904 The `errorCallback' function is called with the CSCsockPassiveUDP() 905 return value, errno, and a string describing the error e.g., 906 907 (*errorCallback) (CSC_NOSOCK, errno, "can't create socket"); 908 909BUGS 910 Cannot select a desired host from which to accept a connection. 911 912SEE ALSO 913 CSCsockConnectTCP(3) 914 CSCsockConnectUDP(3) 915 CSCsockPassiveUDP(3) 916</SUBROUTINE> 917 918 ***************************************************************************/ 919 920PUBLIC int (CSCsockPassiveTCP) ( 921 int* const socketPtr, 922 const char* service, 923 int connectCount, 924 CSCgenFnType errorCallback 925 ) 926 { 927 ASSERT_RTN ( \ 928 socketPtr != NULL, \ 929 "CSCsockPassiveTCP: NULL socketPtr", \ 930 CSC_BADARG \ 931 ); 932 ASSERT_RTN ( \ 933 service != NULL, \ 934 "CSCsockPassiveTCP: NULL service", \ 935 CSC_BADARG \ 936 ); 937 ASSERT_RTN ( \ 938 connectCount != 0, \ 939 "CSCsockPassiveTCP: no connectCount", \ 940 CSC_BADARG \ 941 ); 942 return (passiveSocket(socketPtr,service,"tcp",connectCount,errorCallback)); 943 } 944 945 946/*************************************************************************** 947 * Public Function CSCsockPassiveUDP 948 *************************************************************************** 949 950<SUBROUTINE NAME="CSCsockPassiveUDP"> 951 952NAME 953 CSCsockPassiveUDP - listen for connections on a socket 954 955SYNOPSYS 956 #include "libcsc.h" 957 958 int CSCsockPassiveUDP ( 959 int* const socketPtr, 960 const char* service, 961 int connectCount, 962 CSCgenFnType errorCallback 963 ); 964 965RETURN VALUE 966 CSC_OK .......... successful, and the integer pointed to by socketPtr 967 will be updated with the new socket descriptor 968 969 CSC_NOSVC ....... can't make sense of service 970 971 CSC_NOPROT ...... can't make any sense out of the UDP protocol 972 973 CSC_NOSOCK ...... can't allocate a new socket or can't set a socket 974 option 975 976 CSC_NOBIND ...... can't bind socket to service 977 978 CSC_NOLISTEN .... can't listen to socket 979 980 CSC_BADARG ...... socketPtr or service is NULL or connectCount is zero 981 982DESCRIPTION 983 CSCsockPassiveUDP() attempts to create a PF_INET (IPv4) protocol socket 984 and prepares it to accept UDP (SOCK_DGRAM) connections. 985 986 If successful, CSCsockPassiveUDP() creates a socket that is prepared 987 to accept a datagrams from any IP. 988 989 The `service' argument is a string that represents the the service (see 990 /etc/services) or port number. If `service' specifies port number, then 991 the integer value must fit in an unsigned 16 bit variable 992 (0 <= sevice <= 65535). For example: 993 994 service 995 ------- 996 "echo" 997 "5200" 998 "fsp" 999 "7200" 1000 1001 The socket is set with the SO_REUSEADDR option to enable quick reuse of 1002 the same port. 1003 1004 `connectCount' is the connection backlog (the number of allowed 1005 concurrent connections). 1006 1007 Error conditions are announced via `errorCallback', if it is not NULL. 1008 The `errorCallback' function is called with the CSCsockPassiveUDP() 1009 return value, errno, and a string describing the error e.g., 1010 1011 (*errorCallback) (CSC_NOSOCK, errno, "can't create socket"); 1012 1013BUGS 1014 There's no "connection" in UDP! This function should be re-coded to 1015 remove the TCPisms. I think this function has never been used. 1016 1017SEE ALSO 1018 CSCsockConnectTCP(3) 1019 CSCsockConnectUDP(3) 1020 CSCsockPassiveTCP(3) 1021</SUBROUTINE> 1022 1023 ***************************************************************************/ 1024 1025PUBLIC int (CSCsockPassiveUDP) ( 1026 int* const socketPtr, 1027 const char* service, 1028 int connectCount, 1029 CSCgenFnType errorCallback 1030 ) 1031 { 1032 ASSERT_RTN ( \ 1033 socketPtr != NULL, \ 1034 "CSCsockPassiveUDP: NULL socketPtr", \ 1035 CSC_BADARG \ 1036 ); 1037 ASSERT_RTN ( \ 1038 service != NULL, \ 1039 "CSCsockPassiveUDP: NULL service", \ 1040 CSC_BADARG \ 1041 ); 1042 ASSERT_RTN ( \ 1043 connectCount != 0, \ 1044 "CSCsockPassiveUDP: no connectCount", \ 1045 CSC_BADARG \ 1046 ); 1047 return (passiveSocket(socketPtr,service,"udp",connectCount,errorCallback)); 1048 } 1049 1050 1051/* End of file. */ 1052