1335640Shselasky/* 2335640Shselasky * Copyright (c) 2002 - 2003 3335640Shselasky * NetGroup, Politecnico di Torino (Italy) 4335640Shselasky * All rights reserved. 5335640Shselasky * 6335640Shselasky * Redistribution and use in source and binary forms, with or without 7335640Shselasky * modification, are permitted provided that the following conditions 8335640Shselasky * are met: 9335640Shselasky * 10335640Shselasky * 1. Redistributions of source code must retain the above copyright 11335640Shselasky * notice, this list of conditions and the following disclaimer. 12335640Shselasky * 2. Redistributions in binary form must reproduce the above copyright 13335640Shselasky * notice, this list of conditions and the following disclaimer in the 14335640Shselasky * documentation and/or other materials provided with the distribution. 15335640Shselasky * 3. Neither the name of the Politecnico di Torino nor the names of its 16335640Shselasky * contributors may be used to endorse or promote products derived from 17335640Shselasky * this software without specific prior written permission. 18335640Shselasky * 19335640Shselasky * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20335640Shselasky * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21335640Shselasky * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22335640Shselasky * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23335640Shselasky * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24335640Shselasky * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25335640Shselasky * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26335640Shselasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27335640Shselasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28335640Shselasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29335640Shselasky * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30335640Shselasky * 31335640Shselasky */ 32335640Shselasky 33335640Shselasky#ifdef HAVE_CONFIG_H 34335640Shselasky#include <config.h> 35335640Shselasky#endif 36335640Shselasky 37335640Shselasky/* 38335640Shselasky * \file sockutils.c 39335640Shselasky * 40335640Shselasky * The goal of this file is to provide a common set of primitives for socket 41335640Shselasky * manipulation. 42335640Shselasky * 43335640Shselasky * Although the socket interface defined in the RFC 2553 (and its updates) 44335640Shselasky * is excellent, there are still differences between the behavior of those 45335640Shselasky * routines on UN*X and Windows, and between UN*Xes. 46335640Shselasky * 47335640Shselasky * These calls provide an interface similar to the socket interface, but 48335640Shselasky * that hides the differences between operating systems. It does not 49335640Shselasky * attempt to significantly improve on the socket interface in other 50335640Shselasky * ways. 51335640Shselasky */ 52335640Shselasky 53335640Shselasky#include "ftmacros.h" 54335640Shselasky 55335640Shselasky#include <string.h> 56335640Shselasky#include <errno.h> /* for the errno variable */ 57335640Shselasky#include <stdio.h> /* for the stderr file */ 58335640Shselasky#include <stdlib.h> /* for malloc() and free() */ 59335640Shselasky#ifdef HAVE_LIMITS_H 60335640Shselasky#include <limits.h> 61335640Shselasky#else 62335640Shselasky#define INT_MAX 2147483647 63335640Shselasky#endif 64335640Shselasky 65335640Shselasky#include "pcap-int.h" 66335640Shselasky 67335640Shselasky#include "sockutils.h" 68335640Shselasky#include "portability.h" 69335640Shselasky 70335640Shselasky#ifdef _WIN32 71335640Shselasky /* 72335640Shselasky * Winsock initialization. 73335640Shselasky * 74335640Shselasky * Ask for WinSock 2.2. 75335640Shselasky */ 76335640Shselasky #define WINSOCK_MAJOR_VERSION 2 77335640Shselasky #define WINSOCK_MINOR_VERSION 2 78335640Shselasky 79335640Shselasky static int sockcount = 0; /*!< Variable that allows calling the WSAStartup() only one time */ 80335640Shselasky#endif 81335640Shselasky 82335640Shselasky/* Some minor differences between UNIX and Win32 */ 83335640Shselasky#ifdef _WIN32 84335640Shselasky #define SHUT_WR SD_SEND /* The control code for shutdown() is different in Win32 */ 85335640Shselasky#endif 86335640Shselasky 87335640Shselasky/* Size of the buffer that has to keep error messages */ 88335640Shselasky#define SOCK_ERRBUF_SIZE 1024 89335640Shselasky 90335640Shselasky/* Constants; used in order to keep strings here */ 91335640Shselasky#define SOCKET_NO_NAME_AVAILABLE "No name available" 92335640Shselasky#define SOCKET_NO_PORT_AVAILABLE "No port available" 93335640Shselasky#define SOCKET_NAME_NULL_DAD "Null address (possibly DAD Phase)" 94335640Shselasky 95335640Shselasky/* 96335640Shselasky * On UN*X, send() and recv() return ssize_t. 97335640Shselasky * 98335640Shselasky * On Windows, send() and recv() return an int. 99335640Shselasky * 100335640Shselasky * Wth MSVC, there *is* no ssize_t. 101335640Shselasky * 102335640Shselasky * With MinGW, there is an ssize_t type; it is either an int (32 bit) 103356341Scy * or a long long (64 bit). 104335640Shselasky * 105335640Shselasky * So, on Windows, if we don't have ssize_t defined, define it as an 106335640Shselasky * int, so we can use it, on all platforms, as the type of variables 107335640Shselasky * that hold the return values from send() and recv(). 108335640Shselasky */ 109335640Shselasky#if defined(_WIN32) && !defined(_SSIZE_T_DEFINED) 110335640Shselaskytypedef int ssize_t; 111335640Shselasky#endif 112335640Shselasky 113335640Shselasky/**************************************************** 114335640Shselasky * * 115335640Shselasky * Locally defined functions * 116335640Shselasky * * 117335640Shselasky ****************************************************/ 118335640Shselasky 119335640Shselaskystatic int sock_ismcastaddr(const struct sockaddr *saddr); 120335640Shselasky 121335640Shselasky/**************************************************** 122335640Shselasky * * 123335640Shselasky * Function bodies * 124335640Shselasky * * 125335640Shselasky ****************************************************/ 126335640Shselasky 127335640Shselasky/* 128335640Shselasky * Format an error message given an errno value (UN*X) or a WinSock error 129335640Shselasky * (Windows). 130335640Shselasky */ 131335640Shselaskyvoid sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen) 132335640Shselasky{ 133335640Shselasky if (errbuf == NULL) 134335640Shselasky return; 135335640Shselasky 136356341Scy#ifdef _WIN32 137356341Scy pcap_fmt_errmsg_for_win32_err(errbuf, errbuflen, errcode, 138356341Scy "%s", caller); 139335640Shselasky#else 140356341Scy pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errcode, 141356341Scy "%s", caller); 142335640Shselasky#endif 143335640Shselasky} 144335640Shselasky 145335640Shselasky/* 146335640Shselasky * \brief It retrieves the error message after an error occurred in the socket interface. 147335640Shselasky * 148335640Shselasky * This function is defined because of the different way errors are returned in UNIX 149335640Shselasky * and Win32. This function provides a consistent way to retrieve the error message 150335640Shselasky * (after a socket error occurred) on all the platforms. 151335640Shselasky * 152335640Shselasky * \param caller: a pointer to a user-allocated string which contains a message that has 153335640Shselasky * to be printed *before* the true error message. It could be, for example, 'this error 154356341Scy * comes from the recv() call at line 31'. 155335640Shselasky * 156335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 157335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 158335640Shselasky * It can be NULL; in this case the error cannot be printed. 159335640Shselasky * 160335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 161335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 162335640Shselasky * 163335640Shselasky * \return No return values. The error message is returned in the 'string' parameter. 164335640Shselasky */ 165335640Shselaskyvoid sock_geterror(const char *caller, char *errbuf, int errbuflen) 166335640Shselasky{ 167335640Shselasky#ifdef _WIN32 168335640Shselasky sock_fmterror(caller, GetLastError(), errbuf, errbuflen); 169335640Shselasky#else 170335640Shselasky sock_fmterror(caller, errno, errbuf, errbuflen); 171335640Shselasky#endif 172335640Shselasky} 173335640Shselasky 174335640Shselasky/* 175356341Scy * \brief This function initializes the socket mechanism if it hasn't 176356341Scy * already been initialized or reinitializes it after it has been 177356341Scy * cleaned up. 178335640Shselasky * 179356341Scy * On UN*Xes, it doesn't need to do anything; on Windows, it needs to 180356341Scy * initialize Winsock. 181335640Shselasky * 182356341Scy * \param errbuf: a pointer to an user-allocated buffer that will contain 183356341Scy * the complete error message. This buffer has to be at least 'errbuflen' 184356341Scy * in length. It can be NULL; in this case no error message is supplied. 185335640Shselasky * 186356341Scy * \param errbuflen: length of the buffer that will contains the error. 187356341Scy * The error message cannot be larger than 'errbuflen - 1' because the 188356341Scy * last char is reserved for the string terminator. 189335640Shselasky * 190356341Scy * \return '0' if everything is fine, '-1' if some errors occurred. The 191356341Scy * error message is returned in the buffer pointed to by 'errbuf' variable. 192335640Shselasky */ 193335640Shselasky#ifdef _WIN32 194335640Shselaskyint sock_init(char *errbuf, int errbuflen) 195335640Shselasky{ 196335640Shselasky if (sockcount == 0) 197335640Shselasky { 198335640Shselasky WSADATA wsaData; /* helper variable needed to initialize Winsock */ 199335640Shselasky 200335640Shselasky if (WSAStartup(MAKEWORD(WINSOCK_MAJOR_VERSION, 201335640Shselasky WINSOCK_MINOR_VERSION), &wsaData) != 0) 202335640Shselasky { 203335640Shselasky if (errbuf) 204335640Shselasky pcap_snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n"); 205335640Shselasky 206335640Shselasky WSACleanup(); 207335640Shselasky 208335640Shselasky return -1; 209335640Shselasky } 210335640Shselasky } 211335640Shselasky 212335640Shselasky sockcount++; 213356341Scy return 0; 214356341Scy} 215335640Shselasky#else 216335640Shselaskyint sock_init(char *errbuf _U_, int errbuflen _U_) 217335640Shselasky{ 218356341Scy /* 219356341Scy * Nothing to do on UN*Xes. 220356341Scy */ 221335640Shselasky return 0; 222335640Shselasky} 223356341Scy#endif 224335640Shselasky 225335640Shselasky/* 226356341Scy * \brief This function cleans up the socket mechanism if we have no 227356341Scy * sockets left open. 228335640Shselasky * 229356341Scy * On UN*Xes, it doesn't need to do anything; on Windows, it needs 230356341Scy * to clean up Winsock. 231335640Shselasky * 232335640Shselasky * \return No error values. 233335640Shselasky */ 234335640Shselaskyvoid sock_cleanup(void) 235335640Shselasky{ 236335640Shselasky#ifdef _WIN32 237335640Shselasky sockcount--; 238335640Shselasky 239335640Shselasky if (sockcount == 0) 240335640Shselasky WSACleanup(); 241335640Shselasky#endif 242335640Shselasky} 243335640Shselasky 244335640Shselasky/* 245335640Shselasky * \brief It checks if the sockaddr variable contains a multicast address. 246335640Shselasky * 247335640Shselasky * \return '0' if the address is multicast, '-1' if it is not. 248335640Shselasky */ 249335640Shselaskystatic int sock_ismcastaddr(const struct sockaddr *saddr) 250335640Shselasky{ 251335640Shselasky if (saddr->sa_family == PF_INET) 252335640Shselasky { 253335640Shselasky struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr; 254335640Shselasky if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0; 255335640Shselasky else return -1; 256335640Shselasky } 257335640Shselasky else 258335640Shselasky { 259335640Shselasky struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr; 260335640Shselasky if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0; 261335640Shselasky else return -1; 262335640Shselasky } 263335640Shselasky} 264335640Shselasky 265335640Shselasky/* 266335640Shselasky * \brief It initializes a network connection both from the client and the server side. 267335640Shselasky * 268335640Shselasky * In case of a client socket, this function calls socket() and connect(). 269335640Shselasky * In the meanwhile, it checks for any socket error. 270335640Shselasky * If an error occurs, it writes the error message into 'errbuf'. 271335640Shselasky * 272335640Shselasky * In case of a server socket, the function calls socket(), bind() and listen(). 273335640Shselasky * 274335640Shselasky * This function is usually preceeded by the sock_initaddress(). 275335640Shselasky * 276335640Shselasky * \param addrinfo: pointer to an addrinfo variable which will be used to 277335640Shselasky * open the socket and such. This variable is the one returned by the previous call to 278335640Shselasky * sock_initaddress(). 279335640Shselasky * 280335640Shselasky * \param server: '1' if this is a server socket, '0' otherwise. 281335640Shselasky * 282335640Shselasky * \param nconn: number of the connections that are allowed to wait into the listen() call. 283335640Shselasky * This value has no meanings in case of a client socket. 284335640Shselasky * 285335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 286335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 287335640Shselasky * It can be NULL; in this case the error cannot be printed. 288335640Shselasky * 289335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 290335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 291335640Shselasky * 292335640Shselasky * \return the socket that has been opened (that has to be used in the following sockets calls) 293335640Shselasky * if everything is fine, INVALID_SOCKET if some errors occurred. The error message is returned 294335640Shselasky * in the 'errbuf' variable. 295335640Shselasky */ 296335640ShselaskySOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen) 297335640Shselasky{ 298335640Shselasky SOCKET sock; 299335640Shselasky#if defined(SO_NOSIGPIPE) || defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY) 300335640Shselasky int on = 1; 301335640Shselasky#endif 302335640Shselasky 303335640Shselasky sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); 304335640Shselasky if (sock == INVALID_SOCKET) 305335640Shselasky { 306356341Scy sock_geterror("socket()", errbuf, errbuflen); 307335640Shselasky return INVALID_SOCKET; 308335640Shselasky } 309335640Shselasky 310335640Shselasky /* 311335640Shselasky * Disable SIGPIPE, if we have SO_NOSIGPIPE. We don't want to 312335640Shselasky * have to deal with signals if the peer closes the connection, 313335640Shselasky * especially in client programs, which may not even be aware that 314335640Shselasky * they're sending to sockets. 315335640Shselasky */ 316335640Shselasky#ifdef SO_NOSIGPIPE 317335640Shselasky if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (char *)&on, 318335640Shselasky sizeof (int)) == -1) 319335640Shselasky { 320335640Shselasky sock_geterror("setsockopt(SO_NOSIGPIPE)", errbuf, errbuflen); 321335640Shselasky closesocket(sock); 322335640Shselasky return INVALID_SOCKET; 323335640Shselasky } 324335640Shselasky#endif 325335640Shselasky 326335640Shselasky /* This is a server socket */ 327335640Shselasky if (server) 328335640Shselasky { 329356341Scy /* 330356341Scy * Allow a new server to bind the socket after the old one 331356341Scy * exited, even if lingering sockets are still present. 332356341Scy * 333356341Scy * Don't treat an error as a failure. 334356341Scy */ 335356341Scy int optval = 1; 336356341Scy (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 337356341Scy (char *)&optval, sizeof (optval)); 338356341Scy 339335640Shselasky#if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY) 340335640Shselasky /* 341335640Shselasky * Force the use of IPv6-only addresses. 342335640Shselasky * 343335640Shselasky * RFC 3493 indicates that you can support IPv4 on an 344335640Shselasky * IPv6 socket: 345335640Shselasky * 346335640Shselasky * https://tools.ietf.org/html/rfc3493#section-3.7 347335640Shselasky * 348335640Shselasky * and that this is the default behavior. This means 349335640Shselasky * that if we first create an IPv6 socket bound to the 350335640Shselasky * "any" address, it is, in effect, also bound to the 351335640Shselasky * IPv4 "any" address, so when we create an IPv4 socket 352335640Shselasky * and try to bind it to the IPv4 "any" address, it gets 353335640Shselasky * EADDRINUSE. 354335640Shselasky * 355335640Shselasky * Not all network stacks support IPv4 on IPv6 sockets; 356335640Shselasky * pre-NT 6 Windows stacks don't support it, and the 357335640Shselasky * OpenBSD stack doesn't support it for security reasons 358335640Shselasky * (see the OpenBSD inet6(4) man page). Therefore, we 359335640Shselasky * don't want to rely on this behavior. 360335640Shselasky * 361335640Shselasky * So we try to disable it, using either the IPV6_V6ONLY 362335640Shselasky * option from RFC 3493: 363335640Shselasky * 364335640Shselasky * https://tools.ietf.org/html/rfc3493#section-5.3 365335640Shselasky * 366335640Shselasky * or the IPV6_BINDV6ONLY option from older UN*Xes. 367335640Shselasky */ 368335640Shselasky#ifndef IPV6_V6ONLY 369335640Shselasky /* For older systems */ 370335640Shselasky #define IPV6_V6ONLY IPV6_BINDV6ONLY 371335640Shselasky#endif /* IPV6_V6ONLY */ 372335640Shselasky if (addrinfo->ai_family == PF_INET6) 373335640Shselasky { 374335640Shselasky if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 375335640Shselasky (char *)&on, sizeof (int)) == -1) 376335640Shselasky { 377335640Shselasky if (errbuf) 378335640Shselasky pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)"); 379335640Shselasky closesocket(sock); 380335640Shselasky return INVALID_SOCKET; 381335640Shselasky } 382335640Shselasky } 383335640Shselasky#endif /* defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY) */ 384335640Shselasky 385335640Shselasky /* WARNING: if the address is a mcast one, I should place the proper Win32 code here */ 386335640Shselasky if (bind(sock, addrinfo->ai_addr, (int) addrinfo->ai_addrlen) != 0) 387335640Shselasky { 388356341Scy sock_geterror("bind()", errbuf, errbuflen); 389335640Shselasky closesocket(sock); 390335640Shselasky return INVALID_SOCKET; 391335640Shselasky } 392335640Shselasky 393335640Shselasky if (addrinfo->ai_socktype == SOCK_STREAM) 394335640Shselasky if (listen(sock, nconn) == -1) 395335640Shselasky { 396356341Scy sock_geterror("listen()", errbuf, errbuflen); 397335640Shselasky closesocket(sock); 398335640Shselasky return INVALID_SOCKET; 399335640Shselasky } 400335640Shselasky 401335640Shselasky /* server side ended */ 402335640Shselasky return sock; 403335640Shselasky } 404335640Shselasky else /* we're the client */ 405335640Shselasky { 406335640Shselasky struct addrinfo *tempaddrinfo; 407335640Shselasky char *errbufptr; 408335640Shselasky size_t bufspaceleft; 409335640Shselasky 410335640Shselasky tempaddrinfo = addrinfo; 411335640Shselasky errbufptr = errbuf; 412335640Shselasky bufspaceleft = errbuflen; 413335640Shselasky *errbufptr = 0; 414335640Shselasky 415335640Shselasky /* 416335640Shselasky * We have to loop though all the addinfo returned. 417335640Shselasky * For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying 418335640Shselasky * to connect to is unavailable in IPv6, so we have to try in IPv4 as well 419335640Shselasky */ 420335640Shselasky while (tempaddrinfo) 421335640Shselasky { 422335640Shselasky 423335640Shselasky if (connect(sock, tempaddrinfo->ai_addr, (int) tempaddrinfo->ai_addrlen) == -1) 424335640Shselasky { 425335640Shselasky size_t msglen; 426335640Shselasky char TmpBuffer[100]; 427335640Shselasky char SocketErrorMessage[SOCK_ERRBUF_SIZE]; 428335640Shselasky 429335640Shselasky /* 430335640Shselasky * We have to retrieve the error message before any other socket call completes, otherwise 431335640Shselasky * the error message is lost 432335640Shselasky */ 433356341Scy sock_geterror("Connect to socket failed", 434356341Scy SocketErrorMessage, sizeof(SocketErrorMessage)); 435335640Shselasky 436335640Shselasky /* Returns the numeric address of the host that triggered the error */ 437335640Shselasky sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer)); 438335640Shselasky 439335640Shselasky pcap_snprintf(errbufptr, bufspaceleft, 440356341Scy "Is the server properly installed on %s? %s", TmpBuffer, SocketErrorMessage); 441335640Shselasky 442335640Shselasky /* In case more then one 'connect' fails, we manage to keep all the error messages */ 443335640Shselasky msglen = strlen(errbufptr); 444335640Shselasky 445335640Shselasky errbufptr[msglen] = ' '; 446335640Shselasky errbufptr[msglen + 1] = 0; 447335640Shselasky 448335640Shselasky bufspaceleft = bufspaceleft - (msglen + 1); 449335640Shselasky errbufptr += (msglen + 1); 450335640Shselasky 451335640Shselasky tempaddrinfo = tempaddrinfo->ai_next; 452335640Shselasky } 453335640Shselasky else 454335640Shselasky break; 455335640Shselasky } 456335640Shselasky 457335640Shselasky /* 458335640Shselasky * Check how we exit from the previous loop 459335640Shselasky * If tempaddrinfo is equal to NULL, it means that all the connect() failed. 460335640Shselasky */ 461335640Shselasky if (tempaddrinfo == NULL) 462335640Shselasky { 463335640Shselasky closesocket(sock); 464335640Shselasky return INVALID_SOCKET; 465335640Shselasky } 466335640Shselasky else 467335640Shselasky return sock; 468335640Shselasky } 469335640Shselasky} 470335640Shselasky 471335640Shselasky/* 472335640Shselasky * \brief Closes the present (TCP and UDP) socket connection. 473335640Shselasky * 474335640Shselasky * This function sends a shutdown() on the socket in order to disable send() calls 475335640Shselasky * (while recv() ones are still allowed). Then, it closes the socket. 476335640Shselasky * 477335640Shselasky * \param sock: the socket identifier of the connection that has to be closed. 478335640Shselasky * 479335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 480335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 481335640Shselasky * It can be NULL; in this case the error cannot be printed. 482335640Shselasky * 483335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 484335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 485335640Shselasky * 486335640Shselasky * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned 487335640Shselasky * in the 'errbuf' variable. 488335640Shselasky */ 489335640Shselaskyint sock_close(SOCKET sock, char *errbuf, int errbuflen) 490335640Shselasky{ 491335640Shselasky /* 492335640Shselasky * SHUT_WR: subsequent calls to the send function are disallowed. 493335640Shselasky * For TCP sockets, a FIN will be sent after all data is sent and 494335640Shselasky * acknowledged by the Server. 495335640Shselasky */ 496335640Shselasky if (shutdown(sock, SHUT_WR)) 497335640Shselasky { 498356341Scy sock_geterror("shutdown()", errbuf, errbuflen); 499335640Shselasky /* close the socket anyway */ 500335640Shselasky closesocket(sock); 501335640Shselasky return -1; 502335640Shselasky } 503335640Shselasky 504335640Shselasky closesocket(sock); 505335640Shselasky return 0; 506335640Shselasky} 507335640Shselasky 508335640Shselasky/* 509356341Scy * gai_errstring() has some problems: 510356341Scy * 511356341Scy * 1) on Windows, Microsoft explicitly says it's not thread-safe; 512356341Scy * 2) on UN*X, the Single UNIX Specification doesn't say it *is* 513356341Scy * thread-safe, so an implementation might use a static buffer 514356341Scy * for unknown error codes; 515356341Scy * 3) the error message for the most likely error, EAI_NONAME, is 516356341Scy * truly horrible on several platforms ("nodename nor servname 517356341Scy * provided, or not known"? It's typically going to be "not 518356341Scy * known", not "oopsie, I passed null pointers for the host name 519356341Scy * and service name", not to mention they forgot the "neither"); 520356341Scy * 521356341Scy * so we roll our own. 522356341Scy */ 523356341Scystatic void 524356341Scyget_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err, 525356341Scy const char *hostname, const char *portname) 526356341Scy{ 527356341Scy char hostport[PCAP_ERRBUF_SIZE]; 528356341Scy 529356341Scy if (hostname != NULL && portname != NULL) 530356341Scy pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s:%s", 531356341Scy hostname, portname); 532356341Scy else if (hostname != NULL) 533356341Scy pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s", 534356341Scy hostname); 535356341Scy else if (portname != NULL) 536356341Scy pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, ":%s", 537356341Scy portname); 538356341Scy else 539356341Scy pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "<no host or port!>"); 540356341Scy switch (err) 541356341Scy { 542356341Scy#ifdef EAI_ADDRFAMILY 543356341Scy case EAI_ADDRFAMILY: 544356341Scy pcap_snprintf(errbuf, errbuflen, 545356341Scy "%sAddress family for %s not supported", 546356341Scy prefix, hostport); 547356341Scy break; 548356341Scy#endif 549356341Scy 550356341Scy case EAI_AGAIN: 551356341Scy pcap_snprintf(errbuf, errbuflen, 552356341Scy "%s%s could not be resolved at this time", 553356341Scy prefix, hostport); 554356341Scy break; 555356341Scy 556356341Scy case EAI_BADFLAGS: 557356341Scy pcap_snprintf(errbuf, errbuflen, 558356341Scy "%sThe ai_flags parameter for looking up %s had an invalid value", 559356341Scy prefix, hostport); 560356341Scy break; 561356341Scy 562356341Scy case EAI_FAIL: 563356341Scy pcap_snprintf(errbuf, errbuflen, 564356341Scy "%sA non-recoverable error occurred when attempting to resolve %s", 565356341Scy prefix, hostport); 566356341Scy break; 567356341Scy 568356341Scy case EAI_FAMILY: 569356341Scy pcap_snprintf(errbuf, errbuflen, 570356341Scy "%sThe address family for looking up %s was not recognized", 571356341Scy prefix, hostport); 572356341Scy break; 573356341Scy 574356341Scy case EAI_MEMORY: 575356341Scy pcap_snprintf(errbuf, errbuflen, 576356341Scy "%sOut of memory trying to allocate storage when looking up %s", 577356341Scy prefix, hostport); 578356341Scy break; 579356341Scy 580356341Scy /* 581356341Scy * RFC 2553 had both EAI_NODATA and EAI_NONAME. 582356341Scy * 583356341Scy * RFC 3493 has only EAI_NONAME. 584356341Scy * 585356341Scy * Some implementations define EAI_NODATA and EAI_NONAME 586356341Scy * to the same value, others don't. If EAI_NODATA is 587356341Scy * defined and isn't the same as EAI_NONAME, we handle 588356341Scy * EAI_NODATA. 589356341Scy */ 590356341Scy#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME 591356341Scy case EAI_NODATA: 592356341Scy pcap_snprintf(errbuf, errbuflen, 593356341Scy "%sNo address associated with %s", 594356341Scy prefix, hostport); 595356341Scy break; 596356341Scy#endif 597356341Scy 598356341Scy case EAI_NONAME: 599356341Scy pcap_snprintf(errbuf, errbuflen, 600356341Scy "%sThe host name %s couldn't be resolved", 601356341Scy prefix, hostport); 602356341Scy break; 603356341Scy 604356341Scy case EAI_SERVICE: 605356341Scy pcap_snprintf(errbuf, errbuflen, 606356341Scy "%sThe service value specified when looking up %s as not recognized for the socket type", 607356341Scy prefix, hostport); 608356341Scy break; 609356341Scy 610356341Scy case EAI_SOCKTYPE: 611356341Scy pcap_snprintf(errbuf, errbuflen, 612356341Scy "%sThe socket type specified when looking up %s as not recognized", 613356341Scy prefix, hostport); 614356341Scy break; 615356341Scy 616356341Scy#ifdef EAI_SYSTEM 617356341Scy case EAI_SYSTEM: 618356341Scy /* 619356341Scy * Assumed to be UN*X. 620356341Scy */ 621356341Scy pcap_snprintf(errbuf, errbuflen, 622356341Scy "%sAn error occurred when looking up %s: %s", 623356341Scy prefix, hostport, pcap_strerror(errno)); 624356341Scy break; 625356341Scy#endif 626356341Scy 627356341Scy#ifdef EAI_BADHINTS 628356341Scy case EAI_BADHINTS: 629356341Scy pcap_snprintf(errbuf, errbuflen, 630356341Scy "%sInvalid value for hints when looking up %s", 631356341Scy prefix, hostport); 632356341Scy break; 633356341Scy#endif 634356341Scy 635356341Scy#ifdef EAI_PROTOCOL 636356341Scy case EAI_PROTOCOL: 637356341Scy pcap_snprintf(errbuf, errbuflen, 638356341Scy "%sResolved protocol when looking up %s is unknown", 639356341Scy prefix, hostport); 640356341Scy break; 641356341Scy#endif 642356341Scy 643356341Scy#ifdef EAI_OVERFLOW 644356341Scy case EAI_OVERFLOW: 645356341Scy pcap_snprintf(errbuf, errbuflen, 646356341Scy "%sArgument buffer overflow when looking up %s", 647356341Scy prefix, hostport); 648356341Scy break; 649356341Scy#endif 650356341Scy 651356341Scy default: 652356341Scy pcap_snprintf(errbuf, errbuflen, 653356341Scy "%sgetaddrinfo() error %d when looking up %s", 654356341Scy prefix, err, hostport); 655356341Scy break; 656356341Scy } 657356341Scy} 658356341Scy 659356341Scy/* 660335640Shselasky * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure. 661335640Shselasky * 662335640Shselasky * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks 663335640Shselasky * to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such). 664335640Shselasky * If an error occurs, it writes the error message into 'errbuf'. 665335640Shselasky * 666335640Shselasky * \param host: a pointer to a string identifying the host. It can be 667335640Shselasky * a host name, a numeric literal address, or NULL or "" (useful 668335640Shselasky * in case of a server socket which has to bind to all addresses). 669335640Shselasky * 670335640Shselasky * \param port: a pointer to a user-allocated buffer containing the network port to use. 671335640Shselasky * 672335640Shselasky * \param hints: an addrinfo variable (passed by reference) containing the flags needed to create the 673335640Shselasky * addrinfo structure appropriately. 674335640Shselasky * 675335640Shselasky * \param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable 676335640Shselasky * (passed by reference), which will be allocated by this function and returned back to the caller. 677335640Shselasky * This variable will be used in the next sockets calls. 678335640Shselasky * 679335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 680335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 681335640Shselasky * It can be NULL; in this case the error cannot be printed. 682335640Shselasky * 683335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 684335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 685335640Shselasky * 686335640Shselasky * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned 687335640Shselasky * in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is 688335640Shselasky * returned into the addrinfo parameter. 689335640Shselasky * 690335640Shselasky * \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when 691335640Shselasky * it is no longer needed. 692335640Shselasky * 693335640Shselasky * \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same 694335640Shselasky * of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest 695335640Shselasky * the programmer to look at that function in order to set the 'hints' variable appropriately. 696335640Shselasky */ 697335640Shselaskyint sock_initaddress(const char *host, const char *port, 698335640Shselasky struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen) 699335640Shselasky{ 700335640Shselasky int retval; 701335640Shselasky 702335640Shselasky retval = getaddrinfo(host, port, hints, addrinfo); 703335640Shselasky if (retval != 0) 704335640Shselasky { 705335640Shselasky if (errbuf) 706335640Shselasky { 707356341Scy get_gai_errstring(errbuf, errbuflen, "", retval, 708356341Scy host, port); 709335640Shselasky } 710335640Shselasky return -1; 711335640Shselasky } 712335640Shselasky /* 713335640Shselasky * \warning SOCKET: I should check all the accept() in order to bind to all addresses in case 714335640Shselasky * addrinfo has more han one pointers 715335640Shselasky */ 716335640Shselasky 717335640Shselasky /* 718335640Shselasky * This software only supports PF_INET and PF_INET6. 719335640Shselasky * 720335640Shselasky * XXX - should we just check that at least *one* address is 721335640Shselasky * either PF_INET or PF_INET6, and, when using the list, 722335640Shselasky * ignore all addresses that are neither? (What, no IPX 723335640Shselasky * support? :-)) 724335640Shselasky */ 725335640Shselasky if (((*addrinfo)->ai_family != PF_INET) && 726335640Shselasky ((*addrinfo)->ai_family != PF_INET6)) 727335640Shselasky { 728335640Shselasky if (errbuf) 729335640Shselasky pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported"); 730335640Shselasky freeaddrinfo(*addrinfo); 731335640Shselasky *addrinfo = NULL; 732335640Shselasky return -1; 733335640Shselasky } 734335640Shselasky 735335640Shselasky /* 736335640Shselasky * You can't do multicast (or broadcast) TCP. 737335640Shselasky */ 738335640Shselasky if (((*addrinfo)->ai_socktype == SOCK_STREAM) && 739335640Shselasky (sock_ismcastaddr((*addrinfo)->ai_addr) == 0)) 740335640Shselasky { 741335640Shselasky if (errbuf) 742335640Shselasky pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams"); 743335640Shselasky freeaddrinfo(*addrinfo); 744335640Shselasky *addrinfo = NULL; 745335640Shselasky return -1; 746335640Shselasky } 747335640Shselasky 748335640Shselasky return 0; 749335640Shselasky} 750335640Shselasky 751335640Shselasky/* 752335640Shselasky * \brief It sends the amount of data contained into 'buffer' on the given socket. 753335640Shselasky * 754335640Shselasky * This function basically calls the send() socket function and it checks that all 755335640Shselasky * the data specified in 'buffer' (of size 'size') will be sent. If an error occurs, 756335640Shselasky * it writes the error message into 'errbuf'. 757335640Shselasky * In case the socket buffer does not have enough space, it loops until all data 758335640Shselasky * has been sent. 759335640Shselasky * 760335640Shselasky * \param socket: the connected socket currently opened. 761335640Shselasky * 762335640Shselasky * \param buffer: a char pointer to a user-allocated buffer in which data is contained. 763335640Shselasky * 764335640Shselasky * \param size: number of bytes that have to be sent. 765335640Shselasky * 766335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 767335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 768335640Shselasky * It can be NULL; in this case the error cannot be printed. 769335640Shselasky * 770335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 771335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 772335640Shselasky * 773335640Shselasky * \return '0' if everything is fine, '-1' if an error other than 774335640Shselasky * "connection reset" or "peer has closed the receive side" occurred, 775335640Shselasky * '-2' if we got one of those errors. 776335640Shselasky * For errors, an error message is returned in the 'errbuf' variable. 777335640Shselasky */ 778335640Shselaskyint sock_send(SOCKET sock, const char *buffer, size_t size, 779335640Shselasky char *errbuf, int errbuflen) 780335640Shselasky{ 781335640Shselasky int remaining; 782335640Shselasky ssize_t nsent; 783335640Shselasky 784335640Shselasky if (size > INT_MAX) 785335640Shselasky { 786335640Shselasky if (errbuf) 787335640Shselasky { 788335640Shselasky pcap_snprintf(errbuf, errbuflen, 789356341Scy "Can't send more than %u bytes with sock_send", 790335640Shselasky INT_MAX); 791335640Shselasky } 792335640Shselasky return -1; 793335640Shselasky } 794335640Shselasky remaining = (int)size; 795335640Shselasky 796335640Shselasky do { 797335640Shselasky#ifdef MSG_NOSIGNAL 798335640Shselasky /* 799335640Shselasky * Send with MSG_NOSIGNAL, so that we don't get SIGPIPE 800335640Shselasky * on errors on stream-oriented sockets when the other 801335640Shselasky * end breaks the connection. 802335640Shselasky * The EPIPE error is still returned. 803335640Shselasky */ 804335640Shselasky nsent = send(sock, buffer, remaining, MSG_NOSIGNAL); 805335640Shselasky#else 806335640Shselasky nsent = send(sock, buffer, remaining, 0); 807335640Shselasky#endif 808335640Shselasky 809335640Shselasky if (nsent == -1) 810335640Shselasky { 811335640Shselasky /* 812335640Shselasky * If the client closed the connection out from 813335640Shselasky * under us, there's no need to log that as an 814335640Shselasky * error. 815335640Shselasky */ 816335640Shselasky int errcode; 817335640Shselasky 818335640Shselasky#ifdef _WIN32 819335640Shselasky errcode = GetLastError(); 820335640Shselasky if (errcode == WSAECONNRESET || 821335640Shselasky errcode == WSAECONNABORTED) 822335640Shselasky { 823335640Shselasky /* 824335640Shselasky * WSAECONNABORTED appears to be the error 825335640Shselasky * returned in Winsock when you try to send 826335640Shselasky * on a connection where the peer has closed 827335640Shselasky * the receive side. 828335640Shselasky */ 829335640Shselasky return -2; 830335640Shselasky } 831356341Scy sock_fmterror("send()", errcode, errbuf, errbuflen); 832335640Shselasky#else 833335640Shselasky errcode = errno; 834335640Shselasky if (errcode == ECONNRESET || errcode == EPIPE) 835335640Shselasky { 836335640Shselasky /* 837335640Shselasky * EPIPE is what's returned on UN*X when 838335640Shselasky * you try to send on a connection when 839335640Shselasky * the peer has closed the receive side. 840335640Shselasky */ 841335640Shselasky return -2; 842335640Shselasky } 843356341Scy sock_fmterror("send()", errcode, errbuf, errbuflen); 844335640Shselasky#endif 845335640Shselasky return -1; 846335640Shselasky } 847335640Shselasky 848335640Shselasky remaining -= nsent; 849335640Shselasky buffer += nsent; 850335640Shselasky } while (remaining != 0); 851335640Shselasky 852335640Shselasky return 0; 853335640Shselasky} 854335640Shselasky 855335640Shselasky/* 856335640Shselasky * \brief It copies the amount of data contained into 'buffer' into 'tempbuf'. 857335640Shselasky * and it checks for buffer overflows. 858335640Shselasky * 859335640Shselasky * This function basically copies 'size' bytes of data contained into 'buffer' 860335640Shselasky * into 'tempbuf', starting at offset 'offset'. Before that, it checks that the 861335640Shselasky * resulting buffer will not be larger than 'totsize'. Finally, it updates 862335640Shselasky * the 'offset' variable in order to point to the first empty location of the buffer. 863335640Shselasky * 864335640Shselasky * In case the function is called with 'checkonly' equal to 1, it does not copy 865335640Shselasky * the data into the buffer. It only checks for buffer overflows and it updates the 866335640Shselasky * 'offset' variable. This mode can be useful when the buffer already contains the 867335640Shselasky * data (maybe because the producer writes directly into the target buffer), so 868335640Shselasky * only the buffer overflow check has to be made. 869335640Shselasky * In this case, both 'buffer' and 'tempbuf' can be NULL values. 870335640Shselasky * 871335640Shselasky * This function is useful in case the userland application does not know immediately 872335640Shselasky * all the data it has to write into the socket. This function provides a way to create 873335640Shselasky * the "stream" step by step, appending the new data to the old one. Then, when all the 874335640Shselasky * data has been bufferized, the application can call the sock_send() function. 875335640Shselasky * 876335640Shselasky * \param buffer: a char pointer to a user-allocated buffer that keeps the data 877335640Shselasky * that has to be copied. 878335640Shselasky * 879335640Shselasky * \param size: number of bytes that have to be copied. 880335640Shselasky * 881335640Shselasky * \param tempbuf: user-allocated buffer (of size 'totsize') in which data 882335640Shselasky * has to be copied. 883335640Shselasky * 884335640Shselasky * \param offset: an index into 'tempbuf' which keeps the location of its first 885335640Shselasky * empty location. 886335640Shselasky * 887335640Shselasky * \param totsize: total size of the buffer in which data is being copied. 888335640Shselasky * 889335640Shselasky * \param checkonly: '1' if we do not want to copy data into the buffer and we 890335640Shselasky * want just do a buffer ovreflow control, '0' if data has to be copied as well. 891335640Shselasky * 892335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 893335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 894335640Shselasky * It can be NULL; in this case the error cannot be printed. 895335640Shselasky * 896335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 897335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 898335640Shselasky * 899335640Shselasky * \return '0' if everything is fine, '-1' if some errors occurred. The error message 900335640Shselasky * is returned in the 'errbuf' variable. When the function returns, 'tempbuf' will 901335640Shselasky * have the new string appended, and 'offset' will keep the length of that buffer. 902335640Shselasky * In case of 'checkonly == 1', data is not copied, but 'offset' is updated in any case. 903335640Shselasky * 904335640Shselasky * \warning This function assumes that the buffer in which data has to be stored is 905335640Shselasky * large 'totbuf' bytes. 906335640Shselasky * 907335640Shselasky * \warning In case of 'checkonly', be carefully to call this function *before* copying 908335640Shselasky * the data into the buffer. Otherwise, the control about the buffer overflow is useless. 909335640Shselasky */ 910335640Shselaskyint sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen) 911335640Shselasky{ 912335640Shselasky if ((*offset + size) > totsize) 913335640Shselasky { 914335640Shselasky if (errbuf) 915335640Shselasky pcap_snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer."); 916335640Shselasky return -1; 917335640Shselasky } 918335640Shselasky 919335640Shselasky if (!checkonly) 920335640Shselasky memcpy(tempbuf + (*offset), buffer, size); 921335640Shselasky 922335640Shselasky (*offset) += size; 923335640Shselasky 924335640Shselasky return 0; 925335640Shselasky} 926335640Shselasky 927335640Shselasky/* 928335640Shselasky * \brief It waits on a connected socket and it manages to receive data. 929335640Shselasky * 930335640Shselasky * This function basically calls the recv() socket function and it checks that no 931335640Shselasky * error occurred. If that happens, it writes the error message into 'errbuf'. 932335640Shselasky * 933335640Shselasky * This function changes its behavior according to the 'receiveall' flag: if we 934335640Shselasky * want to receive exactly 'size' byte, it loops on the recv() until all the requested 935335640Shselasky * data is arrived. Otherwise, it returns the data currently available. 936335640Shselasky * 937335640Shselasky * In case the socket does not have enough data available, it cycles on the recv() 938335640Shselasky * until the requested data (of size 'size') is arrived. 939335640Shselasky * In this case, it blocks until the number of bytes read is equal to 'size'. 940335640Shselasky * 941335640Shselasky * \param sock: the connected socket currently opened. 942335640Shselasky * 943335640Shselasky * \param buffer: a char pointer to a user-allocated buffer in which data has to be stored 944335640Shselasky * 945335640Shselasky * \param size: size of the allocated buffer. WARNING: this indicates the number of bytes 946335640Shselasky * that we are expecting to be read. 947335640Shselasky * 948335640Shselasky * \param flags: 949335640Shselasky * 950335640Shselasky * SOCK_RECEIVALL_XXX: 951335640Shselasky * 952335640Shselasky * if SOCK_RECEIVEALL_NO, return as soon as some data is ready 953335640Shselasky * if SOCK_RECEIVALL_YES, wait until 'size' data has been 954335640Shselasky * received (in case the socket does not have enough data available). 955335640Shselasky * 956335640Shselasky * SOCK_EOF_XXX: 957335640Shselasky * 958335640Shselasky * if SOCK_EOF_ISNT_ERROR, if the first read returns 0, just return 0, 959335640Shselasky * and return an error on any subsequent read that returns 0; 960335640Shselasky * if SOCK_EOF_IS_ERROR, if any read returns 0, return an error. 961335640Shselasky * 962335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 963335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 964335640Shselasky * It can be NULL; in this case the error cannot be printed. 965335640Shselasky * 966335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 967335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 968335640Shselasky * 969335640Shselasky * \return the number of bytes read if everything is fine, '-1' if some errors occurred. 970335640Shselasky * The error message is returned in the 'errbuf' variable. 971335640Shselasky */ 972335640Shselasky 973335640Shselaskyint sock_recv(SOCKET sock, void *buffer, size_t size, int flags, 974335640Shselasky char *errbuf, int errbuflen) 975335640Shselasky{ 976335640Shselasky char *bufp = buffer; 977335640Shselasky int remaining; 978335640Shselasky ssize_t nread; 979335640Shselasky 980335640Shselasky if (size == 0) 981335640Shselasky { 982335640Shselasky return 0; 983335640Shselasky } 984335640Shselasky if (size > INT_MAX) 985335640Shselasky { 986335640Shselasky if (errbuf) 987335640Shselasky { 988335640Shselasky pcap_snprintf(errbuf, errbuflen, 989335640Shselasky "Can't read more than %u bytes with sock_recv", 990335640Shselasky INT_MAX); 991335640Shselasky } 992335640Shselasky return -1; 993335640Shselasky } 994335640Shselasky 995335640Shselasky bufp = (char *) buffer; 996335640Shselasky remaining = (int) size; 997335640Shselasky 998335640Shselasky /* 999335640Shselasky * We don't use MSG_WAITALL because it's not supported in 1000335640Shselasky * Win32. 1001335640Shselasky */ 1002335640Shselasky for (;;) { 1003335640Shselasky nread = recv(sock, bufp, remaining, 0); 1004335640Shselasky 1005335640Shselasky if (nread == -1) 1006335640Shselasky { 1007335640Shselasky#ifndef _WIN32 1008335640Shselasky if (errno == EINTR) 1009335640Shselasky return -3; 1010335640Shselasky#endif 1011356341Scy sock_geterror("recv()", errbuf, errbuflen); 1012335640Shselasky return -1; 1013335640Shselasky } 1014335640Shselasky 1015335640Shselasky if (nread == 0) 1016335640Shselasky { 1017335640Shselasky if ((flags & SOCK_EOF_IS_ERROR) || 1018335640Shselasky (remaining != (int) size)) 1019335640Shselasky { 1020335640Shselasky /* 1021335640Shselasky * Either we've already read some data, 1022335640Shselasky * or we're always supposed to return 1023335640Shselasky * an error on EOF. 1024335640Shselasky */ 1025335640Shselasky if (errbuf) 1026335640Shselasky { 1027335640Shselasky pcap_snprintf(errbuf, errbuflen, 1028335640Shselasky "The other host terminated the connection."); 1029335640Shselasky } 1030335640Shselasky return -1; 1031335640Shselasky } 1032335640Shselasky else 1033335640Shselasky return 0; 1034335640Shselasky } 1035335640Shselasky 1036335640Shselasky /* 1037335640Shselasky * Do we want to read the amount requested, or just return 1038335640Shselasky * what we got? 1039335640Shselasky */ 1040335640Shselasky if (!(flags & SOCK_RECEIVEALL_YES)) 1041335640Shselasky { 1042335640Shselasky /* 1043335640Shselasky * Just return what we got. 1044335640Shselasky */ 1045335640Shselasky return (int) nread; 1046335640Shselasky } 1047335640Shselasky 1048335640Shselasky bufp += nread; 1049335640Shselasky remaining -= nread; 1050335640Shselasky 1051335640Shselasky if (remaining == 0) 1052335640Shselasky return (int) size; 1053335640Shselasky } 1054335640Shselasky} 1055335640Shselasky 1056335640Shselasky/* 1057335640Shselasky * Receives a datagram from a socket. 1058335640Shselasky * 1059335640Shselasky * Returns the size of the datagram on success or -1 on error. 1060335640Shselasky */ 1061335640Shselaskyint sock_recv_dgram(SOCKET sock, void *buffer, size_t size, 1062335640Shselasky char *errbuf, int errbuflen) 1063335640Shselasky{ 1064335640Shselasky ssize_t nread; 1065335640Shselasky#ifndef _WIN32 1066335640Shselasky struct msghdr message; 1067335640Shselasky struct iovec iov; 1068335640Shselasky#endif 1069335640Shselasky 1070335640Shselasky if (size == 0) 1071335640Shselasky { 1072335640Shselasky return 0; 1073335640Shselasky } 1074335640Shselasky if (size > INT_MAX) 1075335640Shselasky { 1076335640Shselasky if (errbuf) 1077335640Shselasky { 1078335640Shselasky pcap_snprintf(errbuf, errbuflen, 1079335640Shselasky "Can't read more than %u bytes with sock_recv_dgram", 1080335640Shselasky INT_MAX); 1081335640Shselasky } 1082335640Shselasky return -1; 1083335640Shselasky } 1084335640Shselasky 1085335640Shselasky /* 1086335640Shselasky * This should be a datagram socket, so we should get the 1087335640Shselasky * entire datagram in one recv() or recvmsg() call, and 1088335640Shselasky * don't need to loop. 1089335640Shselasky */ 1090335640Shselasky#ifdef _WIN32 1091335640Shselasky nread = recv(sock, buffer, size, 0); 1092335640Shselasky if (nread == SOCKET_ERROR) 1093335640Shselasky { 1094335640Shselasky /* 1095335640Shselasky * To quote the MSDN documentation for recv(), 1096335640Shselasky * "If the datagram or message is larger than 1097335640Shselasky * the buffer specified, the buffer is filled 1098335640Shselasky * with the first part of the datagram, and recv 1099335640Shselasky * generates the error WSAEMSGSIZE. For unreliable 1100335640Shselasky * protocols (for example, UDP) the excess data is 1101335640Shselasky * lost..." 1102335640Shselasky * 1103335640Shselasky * So if the message is bigger than the buffer 1104335640Shselasky * supplied to us, the excess data is discarded, 1105335640Shselasky * and we'll report an error. 1106335640Shselasky */ 1107356341Scy sock_geterror("recv()", errbuf, errbuflen); 1108335640Shselasky return -1; 1109335640Shselasky } 1110335640Shselasky#else /* _WIN32 */ 1111335640Shselasky /* 1112335640Shselasky * The Single UNIX Specification says that a recv() on 1113335640Shselasky * a socket for a message-oriented protocol will discard 1114335640Shselasky * the excess data. It does *not* indicate that the 1115335640Shselasky * receive will fail with, for example, EMSGSIZE. 1116335640Shselasky * 1117335640Shselasky * Therefore, we use recvmsg(), which appears to be 1118335640Shselasky * the only way to get a "message truncated" indication 1119335640Shselasky * when receiving a message for a message-oriented 1120335640Shselasky * protocol. 1121335640Shselasky */ 1122335640Shselasky message.msg_name = NULL; /* we don't care who it's from */ 1123335640Shselasky message.msg_namelen = 0; 1124335640Shselasky iov.iov_base = buffer; 1125335640Shselasky iov.iov_len = size; 1126335640Shselasky message.msg_iov = &iov; 1127335640Shselasky message.msg_iovlen = 1; 1128335640Shselasky#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL 1129335640Shselasky message.msg_control = NULL; /* we don't care about control information */ 1130335640Shselasky message.msg_controllen = 0; 1131335640Shselasky#endif 1132335640Shselasky#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS 1133335640Shselasky message.msg_flags = 0; 1134335640Shselasky#endif 1135335640Shselasky nread = recvmsg(sock, &message, 0); 1136335640Shselasky if (nread == -1) 1137335640Shselasky { 1138335640Shselasky if (errno == EINTR) 1139335640Shselasky return -3; 1140356341Scy sock_geterror("recv()", errbuf, errbuflen); 1141335640Shselasky return -1; 1142335640Shselasky } 1143335640Shselasky#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS 1144335640Shselasky /* 1145335640Shselasky * XXX - Solaris supports this, but only if you ask for the 1146335640Shselasky * X/Open version of recvmsg(); should we use that, or will 1147335640Shselasky * that cause other problems? 1148335640Shselasky */ 1149335640Shselasky if (message.msg_flags & MSG_TRUNC) 1150335640Shselasky { 1151335640Shselasky /* 1152335640Shselasky * Message was bigger than the specified buffer size. 1153335640Shselasky * 1154335640Shselasky * Report this as an error, as the Microsoft documentation 1155335640Shselasky * implies we'd do in a similar case on Windows. 1156335640Shselasky */ 1157335640Shselasky pcap_snprintf(errbuf, errbuflen, "recv(): Message too long"); 1158335640Shselasky return -1; 1159335640Shselasky } 1160335640Shselasky#endif /* HAVE_STRUCT_MSGHDR_MSG_FLAGS */ 1161335640Shselasky#endif /* _WIN32 */ 1162335640Shselasky 1163335640Shselasky /* 1164335640Shselasky * The size we're reading fits in an int, so the return value 1165335640Shselasky * will fit in an int. 1166335640Shselasky */ 1167335640Shselasky return (int)nread; 1168335640Shselasky} 1169335640Shselasky 1170335640Shselasky/* 1171335640Shselasky * \brief It discards N bytes that are currently waiting to be read on the current socket. 1172335640Shselasky * 1173335640Shselasky * This function is useful in case we receive a message we cannot understand (e.g. 1174335640Shselasky * wrong version number when receiving a network packet), so that we have to discard all 1175335640Shselasky * data before reading a new message. 1176335640Shselasky * 1177335640Shselasky * This function will read 'size' bytes from the socket and discard them. 1178335640Shselasky * It defines an internal buffer in which data will be copied; however, in case 1179335640Shselasky * this buffer is not large enough, it will cycle in order to read everything as well. 1180335640Shselasky * 1181335640Shselasky * \param sock: the connected socket currently opened. 1182335640Shselasky * 1183335640Shselasky * \param size: number of bytes that have to be discarded. 1184335640Shselasky * 1185335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 1186335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 1187335640Shselasky * It can be NULL; in this case the error cannot be printed. 1188335640Shselasky * 1189335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 1190335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 1191335640Shselasky * 1192335640Shselasky * \return '0' if everything is fine, '-1' if some errors occurred. 1193335640Shselasky * The error message is returned in the 'errbuf' variable. 1194335640Shselasky */ 1195335640Shselaskyint sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen) 1196335640Shselasky{ 1197335640Shselasky#define TEMP_BUF_SIZE 32768 1198335640Shselasky 1199335640Shselasky char buffer[TEMP_BUF_SIZE]; /* network buffer, to be used when the message is discarded */ 1200335640Shselasky 1201335640Shselasky /* 1202335640Shselasky * A static allocation avoids the need of a 'malloc()' each time we want to discard a message 1203335640Shselasky * Our feeling is that a buffer if 32KB is enough for most of the application; 1204335640Shselasky * in case this is not enough, the "while" loop discards the message by calling the 1205335640Shselasky * sockrecv() several times. 1206335640Shselasky * We do not want to create a bigger variable because this causes the program to exit on 1207335640Shselasky * some platforms (e.g. BSD) 1208335640Shselasky */ 1209335640Shselasky while (size > TEMP_BUF_SIZE) 1210335640Shselasky { 1211335640Shselasky if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1) 1212335640Shselasky return -1; 1213335640Shselasky 1214335640Shselasky size -= TEMP_BUF_SIZE; 1215335640Shselasky } 1216335640Shselasky 1217335640Shselasky /* 1218335640Shselasky * If there is still data to be discarded 1219335640Shselasky * In this case, the data can fit into the temporary buffer 1220335640Shselasky */ 1221335640Shselasky if (size) 1222335640Shselasky { 1223335640Shselasky if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1) 1224335640Shselasky return -1; 1225335640Shselasky } 1226335640Shselasky 1227335640Shselasky return 0; 1228335640Shselasky} 1229335640Shselasky 1230335640Shselasky/* 1231335640Shselasky * \brief Checks that one host (identified by the sockaddr_storage structure) belongs to an 'allowed list'. 1232335640Shselasky * 1233335640Shselasky * This function is useful after an accept() call in order to check if the connecting 1234335640Shselasky * host is allowed to connect to me. To do that, we have a buffer that keeps the list of the 1235335640Shselasky * allowed host; this function checks the sockaddr_storage structure of the connecting host 1236335640Shselasky * against this host list, and it returns '0' is the host is included in this list. 1237335640Shselasky * 1238335640Shselasky * \param hostlist: pointer to a string that contains the list of the allowed host. 1239335640Shselasky * 1240335640Shselasky * \param sep: a string that keeps the separators used between the hosts (for example the 1241335640Shselasky * space character) in the host list. 1242335640Shselasky * 1243335640Shselasky * \param from: a sockaddr_storage structure, as it is returned by the accept() call. 1244335640Shselasky * 1245335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 1246335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 1247335640Shselasky * It can be NULL; in this case the error cannot be printed. 1248335640Shselasky * 1249335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 1250335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 1251335640Shselasky * 1252335640Shselasky * \return It returns: 1253335640Shselasky * - '1' if the host list is empty 1254335640Shselasky * - '0' if the host belongs to the host list (and therefore it is allowed to connect) 1255335640Shselasky * - '-1' in case the host does not belong to the host list (and therefore it is not allowed to connect 1256335640Shselasky * - '-2' in case or error. The error message is returned in the 'errbuf' variable. 1257335640Shselasky */ 1258335640Shselaskyint sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen) 1259335640Shselasky{ 1260335640Shselasky /* checks if the connecting host is among the ones allowed */ 1261335640Shselasky if ((hostlist) && (hostlist[0])) 1262335640Shselasky { 1263335640Shselasky char *token; /* temp, needed to separate items into the hostlist */ 1264335640Shselasky struct addrinfo *addrinfo, *ai_next; 1265335640Shselasky char *temphostlist; 1266335640Shselasky char *lasts; 1267356341Scy int getaddrinfo_failed = 0; 1268335640Shselasky 1269335640Shselasky /* 1270335640Shselasky * The problem is that strtok modifies the original variable by putting '0' at the end of each token 1271335640Shselasky * So, we have to create a new temporary string in which the original content is kept 1272335640Shselasky */ 1273335640Shselasky temphostlist = strdup(hostlist); 1274335640Shselasky if (temphostlist == NULL) 1275335640Shselasky { 1276335640Shselasky sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen); 1277335640Shselasky return -2; 1278335640Shselasky } 1279335640Shselasky 1280335640Shselasky token = pcap_strtok_r(temphostlist, sep, &lasts); 1281335640Shselasky 1282335640Shselasky /* it avoids a warning in the compilation ('addrinfo used but not initialized') */ 1283335640Shselasky addrinfo = NULL; 1284335640Shselasky 1285335640Shselasky while (token != NULL) 1286335640Shselasky { 1287335640Shselasky struct addrinfo hints; 1288335640Shselasky int retval; 1289335640Shselasky 1290335640Shselasky addrinfo = NULL; 1291335640Shselasky memset(&hints, 0, sizeof(struct addrinfo)); 1292335640Shselasky hints.ai_family = PF_UNSPEC; 1293335640Shselasky hints.ai_socktype = SOCK_STREAM; 1294335640Shselasky 1295356341Scy retval = getaddrinfo(token, NULL, &hints, &addrinfo); 1296335640Shselasky if (retval != 0) 1297335640Shselasky { 1298335640Shselasky if (errbuf) 1299356341Scy get_gai_errstring(errbuf, errbuflen, 1300356341Scy "Allowed host list error: ", 1301356341Scy retval, token, NULL); 1302335640Shselasky 1303356341Scy /* 1304356341Scy * Note that at least one call to getaddrinfo() 1305356341Scy * failed. 1306356341Scy */ 1307356341Scy getaddrinfo_failed = 1; 1308335640Shselasky 1309335640Shselasky /* Get next token */ 1310335640Shselasky token = pcap_strtok_r(NULL, sep, &lasts); 1311335640Shselasky continue; 1312335640Shselasky } 1313335640Shselasky 1314335640Shselasky /* ai_next is required to preserve the content of addrinfo, in order to deallocate it properly */ 1315335640Shselasky ai_next = addrinfo; 1316335640Shselasky while (ai_next) 1317335640Shselasky { 1318335640Shselasky if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0) 1319335640Shselasky { 1320335640Shselasky free(temphostlist); 1321335640Shselasky freeaddrinfo(addrinfo); 1322335640Shselasky return 0; 1323335640Shselasky } 1324335640Shselasky 1325335640Shselasky /* 1326335640Shselasky * If we are here, it means that the current address does not matches 1327335640Shselasky * Let's try with the next one in the header chain 1328335640Shselasky */ 1329335640Shselasky ai_next = ai_next->ai_next; 1330335640Shselasky } 1331335640Shselasky 1332335640Shselasky freeaddrinfo(addrinfo); 1333335640Shselasky addrinfo = NULL; 1334335640Shselasky 1335335640Shselasky /* Get next token */ 1336335640Shselasky token = pcap_strtok_r(NULL, sep, &lasts); 1337335640Shselasky } 1338335640Shselasky 1339335640Shselasky if (addrinfo) 1340335640Shselasky { 1341335640Shselasky freeaddrinfo(addrinfo); 1342335640Shselasky addrinfo = NULL; 1343335640Shselasky } 1344335640Shselasky 1345356341Scy free(temphostlist); 1346335640Shselasky 1347356341Scy if (getaddrinfo_failed) { 1348356341Scy /* 1349356341Scy * At least one getaddrinfo() call failed; 1350356341Scy * treat that as an error, so rpcapd knows 1351356341Scy * that it should log it locally as well 1352356341Scy * as telling the client about it. 1353356341Scy */ 1354356341Scy return -2; 1355356341Scy } else { 1356356341Scy /* 1357356341Scy * All getaddrinfo() calls succeeded, but 1358356341Scy * the host wasn't in the list. 1359356341Scy */ 1360356341Scy if (errbuf) 1361356341Scy pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused."); 1362356341Scy return -1; 1363356341Scy } 1364335640Shselasky } 1365335640Shselasky 1366335640Shselasky /* No hostlist, so we have to return 'empty list' */ 1367335640Shselasky return 1; 1368335640Shselasky} 1369335640Shselasky 1370335640Shselasky/* 1371335640Shselasky * \brief Compares two addresses contained into two sockaddr_storage structures. 1372335640Shselasky * 1373335640Shselasky * This function is useful to compare two addresses, given their internal representation, 1374335640Shselasky * i.e. an sockaddr_storage structure. 1375335640Shselasky * 1376335640Shselasky * The two structures do not need to be sockaddr_storage; you can have both 'sockaddr_in' and 1377335640Shselasky * sockaddr_in6, properly acsted in order to be compliant to the function interface. 1378335640Shselasky * 1379335640Shselasky * This function will return '0' if the two addresses matches, '-1' if not. 1380335640Shselasky * 1381335640Shselasky * \param first: a sockaddr_storage structure, (for example the one that is returned by an 1382335640Shselasky * accept() call), containing the first address to compare. 1383335640Shselasky * 1384335640Shselasky * \param second: a sockaddr_storage structure containing the second address to compare. 1385335640Shselasky * 1386335640Shselasky * \return '0' if the addresses are equal, '-1' if they are different. 1387335640Shselasky */ 1388335640Shselaskyint sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second) 1389335640Shselasky{ 1390335640Shselasky if (first->ss_family == second->ss_family) 1391335640Shselasky { 1392335640Shselasky if (first->ss_family == AF_INET) 1393335640Shselasky { 1394335640Shselasky if (memcmp(&(((struct sockaddr_in *) first)->sin_addr), 1395335640Shselasky &(((struct sockaddr_in *) second)->sin_addr), 1396335640Shselasky sizeof(struct in_addr)) == 0) 1397335640Shselasky return 0; 1398335640Shselasky } 1399335640Shselasky else /* address family is AF_INET6 */ 1400335640Shselasky { 1401335640Shselasky if (memcmp(&(((struct sockaddr_in6 *) first)->sin6_addr), 1402335640Shselasky &(((struct sockaddr_in6 *) second)->sin6_addr), 1403335640Shselasky sizeof(struct in6_addr)) == 0) 1404335640Shselasky return 0; 1405335640Shselasky } 1406335640Shselasky } 1407335640Shselasky 1408335640Shselasky return -1; 1409335640Shselasky} 1410335640Shselasky 1411335640Shselasky/* 1412335640Shselasky * \brief It gets the address/port the system picked for this socket (on connected sockets). 1413335640Shselasky * 1414335640Shselasky * It is used to return the address and port the server picked for our socket on the local machine. 1415335640Shselasky * It works only on: 1416335640Shselasky * - connected sockets 1417335640Shselasky * - server sockets 1418335640Shselasky * 1419335640Shselasky * On unconnected client sockets it does not work because the system dynamically chooses a port 1420335640Shselasky * only when the socket calls a send() call. 1421335640Shselasky * 1422335640Shselasky * \param sock: the connected socket currently opened. 1423335640Shselasky * 1424335640Shselasky * \param address: it contains the address that will be returned by the function. This buffer 1425335640Shselasky * must be properly allocated by the user. The address can be either literal or numeric depending 1426335640Shselasky * on the value of 'Flags'. 1427335640Shselasky * 1428335640Shselasky * \param addrlen: the length of the 'address' buffer. 1429335640Shselasky * 1430335640Shselasky * \param port: it contains the port that will be returned by the function. This buffer 1431335640Shselasky * must be properly allocated by the user. 1432335640Shselasky * 1433335640Shselasky * \param portlen: the length of the 'port' buffer. 1434335640Shselasky * 1435335640Shselasky * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function) 1436335640Shselasky * that determine if the resulting address must be in numeric / literal form, and so on. 1437335640Shselasky * 1438335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 1439335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 1440335640Shselasky * It can be NULL; in this case the error cannot be printed. 1441335640Shselasky * 1442335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 1443335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 1444335640Shselasky * 1445335640Shselasky * \return It returns '-1' if this function succeeds, '0' otherwise. 1446335640Shselasky * The address and port corresponding are returned back in the buffers 'address' and 'port'. 1447335640Shselasky * In any case, the returned strings are '0' terminated. 1448335640Shselasky * 1449335640Shselasky * \warning If the socket is using a connectionless protocol, the address may not be available 1450335640Shselasky * until I/O occurs on the socket. 1451335640Shselasky */ 1452335640Shselaskyint sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) 1453335640Shselasky{ 1454335640Shselasky struct sockaddr_storage mysockaddr; 1455335640Shselasky socklen_t sockaddrlen; 1456335640Shselasky 1457335640Shselasky 1458335640Shselasky sockaddrlen = sizeof(struct sockaddr_storage); 1459335640Shselasky 1460335640Shselasky if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1) 1461335640Shselasky { 1462356341Scy sock_geterror("getsockname()", errbuf, errbuflen); 1463335640Shselasky return 0; 1464335640Shselasky } 1465335640Shselasky 1466335640Shselasky /* Returns the numeric address of the host that triggered the error */ 1467335640Shselasky return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen); 1468335640Shselasky} 1469335640Shselasky 1470335640Shselasky/* 1471335640Shselasky * \brief It retrieves two strings containing the address and the port of a given 'sockaddr' variable. 1472335640Shselasky * 1473335640Shselasky * This function is basically an extended version of the inet_ntop(), which does not exist in 1474335640Shselasky * Winsock because the same result can be obtained by using the getnameinfo(). 1475335640Shselasky * However, differently from inet_ntop(), this function is able to return also literal names 1476335640Shselasky * (e.g. 'localhost') dependently from the 'Flags' parameter. 1477335640Shselasky * 1478335640Shselasky * The function accepts a sockaddr_storage variable (which can be returned by several functions 1479335640Shselasky * like bind(), connect(), accept(), and more) and it transforms its content into a 'human' 1480335640Shselasky * form. So, for instance, it is able to translate an hex address (stored in binary form) into 1481335640Shselasky * a standard IPv6 address like "::1". 1482335640Shselasky * 1483335640Shselasky * The behavior of this function depends on the parameters we have in the 'Flags' variable, which 1484335640Shselasky * are the ones allowed in the standard getnameinfo() socket function. 1485335640Shselasky * 1486335640Shselasky * \param sockaddr: a 'sockaddr_in' or 'sockaddr_in6' structure containing the address that 1487335640Shselasky * need to be translated from network form into the presentation form. This structure must be 1488335640Shselasky * zero-ed prior using it, and the address family field must be filled with the proper value. 1489335640Shselasky * The user must cast any 'sockaddr_in' or 'sockaddr_in6' structures to 'sockaddr_storage' before 1490335640Shselasky * calling this function. 1491335640Shselasky * 1492335640Shselasky * \param address: it contains the address that will be returned by the function. This buffer 1493335640Shselasky * must be properly allocated by the user. The address can be either literal or numeric depending 1494335640Shselasky * on the value of 'Flags'. 1495335640Shselasky * 1496335640Shselasky * \param addrlen: the length of the 'address' buffer. 1497335640Shselasky * 1498335640Shselasky * \param port: it contains the port that will be returned by the function. This buffer 1499335640Shselasky * must be properly allocated by the user. 1500335640Shselasky * 1501335640Shselasky * \param portlen: the length of the 'port' buffer. 1502335640Shselasky * 1503335640Shselasky * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function) 1504335640Shselasky * that determine if the resulting address must be in numeric / literal form, and so on. 1505335640Shselasky * 1506335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 1507335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 1508335640Shselasky * It can be NULL; in this case the error cannot be printed. 1509335640Shselasky * 1510335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 1511335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 1512335640Shselasky * 1513335640Shselasky * \return It returns '-1' if this function succeeds, '0' otherwise. 1514335640Shselasky * The address and port corresponding to the given SockAddr are returned back in the buffers 'address' 1515335640Shselasky * and 'port'. 1516335640Shselasky * In any case, the returned strings are '0' terminated. 1517335640Shselasky */ 1518335640Shselaskyint sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) 1519335640Shselasky{ 1520335640Shselasky socklen_t sockaddrlen; 1521335640Shselasky int retval; /* Variable that keeps the return value; */ 1522335640Shselasky 1523335640Shselasky retval = -1; 1524335640Shselasky 1525335640Shselasky#ifdef _WIN32 1526335640Shselasky if (sockaddr->ss_family == AF_INET) 1527335640Shselasky sockaddrlen = sizeof(struct sockaddr_in); 1528335640Shselasky else 1529335640Shselasky sockaddrlen = sizeof(struct sockaddr_in6); 1530335640Shselasky#else 1531335640Shselasky sockaddrlen = sizeof(struct sockaddr_storage); 1532335640Shselasky#endif 1533335640Shselasky 1534335640Shselasky if ((flags & NI_NUMERICHOST) == 0) /* Check that we want literal names */ 1535335640Shselasky { 1536335640Shselasky if ((sockaddr->ss_family == AF_INET6) && 1537335640Shselasky (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)) 1538335640Shselasky { 1539335640Shselasky if (address) 1540356341Scy pcap_strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen); 1541335640Shselasky return retval; 1542335640Shselasky } 1543335640Shselasky } 1544335640Shselasky 1545335640Shselasky if (getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0) 1546335640Shselasky { 1547335640Shselasky /* If the user wants to receive an error message */ 1548335640Shselasky if (errbuf) 1549335640Shselasky { 1550356341Scy sock_geterror("getnameinfo()", errbuf, errbuflen); 1551335640Shselasky errbuf[errbuflen - 1] = 0; 1552335640Shselasky } 1553335640Shselasky 1554335640Shselasky if (address) 1555335640Shselasky { 1556356341Scy pcap_strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen); 1557335640Shselasky address[addrlen - 1] = 0; 1558335640Shselasky } 1559335640Shselasky 1560335640Shselasky if (port) 1561335640Shselasky { 1562356341Scy pcap_strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen); 1563335640Shselasky port[portlen - 1] = 0; 1564335640Shselasky } 1565335640Shselasky 1566335640Shselasky retval = 0; 1567335640Shselasky } 1568335640Shselasky 1569335640Shselasky return retval; 1570335640Shselasky} 1571335640Shselasky 1572335640Shselasky/* 1573335640Shselasky * \brief It translates an address from the 'presentation' form into the 'network' form. 1574335640Shselasky * 1575335640Shselasky * This function basically replaces inet_pton(), which does not exist in Winsock because 1576335640Shselasky * the same result can be obtained by using the getaddrinfo(). 1577335640Shselasky * An additional advantage is that 'Address' can be both a numeric address (e.g. '127.0.0.1', 1578335640Shselasky * like in inet_pton() ) and a literal name (e.g. 'localhost'). 1579335640Shselasky * 1580335640Shselasky * This function does the reverse job of sock_getascii_addrport(). 1581335640Shselasky * 1582335640Shselasky * \param address: a zero-terminated string which contains the name you have to 1583335640Shselasky * translate. The name can be either literal (e.g. 'localhost') or numeric (e.g. '::1'). 1584335640Shselasky * 1585335640Shselasky * \param sockaddr: a user-allocated sockaddr_storage structure which will contains the 1586335640Shselasky * 'network' form of the requested address. 1587335640Shselasky * 1588335640Shselasky * \param addr_family: a constant which can assume the following values: 1589335640Shselasky * - 'AF_INET' if we want to ping an IPv4 host 1590335640Shselasky * - 'AF_INET6' if we want to ping an IPv6 host 1591335640Shselasky * - 'AF_UNSPEC' if we do not have preferences about the protocol used to ping the host 1592335640Shselasky * 1593335640Shselasky * \param errbuf: a pointer to an user-allocated buffer that will contain the complete 1594335640Shselasky * error message. This buffer has to be at least 'errbuflen' in length. 1595335640Shselasky * It can be NULL; in this case the error cannot be printed. 1596335640Shselasky * 1597335640Shselasky * \param errbuflen: length of the buffer that will contains the error. The error message cannot be 1598335640Shselasky * larger than 'errbuflen - 1' because the last char is reserved for the string terminator. 1599335640Shselasky * 1600335640Shselasky * \return '-1' if the translation succeeded, '-2' if there was some non critical error, '0' 1601335640Shselasky * otherwise. In case it fails, the content of the SockAddr variable remains unchanged. 1602335640Shselasky * A 'non critical error' can occur in case the 'Address' is a literal name, which can be mapped 1603335640Shselasky * to several network addresses (e.g. 'foo.bar.com' => '10.2.2.2' and '10.2.2.3'). In this case 1604335640Shselasky * the content of the SockAddr parameter will be the address corresponding to the first mapping. 1605335640Shselasky * 1606335640Shselasky * \warning The sockaddr_storage structure MUST be allocated by the user. 1607335640Shselasky */ 1608335640Shselaskyint sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen) 1609335640Shselasky{ 1610335640Shselasky int retval; 1611335640Shselasky struct addrinfo *addrinfo; 1612335640Shselasky struct addrinfo hints; 1613335640Shselasky 1614335640Shselasky memset(&hints, 0, sizeof(hints)); 1615335640Shselasky 1616335640Shselasky hints.ai_family = addr_family; 1617335640Shselasky 1618335640Shselasky if ((retval = sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1) 1619335640Shselasky return 0; 1620335640Shselasky 1621335640Shselasky if (addrinfo->ai_family == PF_INET) 1622335640Shselasky memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in)); 1623335640Shselasky else 1624335640Shselasky memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6)); 1625335640Shselasky 1626335640Shselasky if (addrinfo->ai_next != NULL) 1627335640Shselasky { 1628335640Shselasky freeaddrinfo(addrinfo); 1629335640Shselasky 1630335640Shselasky if (errbuf) 1631335640Shselasky pcap_snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned"); 1632335640Shselasky return -2; 1633335640Shselasky } 1634335640Shselasky 1635335640Shselasky freeaddrinfo(addrinfo); 1636335640Shselasky return -1; 1637335640Shselasky} 1638