xref: /freebsd/lib/libfetch/common.c (revision d8acd8dc5cb2a0ce54609c9c1d94cff16792902a)
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