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.