[autobuild] allow sendfile() in cross-compile (fixes #2836)
[lighttpd.git] / src / sock_addr.c
blob41fb92a0e2722babcb7f91ac6e78de6b4b293afd
1 #include "first.h"
3 #include "sock_addr.h"
5 #include "sys-socket.h"
6 #include <sys/types.h>
7 #include <errno.h>
8 #include <string.h>
9 #ifndef _WIN32
10 #include <netdb.h>
11 #include <arpa/inet.h>
12 #endif
14 #include "base.h"
15 #include "log.h"
18 unsigned short sock_addr_get_port (const sock_addr *saddr)
20 switch (saddr->plain.sa_family) {
21 case AF_INET:
22 return ntohs(saddr->ipv4.sin_port);
23 #ifdef HAVE_IPV6
24 case AF_INET6:
25 return ntohs(saddr->ipv6.sin6_port);
26 #endif
27 #ifdef HAVE_SYS_UN_H
28 /*case AF_UNIX:*/
29 #endif
30 default:
31 return 0;
36 int sock_addr_is_addr_wildcard (const sock_addr *saddr)
38 switch (saddr->plain.sa_family) {
39 case AF_INET:
40 return (saddr->ipv4.sin_addr.s_addr == INADDR_ANY); /*(htonl(0x0))*/
41 #ifdef HAVE_IPV6
42 case AF_INET6:
43 return !memcmp(&saddr->ipv6.sin6_addr,&in6addr_any,sizeof(in6addr_any));
44 #endif
45 #ifdef HAVE_SYS_UN_H
46 /*case AF_UNIX:*/
47 #endif
48 default:
49 return 0;
54 int sock_addr_is_family_eq (const sock_addr *saddr1, const sock_addr *saddr2)
56 return saddr1->plain.sa_family == saddr2->plain.sa_family;
60 int sock_addr_is_port_eq (const sock_addr *saddr1, const sock_addr *saddr2)
62 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0;
63 switch (saddr1->plain.sa_family) {
64 case AF_INET:
65 return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port;
66 #ifdef HAVE_IPV6
67 case AF_INET6:
68 return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port;
69 #endif
70 #ifdef HAVE_SYS_UN_H
71 case AF_UNIX:
72 return 1;
73 #endif
74 default:
75 return 0;
80 int sock_addr_is_addr_eq (const sock_addr *saddr1, const sock_addr *saddr2)
82 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0;
83 switch (saddr1->plain.sa_family) {
84 case AF_INET:
85 return saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr;
86 #ifdef HAVE_IPV6
87 case AF_INET6:
88 return 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr,
89 sizeof(struct in6_addr));
90 #endif
91 #ifdef HAVE_SYS_UN_H
92 case AF_UNIX:
93 return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path);
94 #endif
95 default:
96 return 0;
101 #if 0
102 int sock_addr_is_addr_port_eq (const sock_addr *saddr1, const sock_addr *saddr2)
104 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0;
105 switch (saddr1->plain.sa_family) {
106 case AF_INET:
107 return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port
108 && saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr;
109 #ifdef HAVE_IPV6
110 case AF_INET6:
111 return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port
112 && 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr,
113 sizeof(struct in6_addr));
114 #endif
115 #ifdef HAVE_SYS_UN_H
116 case AF_UNIX:
117 return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path);
118 #endif
119 default:
120 return 0;
123 #endif
126 int sock_addr_is_addr_eq_bits(const sock_addr *a, const sock_addr *b, int bits) {
127 switch (a->plain.sa_family) {
128 case AF_INET:
130 uint32_t nm; /* build netmask */
131 if (bits > 32) bits = 32;
132 nm = htonl(~((1u << (32 - (0 != bits ? bits : 32))) - 1));
133 if (b->plain.sa_family == AF_INET) {
134 return
135 (a->ipv4.sin_addr.s_addr & nm) == (b->ipv4.sin_addr.s_addr & nm);
137 #ifdef HAVE_IPV6
138 else if (b->plain.sa_family == AF_INET6
139 && IN6_IS_ADDR_V4MAPPED(&b->ipv6.sin6_addr)) {
140 #ifdef s6_addr32
141 in_addr_t x = b->ipv6.sin6_addr.s6_addr32[3];
142 #else
143 in_addr_t x;
144 memcpy(&x, b->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t));
145 #endif
146 return ((a->ipv4.sin_addr.s_addr & nm) == (x & nm));
148 #endif
149 return 0;
151 #ifdef HAVE_IPV6
152 case AF_INET6:
153 if (bits > 128) bits = 128;
154 if (b->plain.sa_family == AF_INET6) {
155 uint8_t *c = (uint8_t *)&a->ipv6.sin6_addr.s6_addr[0];
156 uint8_t *d = (uint8_t *)&b->ipv6.sin6_addr.s6_addr[0];
157 int match;
158 do {
159 match = (bits >= 8)
160 ? *c++ == *d++
161 : (*c >> (8 - bits)) == (*d >> (8 - bits));
162 } while (match && (bits -= 8) > 0);
163 return match;
165 else if (b->plain.sa_family == AF_INET
166 && IN6_IS_ADDR_V4MAPPED(&a->ipv6.sin6_addr)) {
167 uint32_t nm = bits < 128
168 ? htonl(~(~0u >> (bits > 96 ? bits - 96 : 0)))
169 : ~0u;
170 #ifdef s6_addr32
171 in_addr_t x = a->ipv6.sin6_addr.s6_addr32[3];
172 #else
173 in_addr_t x;
174 memcpy(&x, a->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t));
175 #endif
176 return ((x & nm) == (b->ipv4.sin_addr.s_addr & nm));
178 return 0;
179 #endif
180 #ifdef HAVE_SYS_UN_H
181 /*case AF_UNIX:*/
182 #endif
183 default:
184 return 0;
189 int sock_addr_assign (sock_addr *saddr, int family, unsigned short nport, const void *naddr)
191 switch (family) {
192 case AF_INET:
193 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in));
194 saddr->ipv4.sin_family = AF_INET;
195 saddr->ipv4.sin_port = nport;
196 memcpy(&saddr->ipv4.sin_addr, naddr, 4);
197 return 0;
198 #ifdef HAVE_IPV6
199 case AF_INET6:
200 memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6));
201 saddr->ipv6.sin6_family = AF_INET6;
202 saddr->ipv6.sin6_port = nport;
203 memcpy(&saddr->ipv6.sin6_addr, naddr, 16);
204 return 0;
205 #endif
206 #ifdef HAVE_SYS_UN_H
207 case AF_UNIX:
209 size_t len = strlen((char *)naddr) + 1;
210 if (len > sizeof(saddr->un.sun_path)) {
211 errno = ENAMETOOLONG;
212 return -1;
214 memset(&saddr->un, 0, sizeof(struct sockaddr_un));
215 saddr->un.sun_family = AF_UNIX;
216 memcpy(saddr->un.sun_path, naddr, len);
217 return 0;
219 #endif
220 default:
221 errno = EAFNOSUPPORT;
222 return -1;
227 int sock_addr_inet_pton(sock_addr *saddr, const char *str,
228 int family, unsigned short port)
230 switch (family) {
231 case AF_INET:
232 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in));
233 saddr->ipv4.sin_family = AF_INET;
234 saddr->ipv4.sin_port = htons(port);
235 #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/
236 return (0 != inet_aton(str, &saddr->ipv4.sin_addr));
237 #else
238 return ((saddr->ipv4.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE);
239 #endif
240 #ifdef HAVE_IPV6
241 case AF_INET6:
242 memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6));
243 saddr->ipv6.sin6_family = AF_INET6;
244 saddr->ipv6.sin6_port = htons(port);
245 return inet_pton(AF_INET6, str, &saddr->ipv6.sin6_addr);
246 #endif
247 default:
248 errno = EAFNOSUPPORT;
249 return -1;
254 const char * sock_addr_inet_ntop(const sock_addr *saddr, char *buf, socklen_t sz)
256 switch (saddr->plain.sa_family) {
257 case AF_INET:
258 #if defined(HAVE_INET_PTON) /*(expect inet_ntop if inet_pton)*/
259 return inet_ntop(AF_INET,(const void *)&saddr->ipv4.sin_addr,buf,sz);
260 #else /*(inet_ntoa() not thread-safe)*/
261 return inet_ntoa(saddr->ipv4.sin_addr);
262 #endif
263 #ifdef HAVE_IPV6
264 case AF_INET6:
265 return inet_ntop(AF_INET6,(const void *)&saddr->ipv6.sin6_addr,buf,sz);
266 #endif
267 #ifdef HAVE_SYS_UN_H
268 case AF_UNIX:
269 return saddr->un.sun_path;
270 #endif
271 default:
272 errno = EAFNOSUPPORT;
273 return NULL;
278 int sock_addr_inet_ntop_copy_buffer(buffer *b, const sock_addr *saddr)
280 /*(incur cost of extra copy to avoid potential extra memory allocation)*/
281 char buf[UNIX_PATH_MAX];
282 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf));
283 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/
284 buffer_copy_string(b, s);
285 return 0;
289 int sock_addr_inet_ntop_append_buffer(buffer *b, const sock_addr *saddr)
291 /*(incur cost of extra copy to avoid potential extra memory allocation)*/
292 char buf[UNIX_PATH_MAX];
293 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf));
294 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/
295 buffer_append_string(b, s);
296 return 0;
299 int sock_addr_stringify_append_buffer(buffer *b, const sock_addr *saddr)
301 switch (saddr->plain.sa_family) {
302 case AF_INET:
303 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) return -1;
304 buffer_append_string_len(b, CONST_STR_LEN(":"));
305 buffer_append_int(b, ntohs(saddr->ipv4.sin_port));
306 return 0;
307 #ifdef HAVE_IPV6
308 case AF_INET6:
309 buffer_append_string_len(b, CONST_STR_LEN("["));
310 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) {
311 buffer_string_set_length(b, buffer_string_length(b)-1);
312 return -1;
314 buffer_append_string_len(b, CONST_STR_LEN("]"));
315 buffer_append_string_len(b, CONST_STR_LEN(":"));
316 buffer_append_int(b, ntohs(saddr->ipv6.sin6_port));
317 return 0;
318 #endif
319 #ifdef HAVE_SYS_UN_H
320 case AF_UNIX:
321 buffer_append_string(b, saddr->un.sun_path);
322 return 0;
323 #endif
324 default:
325 return 0;
330 int sock_addr_nameinfo_append_buffer(server *srv, buffer *b, const sock_addr *saddr)
332 /*(this routine originates from
333 * http-header-glue.c:http_response_redirect_to_directory())*/
334 /*(note: name resolution here is *blocking*)*/
335 switch (saddr->plain.sa_family) {
336 case AF_INET:
338 struct hostent *he = gethostbyaddr((char *)&saddr->ipv4.sin_addr,
339 sizeof(struct in_addr), AF_INET);
340 if (NULL == he) {
341 log_error_write(srv, __FILE__, __LINE__,
342 "SdS", "NOTICE: gethostbyaddr failed: ",
343 h_errno, ", using ip-address instead");
345 sock_addr_inet_ntop_append_buffer(b, saddr);
346 } else {
347 buffer_append_string(b, he->h_name);
349 return 0;
351 #ifdef HAVE_IPV6
352 case AF_INET6:
354 char hbuf[256];
355 if (0 != getnameinfo((const struct sockaddr *)(&saddr->ipv6),
356 sizeof(saddr->ipv6),
357 hbuf, sizeof(hbuf), NULL, 0, 0)) {
358 log_error_write(srv, __FILE__, __LINE__,
359 "SSS", "NOTICE: getnameinfo failed: ",
360 strerror(errno), ", using ip-address instead");
362 buffer_append_string_len(b, CONST_STR_LEN("["));
363 sock_addr_inet_ntop_append_buffer(b, saddr);
364 buffer_append_string_len(b, CONST_STR_LEN("]"));
365 } else {
366 buffer_append_string(b, hbuf);
368 return 0;
370 #endif
371 default:
372 log_error_write(srv, __FILE__, __LINE__,
373 "S", "ERROR: unsupported address-type");
374 return -1;
379 int sock_addr_from_str_hints(server *srv, sock_addr *saddr, socklen_t *len, const char *str, int family, unsigned short port)
381 /*(note: name resolution here is *blocking*)*/
382 switch(family) {
383 case AF_UNSPEC:
384 if (0 == strcmp(str, "localhost")) {
385 /*(special-case "localhost" to IPv4 127.0.0.1)*/
386 memset(saddr, 0, sizeof(struct sockaddr_in));
387 saddr->ipv4.sin_family = AF_INET;
388 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
389 saddr->ipv4.sin_port = htons(port);
390 *len = sizeof(struct sockaddr_in);
391 return 1;
393 #ifdef HAVE_IPV6
394 else {
395 struct addrinfo hints, *res;
396 int r;
397 memset(&hints, 0, sizeof(hints));
398 hints.ai_family = AF_UNSPEC;
399 hints.ai_socktype = SOCK_STREAM;
400 hints.ai_protocol = IPPROTO_TCP;
402 if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) {
403 log_error_write(srv, __FILE__, __LINE__,
404 "sssss", "getaddrinfo failed: ",
405 gai_strerror(r), "'", str, "'");
406 return 0;
409 memcpy(saddr, res->ai_addr, res->ai_addrlen);
410 freeaddrinfo(res);
411 if (AF_INET6 == saddr->plain.sa_family) {
412 saddr->ipv6.sin6_port = htons(port);
413 *len = sizeof(struct sockaddr_in6);
415 else { /* AF_INET */
416 saddr->ipv4.sin_port = htons(port);
417 *len = sizeof(struct sockaddr_in);
419 return 1;
421 #else
422 /* fall through */
423 #endif
424 #ifdef HAVE_IPV6
425 case AF_INET6:
426 memset(saddr, 0, sizeof(struct sockaddr_in6));
427 saddr->ipv6.sin6_family = AF_INET6;
428 if (0 == strcmp(str, "::")) {
429 saddr->ipv6.sin6_addr = in6addr_any;
431 else if (0 == strcmp(str, "::1")) {
432 saddr->ipv6.sin6_addr = in6addr_loopback;
434 else {
435 struct addrinfo hints, *res;
436 int r;
438 memset(&hints, 0, sizeof(hints));
440 hints.ai_family = AF_INET6;
441 hints.ai_socktype = SOCK_STREAM;
442 hints.ai_protocol = IPPROTO_TCP;
444 if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) {
445 hints.ai_family = AF_INET;
446 if (
447 #ifdef EAI_ADDRFAMILY
448 EAI_ADDRFAMILY == r &&
449 #endif
450 0 == getaddrinfo(str, NULL, &hints, &res)) {
451 memcpy(saddr, res->ai_addr, res->ai_addrlen);
452 saddr->ipv4.sin_family = AF_INET;
453 saddr->ipv4.sin_port = htons(port);
454 *len = sizeof(struct sockaddr_in);
455 /*assert(*len == res->ai_addrlen);*/
456 freeaddrinfo(res);
457 return 1;
460 log_error_write(srv, __FILE__, __LINE__,
461 "sssss", "getaddrinfo failed: ",
462 gai_strerror(r), "'", str, "'");
464 return 0;
467 memcpy(saddr, res->ai_addr, res->ai_addrlen);
468 freeaddrinfo(res);
470 saddr->ipv6.sin6_port = htons(port);
471 *len = sizeof(struct sockaddr_in6);
472 return 1;
473 #endif
474 case AF_INET:
475 memset(saddr, 0, sizeof(struct sockaddr_in));
476 saddr->ipv4.sin_family = AF_INET;
477 if (0 == strcmp(str, "0.0.0.0")) {
478 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
480 else if (0 == strcmp(str, "127.0.0.1")) {
481 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
483 else {
484 #ifdef HAVE_INET_PTON
485 /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/
486 struct addrinfo hints, *res;
487 int r;
488 memset(&hints, 0, sizeof(hints));
489 hints.ai_family = AF_INET;
490 hints.ai_socktype = SOCK_STREAM;
491 hints.ai_protocol = IPPROTO_TCP;
493 if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) {
494 log_error_write(srv, __FILE__, __LINE__,
495 "sssss", "getaddrinfo failed: ",
496 gai_strerror(r), "'", str, "'");
497 return 0;
500 memcpy(saddr, res->ai_addr, res->ai_addrlen);
501 freeaddrinfo(res);
502 #else
503 struct hostent *he = gethostbyname(str);
504 if (NULL == he) {
505 log_error_write(srv, __FILE__, __LINE__, "sds",
506 "gethostbyname failed:", h_errno, str);
507 return 0;
510 if (he->h_addrtype != AF_INET) {
511 log_error_write(srv, __FILE__, __LINE__, "sd",
512 "addr-type != AF_INET:", he->h_addrtype);
513 return 0;
516 if (he->h_length != sizeof(struct in_addr)) {
517 log_error_write(srv, __FILE__, __LINE__, "sd",
518 "addr-length != sizeof(in_addr):",he->h_length);
519 return 0;
522 memcpy(&saddr->ipv4.sin_addr.s_addr,
523 he->h_addr_list[0], he->h_length);
524 #endif
526 saddr->ipv4.sin_port = htons(port);
527 *len = sizeof(struct sockaddr_in);
528 return 1;
529 #ifdef HAVE_SYS_UN_H
530 case AF_UNIX:
531 memset(saddr, 0, sizeof(struct sockaddr_un));
532 saddr->un.sun_family = AF_UNIX;
534 size_t hostlen = strlen(str) + 1;
535 if (hostlen > sizeof(saddr->un.sun_path)) {
536 log_error_write(srv, __FILE__, __LINE__, "sS",
537 "unix socket filename too long:", str);
538 /*errno = ENAMETOOLONG;*/
539 return 0;
541 memcpy(saddr->un.sun_path, str, hostlen);
542 #if defined(SUN_LEN)
543 *len = SUN_LEN(&saddr->un);
544 #else
545 /* stevens says: */
546 *len = hostlen + sizeof(saddr->un.sun_family);
547 #endif
549 return 1;
550 #else
551 case AF_UNIX:
552 log_error_write(srv, __FILE__, __LINE__, "s",
553 "unix domain sockets are not supported.");
554 return 0;
555 #endif
556 default:
557 log_error_write(srv, __FILE__, __LINE__, "sd",
558 "address family unsupported:", family);
559 /*errno = EAFNOSUPPORT;*/
560 return 0;
565 int sock_addr_from_str_numeric(server *srv, sock_addr *saddr, const char *str)
567 /*(note: does not handle port if getaddrinfo() is not available)*/
568 /*(note: getaddrinfo() is stricter than inet_aton() in what is accepted)*/
569 /*(this routine originates from mod_extforward.c:ipstr_to_sockaddr()*/
570 #ifdef HAVE_IPV6
571 struct addrinfo hints, *addrlist = NULL;
572 int result;
575 * quoting $ man getaddrinfo
577 * NOTES
578 * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3.
579 * AI_NUMERICSERV is available since glibc 2.3.4.
581 #ifndef AI_NUMERICSERV
582 #define AI_NUMERICSERV 0
583 #endif
584 memset(&hints, 0, sizeof(hints));
585 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
587 errno = 0;
588 result = getaddrinfo(str, NULL, &hints, &addrlist);
590 if (result != 0) {
591 log_error_write(srv, __FILE__, __LINE__, "SSSs(S)",
592 "could not parse ip address ", str, " because ",
593 gai_strerror(result), strerror(errno));
594 } else if (addrlist == NULL) {
595 log_error_write(srv, __FILE__, __LINE__, "SSS",
596 "Problem in parsing ip address ", str,
597 ": succeeded, but no information returned");
598 result = -1;
599 } else switch (addrlist->ai_family) {
600 case AF_INET:
601 memcpy(&saddr->ipv4, addrlist->ai_addr, sizeof(saddr->ipv4));
602 force_assert(AF_INET == saddr->plain.sa_family);
603 break;
604 case AF_INET6:
605 memcpy(&saddr->ipv6, addrlist->ai_addr, sizeof(saddr->ipv6));
606 force_assert(AF_INET6 == saddr->plain.sa_family);
607 break;
608 default:
609 log_error_write(srv, __FILE__, __LINE__, "SSS",
610 "Problem in parsing ip address ", str,
611 ": succeeded, but unknown family");
612 result = -1;
613 break;
616 freeaddrinfo(addrlist);
617 return (0 == result);
618 #else
619 UNUSED(srv);
620 saddr->ipv4.sin_addr.s_addr = inet_addr(str);
621 saddr->plain.sa_family = AF_INET;
622 return (saddr->ipv4.sin_addr.s_addr != 0xFFFFFFFF);
623 #endif
627 int sock_addr_from_buffer_hints_numeric(server *srv, sock_addr *saddr, socklen_t *len, const buffer *b, int family, unsigned short port)
629 /*(this routine originates from mod_fastcgi.c and mod_scgi.c)*/
630 if (buffer_string_is_empty(b)) {
631 /*(preserve existing behavior (for now))*/
632 /*(would be better if initialized default when reading config)*/
633 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in));
634 saddr->ipv4.sin_family = AF_INET;
635 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
636 saddr->ipv4.sin_port = htons(port);
637 *len = sizeof(struct sockaddr_in);
638 return 1;
640 else if (1 == sock_addr_inet_pton(saddr, b->ptr, family, port)) {
641 *len = (family == AF_INET)
642 ? sizeof(struct sockaddr_in) /* family == AF_INET */
643 : sizeof(struct sockaddr_in6); /* family == AF_INET6 */
644 return 1;
646 #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
647 else if (family == AF_INET6) {
648 log_error_write(srv, __FILE__, __LINE__, "sb",
649 "invalid IPv6 address literal:", b);
650 return 0;
652 #endif
653 #ifndef HAVE_INET_PTON /*(preserve existing behavior (for now))*/
654 else {
655 struct hostent *he = gethostbyname(b->ptr);
656 if (NULL == he) {
657 log_error_write(srv, __FILE__, __LINE__, "sdb",
658 "gethostbyname failed:", h_errno, b);
659 return 0;
662 if (he->h_addrtype != AF_INET) {
663 log_error_write(srv, __FILE__, __LINE__, "sd",
664 "addr-type != AF_INET:", he->h_addrtype);
665 return 0;
668 if (he->h_length != sizeof(struct in_addr)) {
669 log_error_write(srv, __FILE__, __LINE__, "sd",
670 "addr-length != sizeof(in_addr):",he->h_length);
671 return 0;
674 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in));
675 memcpy(&saddr->ipv4.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
676 saddr->ipv4.sin_family = AF_INET;
677 saddr->ipv4.sin_port = htons(port);
678 *len = sizeof(struct sockaddr_in);
680 #else
681 UNUSED(srv);
682 #endif
684 return 0;