source: MondoRescue/branches/3.3/mindi-busybox/libbb/inet_common.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 4.6 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * stolen from net-tools-1.59 and stripped down for busybox by
4 * Erik Andersen <andersen@codepoet.org>
5 *
6 * Heavily modified by Manuel Novoa III Mar 12, 2001
7 *
8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */
10
11#include "libbb.h"
12#include "inet_common.h"
13
14int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst)
15{
16 struct hostent *hp;
17#if ENABLE_FEATURE_ETC_NETWORKS
18 struct netent *np;
19#endif
20
21 /* Grmpf. -FvK */
22 s_in->sin_family = AF_INET;
23 s_in->sin_port = 0;
24
25 /* Default is special, meaning 0.0.0.0. */
26 if (strcmp(name, "default") == 0) {
27 s_in->sin_addr.s_addr = INADDR_ANY;
28 return 1;
29 }
30 /* Look to see if it's a dotted quad. */
31 if (inet_aton(name, &s_in->sin_addr)) {
32 return 0;
33 }
34 /* If we expect this to be a hostname, try hostname database first */
35 if (hostfirst) {
36#ifdef DEBUG
37 bb_error_msg("gethostbyname(%s)", name);
38#endif
39 hp = gethostbyname(name);
40 if (hp) {
41 memcpy(&s_in->sin_addr, hp->h_addr_list[0],
42 sizeof(struct in_addr));
43 return 0;
44 }
45 }
46#if ENABLE_FEATURE_ETC_NETWORKS
47 /* Try the NETWORKS database to see if this is a known network. */
48#ifdef DEBUG
49 bb_error_msg("getnetbyname(%s)", name);
50#endif
51 np = getnetbyname(name);
52 if (np) {
53 s_in->sin_addr.s_addr = htonl(np->n_net);
54 return 1;
55 }
56#endif
57 if (hostfirst) {
58 /* Don't try again */
59 return -1;
60 }
61#ifdef DEBUG
62 res_init();
63 _res.options |= RES_DEBUG;
64 bb_error_msg("gethostbyname(%s)", name);
65#endif
66 hp = gethostbyname(name);
67 if (!hp) {
68 return -1;
69 }
70 memcpy(&s_in->sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
71 return 0;
72}
73
74
75/* numeric: & 0x8000: "default" instead of "*",
76 * & 0x4000: host instead of net,
77 * & 0x0fff: don't resolve
78 */
79char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t netmask)
80{
81 /* addr-to-name cache */
82 struct addr {
83 struct addr *next;
84 uint32_t nip;
85 smallint is_host;
86 char name[1];
87 };
88 static struct addr *cache = NULL;
89
90 struct addr *pn;
91 char *name;
92 uint32_t nip;
93 smallint is_host;
94
95 if (s_in->sin_family != AF_INET) {
96#ifdef DEBUG
97 bb_error_msg("rresolve: unsupported address family %d!",
98 s_in->sin_family);
99#endif
100 errno = EAFNOSUPPORT;
101 return NULL;
102 }
103 nip = s_in->sin_addr.s_addr;
104#ifdef DEBUG
105 bb_error_msg("rresolve: %08x mask:%08x num:%08x", (unsigned)nip, netmask, numeric);
106#endif
107 if (numeric & 0x0FFF)
108 return xmalloc_sockaddr2dotted_noport((void*)s_in);
109 if (nip == INADDR_ANY) {
110 if (numeric & 0x8000)
111 return xstrdup("default");
112 return xstrdup("*");
113 }
114
115 is_host = ((nip & (~netmask)) != 0 || (numeric & 0x4000));
116
117 pn = cache;
118 while (pn) {
119 if (pn->nip == nip && pn->is_host == is_host) {
120#ifdef DEBUG
121 bb_error_msg("rresolve: found %s %08x in cache",
122 (is_host ? "host" : "net"), (unsigned)nip);
123#endif
124 return xstrdup(pn->name);
125 }
126 pn = pn->next;
127 }
128
129 name = NULL;
130 if (is_host) {
131#ifdef DEBUG
132 bb_error_msg("sockaddr2host_noport(%08x)", (unsigned)nip);
133#endif
134 name = xmalloc_sockaddr2host_noport((void*)s_in);
135 } else if (ENABLE_FEATURE_ETC_NETWORKS) {
136 struct netent *np;
137#ifdef DEBUG
138 bb_error_msg("getnetbyaddr(%08x)", (unsigned)ntohl(nip));
139#endif
140 np = getnetbyaddr(ntohl(nip), AF_INET);
141 if (np)
142 name = xstrdup(np->n_name);
143 }
144 if (!name)
145 name = xmalloc_sockaddr2dotted_noport((void*)s_in);
146
147 pn = xmalloc(sizeof(*pn) + strlen(name)); /* no '+ 1', it's already accounted for */
148 pn->next = cache;
149 pn->nip = nip;
150 pn->is_host = is_host;
151 strcpy(pn->name, name);
152 cache = pn;
153
154 return name;
155}
156
157#if ENABLE_FEATURE_IPV6
158
159int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
160{
161 struct addrinfo req, *ai = NULL;
162 int s;
163
164 memset(&req, 0, sizeof(req));
165 req.ai_family = AF_INET6;
166 s = getaddrinfo(name, NULL, &req, &ai);
167 if (s != 0) {
168 bb_error_msg("getaddrinfo: %s: %d", name, s);
169 return -1;
170 }
171 memcpy(sin6, ai->ai_addr, sizeof(*sin6));
172 freeaddrinfo(ai);
173 return 0;
174}
175
176#ifndef IN6_IS_ADDR_UNSPECIFIED
177# define IN6_IS_ADDR_UNSPECIFIED(a) \
178 (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
179 ((uint32_t *) (a))[2] == 0 && ((uint32_t *) (a))[3] == 0)
180#endif
181
182
183char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric)
184{
185 if (sin6->sin6_family != AF_INET6) {
186#ifdef DEBUG
187 bb_error_msg("rresolve: unsupported address family %d!",
188 sin6->sin6_family);
189#endif
190 errno = EAFNOSUPPORT;
191 return NULL;
192 }
193 if (numeric & 0x7FFF) {
194 return xmalloc_sockaddr2dotted_noport((void*)sin6);
195 }
196 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
197 if (numeric & 0x8000)
198 return xstrdup("default");
199 return xstrdup("*");
200 }
201
202 return xmalloc_sockaddr2host_noport((void*)sin6);
203}
204
205#endif /* CONFIG_FEATURE_IPV6 */
Note: See TracBrowser for help on using the repository browser.