Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

sockutils.c

Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 2002 - 2003 00003 * NetGroup, Politecnico di Torino (Italy) 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 3. Neither the name of the Politecnico di Torino nor the names of its 00016 * contributors may be used to endorse or promote products derived from 00017 * this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00022 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00023 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00025 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00026 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00027 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00029 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 00034 00048 #include "sockutils.h" 00049 #include <string.h> // for strerror() 00050 #include <errno.h> // for the errno variable 00051 #include <stdio.h> // for the stderr file 00052 #include <stdlib.h> // for malloc() and free() 00053 00054 00055 00056 00057 00058 00059 // WinSock Initialization 00060 #ifdef WIN32 00061 #define WINSOCK_MAJOR_VERSION 2 00062 #define WINSOCK_MINOR_VERSION 2 00063 int sockcount= 0; 00064 #endif 00065 00066 // Some minor differences between UNIX and Win32 00067 #ifdef WIN32 00068 #define SHUT_WR SD_SEND 00069 #define snprintf _snprintf 00070 #endif 00071 00072 00074 #define SOCK_ERRBUF_SIZE 1024 00075 00076 00077 // Constants; used in order to keep strings here 00078 #define SOCKET_NO_NAME_AVAILABLE "No name available" 00079 #define SOCKET_NO_PORT_AVAILABLE "No port available" 00080 #define SOCKET_NAME_NULL_DAD "Null address (possibly DAD Phase)" 00081 00082 00083 00084 00085 /**************************************************** 00086 * * 00087 * Locally defined functions * 00088 * * 00089 ****************************************************/ 00090 00091 int sock_ismcastaddr(const struct sockaddr *saddr); 00092 00093 00094 00095 00096 00097 /**************************************************** 00098 * * 00099 * Function bodies * 00100 * * 00101 ****************************************************/ 00102 00103 00124 void sock_geterror(const char *caller, char *errbuf, int errbuflen) 00125 { 00126 #ifdef WIN32 00127 int retval; 00128 int code; 00129 TCHAR message[SOCK_ERRBUF_SIZE]; /* It will be char (if we're using ascii) or wchar_t (if we're using unicode) */ 00130 00131 code= GetLastError(); 00132 00133 retval= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | 00134 FORMAT_MESSAGE_MAX_WIDTH_MASK, 00135 NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00136 message, sizeof(message) / sizeof(TCHAR), NULL); 00137 00138 if (retval == 0) 00139 { 00140 if (errbuf) 00141 { 00142 if ( (caller) && (*caller) ) 00143 snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller); 00144 else 00145 snprintf(errbuf, errbuflen, "Unable to get the exact error message"); 00146 00147 errbuf[errbuflen - 1]= 0; 00148 } 00149 00150 return; 00151 } 00152 00153 if (errbuf) 00154 { 00155 if ( (caller) && (*caller) ) 00156 snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, code); 00157 else 00158 snprintf(errbuf, errbuflen, "%s (code %d)", message, code); 00159 00160 errbuf[errbuflen - 1]= 0; 00161 } 00162 00163 00164 #else 00165 char *message; 00166 00167 message= strerror(errno); 00168 00169 if (errbuf) 00170 { 00171 if ( (caller) && (*caller) ) 00172 snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errno); 00173 else 00174 snprintf(errbuf, errbuflen, "%s (code %d)", message, errno); 00175 00176 errbuf[errbuflen - 1]= 0; 00177 } 00178 00179 #endif 00180 } 00181 00182 00183 00200 int sock_init(char *errbuf, int errbuflen) 00201 { 00202 #ifdef WIN32 00203 if (sockcount == 0) 00204 { 00205 WSADATA wsaData; // helper variable needed to initialize Winsock 00206 00207 // Ask for Winsock version 2.2. 00208 if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 00209 { 00210 if (errbuf) 00211 { 00212 snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n"); 00213 errbuf[errbuflen - 1]= 0; 00214 } 00215 00216 WSACleanup(); 00217 00218 return -1; 00219 } 00220 } 00221 00222 sockcount++; 00223 #endif 00224 00225 return 0; 00226 } 00227 00228 00229 00238 void sock_cleanup() 00239 { 00240 #ifdef WIN32 00241 sockcount--; 00242 00243 if (sockcount == 0) 00244 WSACleanup(); 00245 #endif 00246 } 00247 00248 00249 00255 int sock_ismcastaddr(const struct sockaddr *saddr) 00256 { 00257 if (saddr->sa_family == PF_INET) 00258 { 00259 struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr; 00260 if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0; 00261 else return -1; 00262 } 00263 else 00264 { 00265 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr; 00266 if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0; 00267 else return -1; 00268 } 00269 } 00270 00271 00272 00304 SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen) 00305 { 00306 SOCKET sock; 00307 00308 sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); 00309 if (sock == -1) 00310 { 00311 sock_geterror("socket(): ", errbuf, errbuflen); 00312 return -1; 00313 } 00314 00315 00316 // This is a server socket 00317 if (server) 00318 { 00319 #ifdef BSD 00320 // Force the use of IPv6-only addresses; in BSD you can accept both v4 and v6 00321 // connections if you have a "NULL" pointer as the nodename in the getaddrinfo() 00322 // This behaviour is not clear in the RFC 2553, so each system implements the 00323 // bind() differently from this point of view 00324 00325 if (addrinfo->ai_family == PF_INET6) 00326 { 00327 int on; 00328 00329 if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (int)) == -1) 00330 { 00331 if (errbuf) 00332 { 00333 snprintf(errbuf, errbuflen, "setsockopt(IPV6_BINDV6ONLY)"); 00334 errbuf[errbuflen - 1]= 0; 00335 } 00336 return -1; 00337 } 00338 } 00339 #endif 00340 00341 // WARNING: if the address is a mcast one, I should place the proper Win32 code here 00342 if (bind(sock, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) 00343 { 00344 sock_geterror("bind(): ", errbuf, errbuflen); 00345 return -1; 00346 } 00347 00348 if (addrinfo->ai_socktype == SOCK_STREAM) 00349 if (listen(sock, nconn) == -1) 00350 { 00351 sock_geterror("listen(): ", errbuf, errbuflen); 00352 return -1; 00353 } 00354 00355 // server side ended 00356 return sock; 00357 } 00358 else // we're the client 00359 { 00360 struct addrinfo *tempaddrinfo; 00361 char *errbufptr; 00362 int bufspaceleft; 00363 00364 tempaddrinfo= addrinfo; 00365 errbufptr= errbuf; 00366 bufspaceleft= errbuflen; 00367 *errbufptr= 0; 00368 00369 00370 // We have to loop though all the addinfo returned. 00371 // For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying 00372 // to connect to is unavailable in IPv6, so we have to try in IPv4 as well 00373 while (tempaddrinfo) 00374 { 00375 00376 if (connect(sock, tempaddrinfo->ai_addr, tempaddrinfo->ai_addrlen) == -1) 00377 { 00378 int msglen; 00379 char TmpBuffer[100]; 00380 char SocketErrorMessage[SOCK_ERRBUF_SIZE]; 00381 00382 // We have to retrieve the error message before any other socket call completes, otherwise 00383 // the error message is lost 00384 sock_geterror(NULL, SocketErrorMessage, sizeof(SocketErrorMessage) ); 00385 00386 // Returns the numeric address of the host that triggered the error 00387 sock_getascii_addrport( (struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer) ); 00388 00389 snprintf(errbufptr, bufspaceleft, "Is the server properly installed on %s? connect() failed: %s", TmpBuffer, SocketErrorMessage); 00390 00391 // In case more then one 'connect' fails, we manage to keep all the error messages 00392 msglen= strlen(errbufptr); 00393 00394 errbufptr[msglen]= ' '; 00395 errbufptr[msglen + 1]= 0; 00396 00397 bufspaceleft= bufspaceleft - (msglen + 1); 00398 errbufptr+= (msglen + 1); 00399 00400 tempaddrinfo= tempaddrinfo->ai_next; 00401 } 00402 else 00403 break; 00404 } 00405 00406 // Check how we exit from the previous loop 00407 // If tempaddrinfo is equal to NULL, it means that all the connect() failed. 00408 if (tempaddrinfo == NULL) 00409 { 00410 closesocket(sock); 00411 return -1; 00412 } 00413 else 00414 return sock; 00415 } 00416 } 00417 00418 00419 00420 00439 int sock_close(SOCKET sock, char *errbuf, int errbuflen) 00440 { 00441 // SHUT_WR: subsequent calls to the send function are disallowed. 00442 // For TCP sockets, a FIN will be sent after all data is sent and 00443 // acknowledged by the Server. 00444 if (shutdown(sock, SHUT_WR) ) 00445 { 00446 sock_geterror("shutdown(): ", errbuf, errbuflen); 00447 // close the socket anyway 00448 closesocket(sock); 00449 return -1; 00450 } 00451 00452 closesocket(sock); 00453 return 0; 00454 } 00455 00456 00457 00458 00459 00460 00499 int sock_initaddress(const char *address, const char *port, 00500 struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen) 00501 { 00502 int retval; 00503 00504 retval = getaddrinfo(address, port, hints, addrinfo); 00505 if (retval != 0) 00506 { 00507 // if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard 00508 // error routines (errno) in UNIX; WIN32 suggests using the GetLastError() instead. 00509 if (errbuf) 00510 #ifdef WIN32 00511 sock_geterror("getaddrinfo(): ", errbuf, errbuflen); 00512 #else 00513 if (errbuf) 00514 { 00515 snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval)); 00516 errbuf[errbuflen - 1]= 0; 00517 } 00518 #endif 00519 return -1; 00520 } 00526 // This software only supports PF_INET and PF_INET6. 00527 if (( (*addrinfo)->ai_family != PF_INET) && ( (*addrinfo)->ai_family != PF_INET6)) 00528 { 00529 if (errbuf) 00530 { 00531 snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported"); 00532 errbuf[errbuflen - 1]= 0; 00533 } 00534 return -1; 00535 } 00536 00537 if ( ( (*addrinfo)->ai_socktype == SOCK_STREAM) && (sock_ismcastaddr( (*addrinfo)->ai_addr) == 0) ) 00538 { 00539 if (errbuf) 00540 { 00541 snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams"); 00542 errbuf[errbuflen - 1]= 0; 00543 } 00544 00545 return -1; 00546 } 00547 00548 return 0; 00549 } 00550 00551 00552 00578 int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen) 00579 { 00580 int nsent; 00581 00582 send: 00583 #ifdef linux 00584 /* 00585 Another pain... in Linux there's this flag 00586 MSG_NOSIGNAL 00587 Requests not to send SIGPIPE on errors on stream-oriented 00588 sockets when the other end breaks the connection. 00589 The EPIPE error is still returned. 00590 */ 00591 nsent = send(socket, buffer, size, MSG_NOSIGNAL); 00592 #else 00593 nsent = send(socket, buffer, size, 0); 00594 #endif 00595 00596 if (nsent == -1) 00597 { 00598 sock_geterror("send(): ", errbuf, errbuflen); 00599 return -1; 00600 } 00601 00602 if (nsent != size) 00603 { 00604 size-= nsent; 00605 buffer+= nsent; 00606 goto send; 00607 } 00608 00609 return 0; 00610 } 00611 00612 00668 int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen) 00669 { 00670 00671 if ((*offset + size) > totsize) 00672 { 00673 if (errbuf) 00674 { 00675 snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer."); 00676 errbuf[errbuflen - 1]= 0; 00677 } 00678 00679 return -1; 00680 }; 00681 00682 if (!checkonly) 00683 memcpy(tempbuf + (*offset), buffer, size); 00684 00685 (*offset)+= size; 00686 00687 return 0; 00688 } 00689 00690 00691 00727 int sock_recv(SOCKET sock, char *buffer, int size, int receiveall, char *errbuf, int errbuflen) 00728 { 00729 int nread; 00730 int totread= 0; 00731 // We can obtain the same result using the MSG_WAITALL flag 00732 // However, this is not supported by recv() in Win32 00733 00734 if (size == 0) 00735 { 00736 SOCK_ASSERT("I have been requested to read zero bytes", 1); 00737 return 0; 00738 } 00739 00740 again: 00741 nread= recv(sock, &(buffer[totread]), size - totread, 0); 00742 00743 if (nread == -1) 00744 { 00745 sock_geterror("recv(): ", errbuf, errbuflen); 00746 return -1; 00747 } 00748 00749 if (nread == 0) 00750 { 00751 if (errbuf) 00752 { 00753 snprintf(errbuf, errbuflen, "The other host terminated the connection."); 00754 errbuf[errbuflen - 1]= 0; 00755 } 00756 00757 return -1; 00758 } 00759 00760 // If we want to return as soon as some data has been received, 00761 // let's do the job 00762 if (!receiveall) 00763 return nread; 00764 00765 totread+= nread; 00766 00767 if (totread != size) 00768 goto again; 00769 00770 return totread; 00771 } 00772 00773 00774 00800 int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen) 00801 { 00802 #define TEMP_BUF_SIZE 32768 00803 00804 char buffer[TEMP_BUF_SIZE]; // network buffer, to be used when the message is discarded 00805 00806 // A static allocation avoids the need of a 'malloc()' each time we want to discard a message 00807 // Our feeling is that a buffer if 32KB is enough for most of the application; 00808 // in case this is not enough, the "while" loop discards the message by calling the 00809 // sockrecv() several times. 00810 // We do not want to create a bigger variable because this causes the program to exit on 00811 // some platforms (e.g. BSD) 00812 00813 while (size > TEMP_BUF_SIZE) 00814 { 00815 if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1) 00816 return -1; 00817 00818 size-= TEMP_BUF_SIZE; 00819 } 00820 00821 // If there is still data to be discarded 00822 // In this case, the data can fit into the temporaty buffer 00823 if (size) 00824 { 00825 if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1) 00826 return -1; 00827 } 00828 00829 SOCK_ASSERT("I'm currently discarding data\n", 1); 00830 00831 return 0; 00832 } 00833 00834 00835 00864 int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen) 00865 { 00866 // checks if the connecting host is among the ones allowed 00867 if ( (hostlist) && (hostlist[0]) ) 00868 { 00869 char *token; // temp, needed to separate items into the hostlist 00870 struct addrinfo *addrinfo, *ai_next; 00871 char *temphostlist; 00872 00873 temphostlist= (char *) malloc (strlen(hostlist) + 1); 00874 if (temphostlist == NULL) 00875 { 00876 sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen); 00877 return -2; 00878 } 00879 00880 // The problem is that strtok modifies the original variable by putting '0' at the end of each token 00881 // So, we have to create a new temporary string in which the original content is kept 00882 strcpy(temphostlist, hostlist); 00883 00884 token= strtok(temphostlist, sep); 00885 00886 // it avoids a warning in the compilation ('addrinfo used but not initialized') 00887 addrinfo = NULL; 00888 00889 while( token != NULL ) 00890 { 00891 struct addrinfo hints; 00892 int retval; 00893 00894 addrinfo = NULL; 00895 memset(&hints, 0, sizeof (struct addrinfo) ); 00896 hints.ai_family = PF_UNSPEC; 00897 hints.ai_socktype= SOCK_STREAM; 00898 00899 retval = getaddrinfo(token, "0", &hints, &addrinfo); 00900 if (retval != 0) 00901 { 00902 if (errbuf) 00903 { 00904 snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval)); 00905 errbuf[errbuflen - 1]= 0; 00906 } 00907 00908 SOCK_ASSERT(errbuf, 1); 00909 00910 // Get next token 00911 token = strtok( NULL, sep); 00912 continue; 00913 } 00914 00915 // ai_next is required to preserve the content of addrinfo, in order to deallocate it properly 00916 ai_next= addrinfo; 00917 while(ai_next) 00918 { 00919 if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0) 00920 { 00921 free(temphostlist); 00922 return 0; 00923 } 00924 00925 // If we are here, it means that the current address does not matches 00926 // Let's try with the next one in the header chain 00927 ai_next= ai_next->ai_next; 00928 } 00929 00930 freeaddrinfo(addrinfo); 00931 addrinfo= NULL; 00932 00933 // Get next token 00934 token = strtok( NULL, sep); 00935 } 00936 00937 if (addrinfo) 00938 { 00939 freeaddrinfo(addrinfo); 00940 addrinfo= NULL; 00941 } 00942 00943 if (errbuf) 00944 { 00945 snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused."); 00946 errbuf[errbuflen - 1]= 0; 00947 } 00948 00949 free(temphostlist); 00950 return -1; 00951 } 00952 00953 // No hostlist, so we have to return 'empty list' 00954 return 1; 00955 } 00956 00957 00976 int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second) 00977 { 00978 if (first->ss_family == second->ss_family) 00979 { 00980 if (first->ss_family == AF_INET) 00981 { 00982 if (memcmp( &(((struct sockaddr_in *) first)->sin_addr), 00983 &(((struct sockaddr_in *) second)->sin_addr), 00984 sizeof(struct in_addr) ) == 0) 00985 return 0; 00986 } 00987 else // address family is AF_INET6 00988 { 00989 if (memcmp( &(((struct sockaddr_in6 *) first)->sin6_addr), 00990 &(((struct sockaddr_in6 *) second)->sin6_addr), 00991 sizeof(struct in6_addr) ) == 0) 00992 return 0; 00993 } 00994 } 00995 00996 return -1; 00997 } 00998 00999 01000 01042 int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) 01043 { 01044 struct sockaddr_storage mysockaddr; 01045 socklen_t sockaddrlen; 01046 01047 01048 sockaddrlen = sizeof(struct sockaddr_storage); 01049 01050 if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1) 01051 { 01052 sock_geterror("getsockname(): ", errbuf, errbuflen); 01053 return 0; 01054 } 01055 else 01056 { 01057 // Returns the numeric address of the host that triggered the error 01058 return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen); 01059 } 01060 01061 return 0; 01062 } 01063 01064 01065 01114 int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) 01115 { 01116 socklen_t sockaddrlen; 01117 int retval; // Variable that keeps the return value; 01118 01119 retval= -1; 01120 01121 #ifdef WIN32 01122 if (sockaddr->ss_family == AF_INET) 01123 sockaddrlen = sizeof(struct sockaddr_in); 01124 else 01125 sockaddrlen = sizeof(struct sockaddr_in6); 01126 #else 01127 sockaddrlen = sizeof(struct sockaddr_storage); 01128 #endif 01129 01130 if ((flags & NI_NUMERICHOST) == 0) // Check that we want literal names 01131 { 01132 if ( (sockaddr->ss_family == AF_INET6) && 01133 (memcmp( &((struct sockaddr_in6 *) sockaddr)->sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(struct in6_addr) ) == 0) ) 01134 { 01135 if (address) 01136 strncpy(address, SOCKET_NAME_NULL_DAD, addrlen); 01137 return retval; 01138 } 01139 } 01140 01141 if ( getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0) 01142 { 01143 // If the user wants to receive an error message 01144 if (errbuf) 01145 { 01146 sock_geterror("getnameinfo(): ", errbuf, errbuflen); 01147 errbuf[errbuflen-1]= 0; 01148 } 01149 01150 if (address) 01151 { 01152 strncpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen); 01153 address[addrlen-1]= 0; 01154 } 01155 01156 if (port) 01157 { 01158 strncpy(port, SOCKET_NO_PORT_AVAILABLE, portlen); 01159 port[portlen-1]= 0; 01160 } 01161 01162 retval= 0; 01163 } 01164 01165 return retval; 01166 } 01167 01168 01169 01206 int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen) 01207 { 01208 int retval; 01209 struct addrinfo *addrinfo; 01210 struct addrinfo hints; 01211 01212 memset(&hints, 0, sizeof(hints) ); 01213 01214 hints.ai_family= addr_family; 01215 01216 if ( (retval= sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1 ) 01217 return 0; 01218 01219 if (addrinfo->ai_family == PF_INET) 01220 memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in) ); 01221 else 01222 memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6) ); 01223 01224 if (addrinfo->ai_next != NULL) 01225 { 01226 freeaddrinfo(addrinfo); 01227 01228 if (errbuf) 01229 { 01230 snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned"); 01231 errbuf[errbuflen - 1]= 0; 01232 } 01233 01234 return -2; 01235 } 01236 01237 freeaddrinfo(addrinfo); 01238 return -1; 01239 } 01240 01241

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.