1842a95ccSDag-Erling Smørgrav /*- 2842a95ccSDag-Erling Smørgrav * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav 3842a95ccSDag-Erling Smørgrav * All rights reserved. 4842a95ccSDag-Erling Smørgrav * 5842a95ccSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 6842a95ccSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 7842a95ccSDag-Erling Smørgrav * are met: 8842a95ccSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 9842a95ccSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 10842a95ccSDag-Erling Smørgrav * in this position and unchanged. 11842a95ccSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 12842a95ccSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 13842a95ccSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 14842a95ccSDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 15842a95ccSDag-Erling Smørgrav * derived from this software without specific prior written permission 16842a95ccSDag-Erling Smørgrav * 17842a95ccSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18842a95ccSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19842a95ccSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20842a95ccSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21842a95ccSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22842a95ccSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23842a95ccSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24842a95ccSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25842a95ccSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26842a95ccSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27842a95ccSDag-Erling Smørgrav * 28d8acd8dcSDag-Erling Smørgrav * $Id: common.c,v 1.1 1998/11/05 19:48:16 des Exp $ 29842a95ccSDag-Erling Smørgrav */ 30842a95ccSDag-Erling Smørgrav 31842a95ccSDag-Erling Smørgrav #include <sys/types.h> 32842a95ccSDag-Erling Smørgrav #include <sys/socket.h> 33842a95ccSDag-Erling Smørgrav #include <netinet/in.h> 34842a95ccSDag-Erling Smørgrav 35d8acd8dcSDag-Erling Smørgrav #include <com_err.h> 36842a95ccSDag-Erling Smørgrav #include <errno.h> 37842a95ccSDag-Erling Smørgrav #include <netdb.h> 38842a95ccSDag-Erling Smørgrav #include <string.h> 39842a95ccSDag-Erling Smørgrav #include <unistd.h> 40842a95ccSDag-Erling Smørgrav 41842a95ccSDag-Erling Smørgrav #include "fetch.h" 42842a95ccSDag-Erling Smørgrav #include "common.h" 43842a95ccSDag-Erling Smørgrav 44d8acd8dcSDag-Erling Smørgrav 45842a95ccSDag-Erling Smørgrav /*** Local data **************************************************************/ 46842a95ccSDag-Erling Smørgrav 47842a95ccSDag-Erling Smørgrav /* 48842a95ccSDag-Erling Smørgrav * Error messages for resolver errors 49842a95ccSDag-Erling Smørgrav */ 50842a95ccSDag-Erling Smørgrav static struct fetcherr _netdb_errlist[] = { 51d8acd8dcSDag-Erling Smørgrav { HOST_NOT_FOUND, FETCH_RESOLV, "Host not found" }, 52d8acd8dcSDag-Erling Smørgrav { TRY_AGAIN, FETCH_RESOLV, "Transient resolver failure" }, 53d8acd8dcSDag-Erling Smørgrav { NO_RECOVERY, FETCH_RESOLV, "Non-recoverable resolver failure" }, 54d8acd8dcSDag-Erling Smørgrav { NO_DATA, FETCH_RESOLV, "No address record" }, 55d8acd8dcSDag-Erling Smørgrav { -1, FETCH_UNKNOWN, "Unknown resolver error" } 56842a95ccSDag-Erling Smørgrav }; 57842a95ccSDag-Erling Smørgrav 58d8acd8dcSDag-Erling Smørgrav static int com_err_initialized; 59842a95ccSDag-Erling Smørgrav 60842a95ccSDag-Erling Smørgrav /*** Error-reporting functions ***********************************************/ 61842a95ccSDag-Erling Smørgrav 62842a95ccSDag-Erling Smørgrav /* 63d8acd8dcSDag-Erling Smørgrav * Initialize the common error library 64d8acd8dcSDag-Erling Smørgrav */ 65d8acd8dcSDag-Erling Smørgrav static void 66d8acd8dcSDag-Erling Smørgrav _fetch_init_com_err(void) 67d8acd8dcSDag-Erling Smørgrav { 68d8acd8dcSDag-Erling Smørgrav initialize_ftch_error_table(); 69d8acd8dcSDag-Erling Smørgrav com_err_initialized = 1; 70d8acd8dcSDag-Erling Smørgrav } 71d8acd8dcSDag-Erling Smørgrav 72d8acd8dcSDag-Erling Smørgrav /* 73842a95ccSDag-Erling Smørgrav * Map error code to string 74842a95ccSDag-Erling Smørgrav */ 75d8acd8dcSDag-Erling Smørgrav static int 76d8acd8dcSDag-Erling Smørgrav _fetch_finderr(struct fetcherr *p, int e) 77842a95ccSDag-Erling Smørgrav { 78d8acd8dcSDag-Erling Smørgrav int i; 79d8acd8dcSDag-Erling Smørgrav for (i = 0; p[i].num != -1; i++) 80d8acd8dcSDag-Erling Smørgrav if (p[i].num == e) 81d8acd8dcSDag-Erling Smørgrav break; 82d8acd8dcSDag-Erling Smørgrav return i; 83842a95ccSDag-Erling Smørgrav } 84842a95ccSDag-Erling Smørgrav 85842a95ccSDag-Erling Smørgrav /* 86842a95ccSDag-Erling Smørgrav * Set error code 87842a95ccSDag-Erling Smørgrav */ 88842a95ccSDag-Erling Smørgrav void 89842a95ccSDag-Erling Smørgrav _fetch_seterr(struct fetcherr *p, int e) 90842a95ccSDag-Erling Smørgrav { 91d8acd8dcSDag-Erling Smørgrav int n; 92d8acd8dcSDag-Erling Smørgrav 93d8acd8dcSDag-Erling Smørgrav if (!com_err_initialized) 94d8acd8dcSDag-Erling Smørgrav _fetch_init_com_err(); 95d8acd8dcSDag-Erling Smørgrav 96d8acd8dcSDag-Erling Smørgrav n = _fetch_finderr(p, e); 97d8acd8dcSDag-Erling Smørgrav com_err("libfetch", p[n].cat, "(%d %s)", e, p[n].string); 98842a95ccSDag-Erling Smørgrav } 99842a95ccSDag-Erling Smørgrav 100842a95ccSDag-Erling Smørgrav /* 101842a95ccSDag-Erling Smørgrav * Set error code according to errno 102842a95ccSDag-Erling Smørgrav */ 103842a95ccSDag-Erling Smørgrav void 104842a95ccSDag-Erling Smørgrav _fetch_syserr(void) 105842a95ccSDag-Erling Smørgrav { 106d8acd8dcSDag-Erling Smørgrav int cat; 107d8acd8dcSDag-Erling Smørgrav 108d8acd8dcSDag-Erling Smørgrav if (!com_err_initialized) 109d8acd8dcSDag-Erling Smørgrav _fetch_init_com_err(); 110d8acd8dcSDag-Erling Smørgrav 111d8acd8dcSDag-Erling Smørgrav switch (errno) { 112d8acd8dcSDag-Erling Smørgrav case 0: 113d8acd8dcSDag-Erling Smørgrav cat = FETCH_OK; 114d8acd8dcSDag-Erling Smørgrav break; 115d8acd8dcSDag-Erling Smørgrav case EPERM: 116d8acd8dcSDag-Erling Smørgrav case EACCES: 117d8acd8dcSDag-Erling Smørgrav case EROFS: 118d8acd8dcSDag-Erling Smørgrav case EAUTH: 119d8acd8dcSDag-Erling Smørgrav case ENEEDAUTH: 120d8acd8dcSDag-Erling Smørgrav cat = FETCH_AUTH; 121d8acd8dcSDag-Erling Smørgrav break; 122d8acd8dcSDag-Erling Smørgrav case ENOENT: 123d8acd8dcSDag-Erling Smørgrav case EISDIR: /* XXX */ 124d8acd8dcSDag-Erling Smørgrav cat = FETCH_UNAVAIL; 125d8acd8dcSDag-Erling Smørgrav break; 126d8acd8dcSDag-Erling Smørgrav case ENOMEM: 127d8acd8dcSDag-Erling Smørgrav cat = FETCH_MEMORY; 128d8acd8dcSDag-Erling Smørgrav break; 129d8acd8dcSDag-Erling Smørgrav case EBUSY: 130d8acd8dcSDag-Erling Smørgrav case EAGAIN: 131d8acd8dcSDag-Erling Smørgrav cat = FETCH_TEMP; 132d8acd8dcSDag-Erling Smørgrav break; 133d8acd8dcSDag-Erling Smørgrav case EEXIST: 134d8acd8dcSDag-Erling Smørgrav cat = FETCH_EXISTS; 135d8acd8dcSDag-Erling Smørgrav break; 136d8acd8dcSDag-Erling Smørgrav case ENOSPC: 137d8acd8dcSDag-Erling Smørgrav cat = FETCH_FULL; 138d8acd8dcSDag-Erling Smørgrav break; 139d8acd8dcSDag-Erling Smørgrav case EADDRINUSE: 140d8acd8dcSDag-Erling Smørgrav case EADDRNOTAVAIL: 141d8acd8dcSDag-Erling Smørgrav case ENETDOWN: 142d8acd8dcSDag-Erling Smørgrav case ENETUNREACH: 143d8acd8dcSDag-Erling Smørgrav case ENETRESET: 144d8acd8dcSDag-Erling Smørgrav case EHOSTUNREACH: 145d8acd8dcSDag-Erling Smørgrav cat = FETCH_NETWORK; 146d8acd8dcSDag-Erling Smørgrav break; 147d8acd8dcSDag-Erling Smørgrav case ECONNABORTED: 148d8acd8dcSDag-Erling Smørgrav case ECONNRESET: 149d8acd8dcSDag-Erling Smørgrav cat = FETCH_ABORT; 150d8acd8dcSDag-Erling Smørgrav break; 151d8acd8dcSDag-Erling Smørgrav case ETIMEDOUT: 152d8acd8dcSDag-Erling Smørgrav cat = FETCH_TIMEOUT; 153d8acd8dcSDag-Erling Smørgrav break; 154d8acd8dcSDag-Erling Smørgrav case ECONNREFUSED: 155d8acd8dcSDag-Erling Smørgrav case EHOSTDOWN: 156d8acd8dcSDag-Erling Smørgrav cat = FETCH_DOWN; 157d8acd8dcSDag-Erling Smørgrav break; 158d8acd8dcSDag-Erling Smørgrav default: 159d8acd8dcSDag-Erling Smørgrav cat = FETCH_UNKNOWN; 160d8acd8dcSDag-Erling Smørgrav } 161d8acd8dcSDag-Erling Smørgrav com_err("libfetch", cat, "(%02d %s)", errno, strerror(errno)); 162842a95ccSDag-Erling Smørgrav } 163842a95ccSDag-Erling Smørgrav 164842a95ccSDag-Erling Smørgrav 165842a95ccSDag-Erling Smørgrav /*** Network-related utility functions ***************************************/ 166842a95ccSDag-Erling Smørgrav 167842a95ccSDag-Erling Smørgrav /* 168842a95ccSDag-Erling Smørgrav * Establish a TCP connection to the specified port on the specified host. 169842a95ccSDag-Erling Smørgrav */ 170842a95ccSDag-Erling Smørgrav int 171842a95ccSDag-Erling Smørgrav fetchConnect(char *host, int port) 172842a95ccSDag-Erling Smørgrav { 173842a95ccSDag-Erling Smørgrav struct sockaddr_in sin; 174842a95ccSDag-Erling Smørgrav struct hostent *he; 175842a95ccSDag-Erling Smørgrav int sd; 176842a95ccSDag-Erling Smørgrav 177842a95ccSDag-Erling Smørgrav #ifndef NDEBUG 178842a95ccSDag-Erling Smørgrav fprintf(stderr, "\033[1m---> %s:%d\033[m\n", host, port); 179842a95ccSDag-Erling Smørgrav #endif 180842a95ccSDag-Erling Smørgrav 181842a95ccSDag-Erling Smørgrav /* look up host name */ 182842a95ccSDag-Erling Smørgrav if ((he = gethostbyname(host)) == NULL) { 183842a95ccSDag-Erling Smørgrav _netdb_seterr(h_errno); 184842a95ccSDag-Erling Smørgrav return -1; 185842a95ccSDag-Erling Smørgrav } 186842a95ccSDag-Erling Smørgrav 187842a95ccSDag-Erling Smørgrav /* set up socket address structure */ 188842a95ccSDag-Erling Smørgrav bzero(&sin, sizeof(sin)); 189842a95ccSDag-Erling Smørgrav bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length); 190842a95ccSDag-Erling Smørgrav sin.sin_family = he->h_addrtype; 191842a95ccSDag-Erling Smørgrav sin.sin_port = htons(port); 192842a95ccSDag-Erling Smørgrav 193842a95ccSDag-Erling Smørgrav /* try to connect */ 194842a95ccSDag-Erling Smørgrav if ((sd = socket(sin.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { 195842a95ccSDag-Erling Smørgrav _fetch_syserr(); 196842a95ccSDag-Erling Smørgrav return -1; 197842a95ccSDag-Erling Smørgrav } 198842a95ccSDag-Erling Smørgrav if (connect(sd, (struct sockaddr *)&sin, sizeof sin) == -1) { 199842a95ccSDag-Erling Smørgrav _fetch_syserr(); 200842a95ccSDag-Erling Smørgrav close(sd); 201842a95ccSDag-Erling Smørgrav return -1; 202842a95ccSDag-Erling Smørgrav } 203842a95ccSDag-Erling Smørgrav 204842a95ccSDag-Erling Smørgrav return sd; 205842a95ccSDag-Erling Smørgrav } 206