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
    00053
    00054
    00055
    00056
    00057
    00058 // WinSock Initialization
    00059 #ifdef WIN32
    00060     #define WINSOCK_MAJOR_VERSION 2
    00061     #define WINSOCK_MINOR_VERSION 2
    00062     int sockcount= 0;
    00063 #endif
    00064
    00065 // Some minor differences between UNIX and Win32
    00066 #ifdef WIN32
    00067     #define SHUT_WR SD_SEND
    00068     #define snprintf _snprintf
    00069 #endif
    00070
    00071
    00073 #define SOCK_ERRBUF_SIZE 1024
    00074
    00075
    00076     // Constants; used in order to keep strings here
    00077 #define SOCKET_NO_NAME_AVAILABLE "No name available"
    00078 #define SOCKET_NO_PORT_AVAILABLE "No port available"
    00079 #define SOCKET_NAME_NULL_DAD "Null address (DAD Phase)"
    00080
    00081
    00082
    00083
    00084 /****************************************************
    00085  *                                                  *
    00086  * Locally defined functions                        *
    00087  *                                                  *
    00088  ****************************************************/
    00089
    00090 int sock_ismcastaddr(const struct sockaddr *saddr);
    00091
    00092
    00093
    00094
    00095
    00096 /****************************************************
    00097  *                                                  *
    00098  * Function bodies                                  *
    00099  *                                                  *
    00100  ****************************************************/
    00101
    00102
    00123 void sock_geterror(const char *caller, char *errbuf, int errbuflen)
    00124 {
    00125 #ifdef WIN32
    00126     int retval;
    00127     int code;
    00128     TCHAR message[SOCK_ERRBUF_SIZE];    /* It will be char (if we're using ascii) or wchar_t (if we're using unicode) */
    00129
    00130         code= GetLastError();
    00131
    00132         retval= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
    00133                       FORMAT_MESSAGE_MAX_WIDTH_MASK,
    00134                       NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00135                       message, sizeof(message) / sizeof(TCHAR), NULL);
    00136
    00137         if (retval == 0)
    00138         {
    00139             if (errbuf)
    00140             {
    00141                 snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
    00142                 errbuf[errbuflen - 1]= 0;
    00143             }
    00144
    00145             return;
    00146         }
    00147
    00148         if (errbuf)
    00149         {
    00150             snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, code);
    00151             errbuf[errbuflen - 1]= 0;
    00152         }
    00153
    00154
    00155 #else
    00156     char *message;
    00157
    00158         message= strerror(errno);
    00159
    00160         if (errbuf)
    00161         {
    00162             snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errno);
    00163             errbuf[errbuflen - 1]= 0;
    00164         }
    00165
    00166 #endif
    00167 }
    00168
    00169
    00170
    00187 int sock_init(char *errbuf, int errbuflen)
    00188 {
    00189 #ifdef WIN32
    00190     if (sockcount == 0)
    00191     {
    00192     WSADATA wsaData;            // helper variable needed to initialize Winsock
    00193
    00194         // Ask for Winsock version 2.2.
    00195         if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    00196         {
    00197             if (errbuf)
    00198             {
    00199                 snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
    00200                 errbuf[errbuflen - 1]= 0;
    00201             }
    00202
    00203             WSACleanup();
    00204
    00205             return -1;
    00206         }
    00207     }
    00208
    00209     sockcount++;
    00210 #endif
    00211
    00212     return 0;
    00213 }
    00214
    00215
    00216
    00225 void sock_cleanup()
    00226 {
    00227 #ifdef WIN32
    00228     sockcount--;
    00229
    00230     if (sockcount == 0)
    00231         WSACleanup();
    00232 #endif
    00233 }
    00234
    00235
    00236
    00242 int sock_ismcastaddr(const struct sockaddr *saddr)
    00243 {
    00244     if (saddr->sa_family == PF_INET)
    00245     {
    00246         struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr;
    00247         if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0;
    00248         else return -1;
    00249     }
    00250     else
    00251     {
    00252         struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
    00253         if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0;
    00254         else return -1;
    00255     }
    00256 }
    00257
    00258
    00259
    00291 SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen)
    00292 {
    00293 SOCKET sock;
    00294
    00295     sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
    00296     if (sock == -1)
    00297     {
    00298         sock_geterror("socket(): ", errbuf, errbuflen);
    00299         return -1;
    00300     }
    00301
    00302
    00303     // This is a server socket
    00304     if (server)
    00305     {
    00306 #ifdef BSD
    00307         // Force the use of IPv6-only addresses; in BSD you can accept both v4 and v6
    00308         // connections if you have a "NULL" pointer as the nodename in the getaddrinfo()
    00309         // This behaviour is not clear in the RFC 2553, so each system implements the
    00310         // bind() differently from this point of view
    00311
    00312         if (addrinfo->ai_family == PF_INET6)
    00313         {
    00314         int on;
    00315
    00316             if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (int)) == -1)
    00317             {
    00318                 if (errbuf)
    00319                 {
    00320                     snprintf(errbuf, errbuflen, "setsockopt(IPV6_BINDV6ONLY)");
    00321                     errbuf[errbuflen - 1]= 0;
    00322                 }
    00323                 return -1;
    00324             }
    00325         }
    00326 #endif
    00327
    00328         // WARNING: if the address is a mcast one, I should place the proper Win32 code here
    00329         if (bind(sock, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
    00330         {
    00331             sock_geterror("bind(): ", errbuf, errbuflen);
    00332             return -1;
    00333         }
    00334
    00335         if (addrinfo->ai_socktype == SOCK_STREAM)
    00336             if (listen(sock, nconn) == -1)
    00337             {
    00338                 sock_geterror("listen(): ", errbuf, errbuflen);
    00339                 return -1;
    00340             }
    00341
    00342         // server side ended
    00343         return sock;
    00344     }
    00345     else    // we're the client
    00346     {
    00347     struct addrinfo *tempaddrinfo;
    00348
    00349         tempaddrinfo= addrinfo;
    00350
    00351         // We have to loop though all the addinfo returned.
    00352         // For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying
    00353         // to connect to is unavailable in IPv6, so we have to try in IPv4 as well
    00354         while (tempaddrinfo)
    00355         {
    00356             if (connect(sock, tempaddrinfo->ai_addr, tempaddrinfo->ai_addrlen) == -1)
    00357                 tempaddrinfo= tempaddrinfo->ai_next;
    00358             else
    00359                 break;
    00360         }
    00361
    00362         // Check how we exit from the previous loop
    00363         // If tempaddrinfo is equal to NULL, it means that all the connect() failed.
    00364         if (tempaddrinfo == NULL)
    00365         {
    00366             sock_geterror("Is the server properly installed on the other host? connect() failed: ", errbuf, errbuflen);
    00367             closesocket(sock);
    00368             return -1;
    00369         }
    00370         else
    00371             return sock;
    00372     }
    00373 }
    00374
    00375
    00376
    00377
    00396 int sock_close(SOCKET sock, char *errbuf, int errbuflen)
    00397 {
    00398     // SHUT_WR: subsequent calls to the send function are disallowed.
    00399     // For TCP sockets, a FIN will be sent after all data is sent and
    00400     // acknowledged by the Server.
    00401     if (shutdown(sock, SHUT_WR) )
    00402     {
    00403         sock_geterror("shutdown(): ", errbuf, errbuflen);
    00404         // close the socket anyway
    00405         closesocket(sock);
    00406         return -1;
    00407     }
    00408
    00409     closesocket(sock);
    00410     return 0;
    00411 }
    00412
    00413
    00414
    00415
    00416
    00417
    00456 int sock_initaddress(const char *address, const char *port,
    00457                             struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
    00458 {
    00459 int retval;
    00460
    00461     retval = getaddrinfo(address, port, hints, addrinfo);
    00462     if (retval != 0)
    00463     {
    00464         // if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
    00465         // error routines (errno) in UNIX; WIN32 suggests using the GetLastError() instead.
    00466         if (errbuf)
    00467 #ifdef WIN32
    00468             sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
    00469 #else
    00470             if (errbuf)
    00471             {
    00472                 snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
    00473                 errbuf[errbuflen - 1]= 0;
    00474             }
    00475 #endif
    00476         return -1;
    00477     }
    00483     // This software only supports PF_INET and PF_INET6.
    00484     if (( (*addrinfo)->ai_family != PF_INET) && ( (*addrinfo)->ai_family != PF_INET6))
    00485     {
    00486         if (errbuf)
    00487         {
    00488             snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
    00489             errbuf[errbuflen - 1]= 0;
    00490         }
    00491         return -1;
    00492     }
    00493
    00494     if ( ( (*addrinfo)->ai_socktype == SOCK_STREAM) && (sock_ismcastaddr( (*addrinfo)->ai_addr) == 0) )
    00495     {
    00496         if (errbuf)
    00497         {
    00498             snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
    00499             errbuf[errbuflen - 1]= 0;
    00500         }
    00501
    00502         return -1;
    00503     }
    00504
    00505     return 0;
    00506 }
    00507
    00508
    00509
    00535 int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen)
    00536 {
    00537 int nsent;
    00538
    00539 send:
    00540 #ifdef linux
    00541 /*
    00542     Another pain... in Linux there's this flag
    00543     MSG_NOSIGNAL
    00544         Requests not to send SIGPIPE on errors on stream-oriented
    00545         sockets when the other end breaks the connection.
    00546         The EPIPE error is still returned.
    00547 */
    00548     nsent = send(socket, buffer, size, MSG_NOSIGNAL);
    00549 #else
    00550     nsent = send(socket, buffer, size, 0);
    00551 #endif
    00552
    00553     if (nsent == -1)
    00554     {
    00555         sock_geterror("send(): ", errbuf, errbuflen);
    00556         return -1;
    00557     }
    00558
    00559     if (nsent != size)
    00560     {
    00561         size-= nsent;
    00562         buffer+= nsent;
    00563         goto send;
    00564     }
    00565
    00566     return 0;
    00567 }
    00568
    00569
    00625 int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen)
    00626 {
    00627
    00628     if ((*offset + size) > totsize)
    00629     {
    00630         if (errbuf)
    00631         {
    00632             snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
    00633             errbuf[errbuflen - 1]= 0;
    00634         }
    00635
    00636         return -1;
    00637     };
    00638
    00639     if (!checkonly)
    00640         memcpy(tempbuf + (*offset), buffer, size);
    00641
    00642     (*offset)+= size;
    00643
    00644     return 0;
    00645 }
    00646
    00647
    00648
    00684 int sock_recv(SOCKET sock, char *buffer, int size, int receiveall, char *errbuf, int errbuflen)
    00685 {
    00686 int nread;
    00687 int totread= 0;
    00688     // We can obtain the same result using the MSG_WAITALL flag
    00689     // However, this is not supported by recv() in Win32
    00690
    00691     if (size == 0)
    00692     {
    00693         SOCK_ASSERT("I have been requested to read zero bytes", 1);
    00694         return 0;
    00695     }
    00696
    00697 again:
    00698     nread= recv(sock, &(buffer[totread]), size - totread, 0);
    00699
    00700     if (nread == -1)
    00701     {
    00702         sock_geterror("recv(): ", errbuf, errbuflen);
    00703         return -1;
    00704     }
    00705
    00706     if (nread == 0)
    00707     {
    00708         if (errbuf)
    00709         {
    00710             snprintf(errbuf, errbuflen, "The other host terminated the connection.");
    00711             errbuf[errbuflen - 1]= 0;
    00712         }
    00713
    00714         return -1;
    00715     }
    00716
    00717     // If we want to return as soon as some data has been received,
    00718     // let's do the job
    00719     if (!receiveall)
    00720         return nread;
    00721
    00722     totread+= nread;
    00723
    00724     if (totread != size)
    00725         goto again;
    00726
    00727     return totread;
    00728 }
    00729
    00730
    00731
    00767 /*
    00768 int sock_recv(SOCKET sock, char *buffer, int size, char *errbuf, int errbuflen)
    00769 {
    00770 int nread;
    00771
    00772     nread= recv(sock, buffer, size, 0);
    00773
    00774     if (nread == -1)
    00775     {
    00776         sock_geterror("recv(): ", errbuf, errbuflen);
    00777         return -1;
    00778     }
    00779
    00780     if (nread == 0)
    00781     {
    00782         if (errbuf)
    00783         {
    00784             snprintf(errbuf, errbuflen, "The other host terminated the connection.");
    00785             errbuf[errbuflen - 1]= 0;
    00786         }
    00787
    00788         return -1;
    00789     }
    00790
    00791     return nread;
    00792 }
    00793 */
    00794
    00795
    00821 int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
    00822 {
    00823 #define TEMP_BUF_SIZE 65536
    00824
    00825 char buffer[TEMP_BUF_SIZE];     // network buffer, to be used when the message is discarded
    00826
    00827     // A static allocation avoids the need of a 'malloc()' each time we want to discard a message
    00828     // Our feeling is that a buffer if 65536 is enough for mot of the application;
    00829     // in case this is not enough, the "while" loop discards the message by calling the
    00830     // sockrecv() several times.
    00831
    00832     while (size > TEMP_BUF_SIZE)
    00833     {
    00834         if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
    00835             return -1;
    00836
    00837         size-= TEMP_BUF_SIZE;
    00838     }
    00839
    00840     // If there is still data to be discarded
    00841     // In this case, the data can fit into the temporaty buffer
    00842     if (size)
    00843     {
    00844         if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
    00845             return -1;
    00846     }
    00847
    00848     SOCK_ASSERT("I'm currently discarding data\n", 1);
    00849
    00850     return 0;
    00851 }
    00852
    00853
    00854
    00883 int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen)
    00884 {
    00885     // checks if the connecting host is among the ones allowed
    00886     if ( (hostlist) && (hostlist[0]) )
    00887     {
    00888     char *token;                    // temp, needed to separate items into the hostlist
    00889     struct addrinfo *addrinfo, *ai_next;
    00890     char *temphostlist;
    00891
    00892         temphostlist= (char *) malloc (strlen(hostlist) + 1);
    00893         if (temphostlist == NULL)
    00894         {
    00895             sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen);
    00896             return -2;
    00897         }
    00898
    00899         // The problem is that strtok modifies the original variable by putting '0' at the end of each token
    00900         // So, we have to create a new temporary string in which the original content is kept
    00901         strcpy(temphostlist, hostlist);
    00902
    00903         token= strtok(temphostlist, sep);
    00904
    00905         while( token != NULL )
    00906         {
    00907         struct addrinfo hints;
    00908         int retval;
    00909
    00910             addrinfo = NULL;
    00911             memset(&hints, 0, sizeof (struct addrinfo) );
    00912             hints.ai_family = PF_UNSPEC;
    00913             hints.ai_socktype= SOCK_STREAM;
    00914
    00915             retval = getaddrinfo(token, "0", &hints, &addrinfo);
    00916             if (retval != 0)
    00917             {
    00918                 if (errbuf)
    00919                 {
    00920                     snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
    00921                     errbuf[errbuflen - 1]= 0;
    00922                 }
    00923
    00924                 SOCK_ASSERT(errbuf, 1);
    00925
    00926                 // Get next token
    00927                 token = strtok( NULL, sep);
    00928                 continue;
    00929             }
    00930
    00931             // ai_next is required to preserve the content of addrinfo, in order to deallocate it properly
    00932             ai_next= addrinfo;
    00933             while(ai_next)
    00934             {
    00935                 if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
    00936                 {
    00937                     free(temphostlist);
    00938                     return 0;
    00939                 }
    00940
    00941                 // If we are here, it means that the current address does not matches
    00942                 // Let's try with the next one in the header chain
    00943                 ai_next= ai_next->ai_next;
    00944             }
    00945
    00946             freeaddrinfo(addrinfo);
    00947             addrinfo= NULL;
    00948
    00949             // Get next token
    00950             token = strtok( NULL, sep);
    00951         }
    00952
    00953         if (addrinfo)
    00954         {
    00955             freeaddrinfo(addrinfo);
    00956             addrinfo= NULL;
    00957         }
    00958
    00959         if (errbuf)
    00960         {
    00961             snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
    00962             errbuf[errbuflen - 1]= 0;
    00963         }
    00964
    00965         free(temphostlist);
    00966         return -1;
    00967     }
    00968
    00969     // No hostlist, so we have to return 'empty list'
    00970     return 1;
    00971 }
    00972
    00973
    00992 int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second)
    00993 {
    00994     if (first->ss_family == second->ss_family)
    00995     {
    00996         if (first->ss_family == AF_INET)
    00997         {
    00998             if (memcmp(     &(((struct sockaddr_in *) first)->sin_addr),
    00999                             &(((struct sockaddr_in *) second)->sin_addr),
    01000                             sizeof(struct in_addr) ) == 0)
    01001                                 return 0;
    01002         }
    01003         else // address family is AF_INET6
    01004         {
    01005             if (memcmp(     &(((struct sockaddr_in6 *) first)->sin6_addr),
    01006                             &(((struct sockaddr_in6 *) second)->sin6_addr),
    01007                             sizeof(struct in6_addr) ) == 0)
    01008                                 return 0;
    01009         }
    01010     }
    01011
    01012     return -1;
    01013 }
    01014
    01015
    01016
    01065 int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
    01066 {
    01067 socklen_t sockaddrlen;
    01068 int retval;                 // Variable that keeps the return value;
    01069
    01070     retval= -1;
    01071
    01072 #ifdef WIN32
    01073     if (sockaddr->ss_family == AF_INET)
    01074         sockaddrlen = sizeof(struct sockaddr_in);
    01075     else
    01076         sockaddrlen = sizeof(struct sockaddr_in6);
    01077 #else
    01078     sockaddrlen = sizeof(struct sockaddr_storage);
    01079 #endif
    01080
    01081 /* TEMP
    01082     if ( (SockAddr->ss_family == AF_INET6) &&
    01083         (memcmp( &((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) )
    01084     {
    01085         strncpy(Name, SOCKET_NAME_NULL_DAD, NameLen);
    01086         return -1;
    01087     }
    01088 */
    01089
    01090     if ( getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0)
    01091     {
    01092         // If the user wants to receive an error message
    01093         if (errbuf)
    01094         {
    01095             sock_geterror("getnameinfo(): ", errbuf, errbuflen);
    01096             errbuf[errbuflen-1]= 0;
    01097         }
    01098
    01099         if (address)
    01100         {
    01101             strncpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
    01102             address[addrlen-1]= 0;
    01103         }
    01104
    01105         if (port)
    01106         {
    01107             strncpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
    01108             port[portlen-1]= 0;
    01109         }
    01110
    01111         retval= 0;
    01112     }
    01113
    01114     return retval;
    01115 }
    01116
    01117
    01118
    01150 int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, char *errbuf, int errbuflen)
    01151 {
    01152 int retval;
    01153 struct addrinfo *addrinfo;
    01154
    01155     if ( (retval= sock_initaddress(address, "22222" /* fake port */, NULL, &addrinfo, errbuf, errbuflen)) == -1 )
    01156         return retval;
    01157
    01158     if (addrinfo->ai_family == PF_INET)
    01159         memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in) );
    01160     else
    01161         memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6) );
    01162
    01163     if (addrinfo->ai_next != NULL)
    01164     {
    01165         freeaddrinfo(addrinfo);
    01166
    01167         if (errbuf)
    01168         {
    01169             snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
    01170             errbuf[errbuflen - 1]= 0;
    01171         }
    01172
    01173         return -2;
    01174     }
    01175
    01176     freeaddrinfo(addrinfo);
    01177     return -1;
    01178 }
    01179
    01180

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