1
2
3
4
5
6
7
8
9
10#include <netinet/in.h>
11#include <net/if.h>
12#include <sys/un.h>
13#include "libbb.h"
14
15void FAST_FUNC setsockopt_reuseaddr(int fd)
16{
17 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1));
18}
19int FAST_FUNC setsockopt_broadcast(int fd)
20{
21 return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1));
22}
23int FAST_FUNC setsockopt_bindtodevice(int fd, const char *iface)
24{
25 int r;
26 struct ifreq ifr;
27 strncpy_IFNAMSIZ(ifr.ifr_name, iface);
28
29
30
31
32
33 r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
34 if (r)
35 bb_perror_msg("can't bind to interface %s", iface);
36 return r;
37}
38
39len_and_sockaddr* FAST_FUNC get_sock_lsa(int fd)
40{
41 len_and_sockaddr lsa;
42 len_and_sockaddr *lsa_ptr;
43
44 lsa.len = LSA_SIZEOF_SA;
45 if (getsockname(fd, &lsa.u.sa, &lsa.len) != 0)
46 return NULL;
47
48 lsa_ptr = xzalloc(LSA_LEN_SIZE + lsa.len);
49 if (lsa.len > LSA_SIZEOF_SA) {
50 lsa_ptr->len = lsa.len;
51 getsockname(fd, &lsa_ptr->u.sa, &lsa_ptr->len);
52 } else {
53 memcpy(lsa_ptr, &lsa, LSA_LEN_SIZE + lsa.len);
54 }
55 return lsa_ptr;
56}
57
58void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
59{
60 if (connect(s, s_addr, addrlen) < 0) {
61 if (ENABLE_FEATURE_CLEAN_UP)
62 close(s);
63 if (s_addr->sa_family == AF_INET)
64 bb_perror_msg_and_die("%s (%s)",
65 "cannot connect to remote host",
66 inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr));
67 bb_perror_msg_and_die("cannot connect to remote host");
68 }
69}
70
71
72
73
74
75
76unsigned FAST_FUNC bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
77{
78 unsigned port_nr = default_port;
79 if (port) {
80 int old_errno;
81
82
83
84 old_errno = errno;
85 port_nr = bb_strtou(port, NULL, 10);
86 if (errno || port_nr > 65535) {
87 struct servent *tserv = getservbyname(port, protocol);
88 port_nr = default_port;
89 if (tserv)
90 port_nr = ntohs(tserv->s_port);
91 }
92 errno = old_errno;
93 }
94 return (uint16_t)port_nr;
95}
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123int FAST_FUNC get_nport(const struct sockaddr *sa)
124{
125#if ENABLE_FEATURE_IPV6
126 if (sa->sa_family == AF_INET6) {
127 return ((struct sockaddr_in6*)sa)->sin6_port;
128 }
129#endif
130 if (sa->sa_family == AF_INET) {
131 return ((struct sockaddr_in*)sa)->sin_port;
132 }
133
134 return -1;
135}
136
137void FAST_FUNC set_nport(len_and_sockaddr *lsa, unsigned port)
138{
139#if ENABLE_FEATURE_IPV6
140 if (lsa->u.sa.sa_family == AF_INET6) {
141 lsa->u.sin6.sin6_port = port;
142 return;
143 }
144#endif
145 if (lsa->u.sa.sa_family == AF_INET) {
146 lsa->u.sin.sin_port = port;
147 return;
148 }
149
150}
151
152
153
154#define DIE_ON_ERROR AI_CANONNAME
155
156
157
158static len_and_sockaddr* str2sockaddr(
159 const char *host, int port,
160IF_FEATURE_IPV6(sa_family_t af,)
161 int ai_flags)
162{
163 int rc;
164 len_and_sockaddr *r;
165 struct addrinfo *result = NULL;
166 struct addrinfo *used_res;
167 const char *org_host = host;
168 const char *cp;
169 struct addrinfo hint;
170
171 if (ENABLE_FEATURE_UNIX_LOCAL && strncmp(host, "local:", 6) == 0) {
172 struct sockaddr_un *sun;
173
174 r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un));
175 r->len = sizeof(struct sockaddr_un);
176 r->u.sa.sa_family = AF_UNIX;
177 sun = (struct sockaddr_un *)&r->u.sa;
178 safe_strncpy(sun->sun_path, host + 6, sizeof(sun->sun_path));
179 return r;
180 }
181
182 r = NULL;
183
184
185 if (ENABLE_FEATURE_IPV6 && host[0] == '[') {
186
187 host++;
188 cp = strchr(host, ']');
189 if (!cp || (cp[1] != ':' && cp[1] != '\0')) {
190
191 bb_error_msg("bad address '%s'", org_host);
192 if (ai_flags & DIE_ON_ERROR)
193 xfunc_die();
194 return NULL;
195 }
196 } else {
197 cp = strrchr(host, ':');
198 if (ENABLE_FEATURE_IPV6 && cp && strchr(host, ':') != cp) {
199
200 cp = NULL;
201 }
202 }
203 if (cp) {
204 int sz = cp - host + 1;
205
206 host = safe_strncpy(alloca(sz), host, sz);
207 if (ENABLE_FEATURE_IPV6 && *cp != ':') {
208 cp++;
209 if (*cp == '\0')
210 goto skip;
211 }
212 cp++;
213 port = bb_strtou(cp, NULL, 10);
214 if (errno || (unsigned)port > 0xffff) {
215 bb_error_msg("bad port spec '%s'", org_host);
216 if (ai_flags & DIE_ON_ERROR)
217 xfunc_die();
218 return NULL;
219 }
220 skip: ;
221 }
222
223 memset(&hint, 0 , sizeof(hint));
224#if !ENABLE_FEATURE_IPV6
225 hint.ai_family = AF_INET;
226#else
227 hint.ai_family = af;
228#endif
229
230
231 hint.ai_socktype = SOCK_STREAM;
232 hint.ai_flags = ai_flags & ~DIE_ON_ERROR;
233 rc = getaddrinfo(host, NULL, &hint, &result);
234 if (rc || !result) {
235 bb_error_msg("bad address '%s'", org_host);
236 if (ai_flags & DIE_ON_ERROR)
237 xfunc_die();
238 goto ret;
239 }
240 used_res = result;
241#if ENABLE_FEATURE_PREFER_IPV4_ADDRESS
242 while (1) {
243 if (used_res->ai_family == AF_INET)
244 break;
245 used_res = used_res->ai_next;
246 if (!used_res) {
247 used_res = result;
248 break;
249 }
250 }
251#endif
252 r = xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen);
253 r->len = used_res->ai_addrlen;
254 memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen);
255 set_nport(r, htons(port));
256 ret:
257 freeaddrinfo(result);
258 return r;
259}
260#if !ENABLE_FEATURE_IPV6
261#define str2sockaddr(host, port, af, ai_flags) str2sockaddr(host, port, ai_flags)
262#endif
263
264#if ENABLE_FEATURE_IPV6
265len_and_sockaddr* FAST_FUNC host_and_af2sockaddr(const char *host, int port, sa_family_t af)
266{
267 return str2sockaddr(host, port, af, 0);
268}
269
270len_and_sockaddr* FAST_FUNC xhost_and_af2sockaddr(const char *host, int port, sa_family_t af)
271{
272 return str2sockaddr(host, port, af, DIE_ON_ERROR);
273}
274#endif
275
276len_and_sockaddr* FAST_FUNC host2sockaddr(const char *host, int port)
277{
278 return str2sockaddr(host, port, AF_UNSPEC, 0);
279}
280
281len_and_sockaddr* FAST_FUNC xhost2sockaddr(const char *host, int port)
282{
283 return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR);
284}
285
286len_and_sockaddr* FAST_FUNC xdotted2sockaddr(const char *host, int port)
287{
288 return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR);
289}
290
291#undef xsocket_type
292int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, IF_FEATURE_IPV6(int family,) int sock_type)
293{
294 IF_NOT_FEATURE_IPV6(enum { family = AF_INET };)
295 len_and_sockaddr *lsa;
296 int fd;
297 int len;
298
299#if ENABLE_FEATURE_IPV6
300 if (family == AF_UNSPEC) {
301 fd = socket(AF_INET6, sock_type, 0);
302 if (fd >= 0) {
303 family = AF_INET6;
304 goto done;
305 }
306 family = AF_INET;
307 }
308#endif
309 fd = xsocket(family, sock_type, 0);
310 len = sizeof(struct sockaddr_in);
311#if ENABLE_FEATURE_IPV6
312 if (family == AF_INET6) {
313 done:
314 len = sizeof(struct sockaddr_in6);
315 }
316#endif
317 lsa = xzalloc(offsetof(len_and_sockaddr, u.sa) + len);
318 lsa->len = len;
319 lsa->u.sa.sa_family = family;
320 *lsap = lsa;
321 return fd;
322}
323
324int FAST_FUNC xsocket_stream(len_and_sockaddr **lsap)
325{
326 return xsocket_type(lsap, IF_FEATURE_IPV6(AF_UNSPEC,) SOCK_STREAM);
327}
328
329static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type)
330{
331 int fd;
332 len_and_sockaddr *lsa;
333
334 if (bindaddr && bindaddr[0]) {
335 lsa = xdotted2sockaddr(bindaddr, port);
336
337 fd = xsocket(lsa->u.sa.sa_family, sock_type, 0);
338 } else {
339 fd = xsocket_type(&lsa, IF_FEATURE_IPV6(AF_UNSPEC,) sock_type);
340 set_nport(lsa, htons(port));
341 }
342 setsockopt_reuseaddr(fd);
343 xbind(fd, &lsa->u.sa, lsa->len);
344 free(lsa);
345 return fd;
346}
347
348int FAST_FUNC create_and_bind_stream_or_die(const char *bindaddr, int port)
349{
350 return create_and_bind_or_die(bindaddr, port, SOCK_STREAM);
351}
352
353int FAST_FUNC create_and_bind_dgram_or_die(const char *bindaddr, int port)
354{
355 return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM);
356}
357
358
359int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port)
360{
361 int fd;
362 len_and_sockaddr *lsa;
363
364 lsa = xhost2sockaddr(peer, port);
365 fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
366 setsockopt_reuseaddr(fd);
367 xconnect(fd, &lsa->u.sa, lsa->len);
368 free(lsa);
369 return fd;
370}
371
372int FAST_FUNC xconnect_stream(const len_and_sockaddr *lsa)
373{
374 int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
375 xconnect(fd, &lsa->u.sa, lsa->len);
376 return fd;
377}
378
379
380
381#define IGNORE_PORT NI_NUMERICSERV
382static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags)
383{
384 char host[128];
385 char serv[16];
386 int rc;
387 socklen_t salen;
388
389 if (ENABLE_FEATURE_UNIX_LOCAL && sa->sa_family == AF_UNIX) {
390 struct sockaddr_un *sun = (struct sockaddr_un *)sa;
391 return xasprintf("local:%.*s",
392 (int) sizeof(sun->sun_path),
393 sun->sun_path);
394 }
395
396 salen = LSA_SIZEOF_SA;
397#if ENABLE_FEATURE_IPV6
398 if (sa->sa_family == AF_INET)
399 salen = sizeof(struct sockaddr_in);
400 if (sa->sa_family == AF_INET6)
401 salen = sizeof(struct sockaddr_in6);
402#endif
403 rc = getnameinfo(sa, salen,
404 host, sizeof(host),
405
406 serv, sizeof(serv),
407
408 flags | NI_NUMERICSERV
409 );
410 if (rc)
411 return NULL;
412 if (flags & IGNORE_PORT)
413 return xstrdup(host);
414#if ENABLE_FEATURE_IPV6
415 if (sa->sa_family == AF_INET6) {
416 if (strchr(host, ':'))
417 return xasprintf("[%s]:%s", host, serv);
418
419
420 }
421#endif
422
423
424 return xasprintf("%s:%s", host, serv);
425
426}
427
428char* FAST_FUNC xmalloc_sockaddr2host(const struct sockaddr *sa)
429{
430 return sockaddr2str(sa, 0);
431}
432
433char* FAST_FUNC xmalloc_sockaddr2host_noport(const struct sockaddr *sa)
434{
435 return sockaddr2str(sa, IGNORE_PORT);
436}
437
438char* FAST_FUNC xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa)
439{
440 return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT);
441}
442char* FAST_FUNC xmalloc_sockaddr2dotted(const struct sockaddr *sa)
443{
444 return sockaddr2str(sa, NI_NUMERICHOST);
445}
446
447char* FAST_FUNC xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa)
448{
449 return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT);
450}
451