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.