mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-22 07:07:08 +00:00
019816dcf1
slumber list. git-svn-id: file:///svn/unbound/trunk@374 be551aaa-1e26-0410-a405-d3ace91eadb9
246 lines
7.2 KiB
C
246 lines
7.2 KiB
C
/*
|
|
* util/net_help.c - implementation of the network helper code
|
|
*
|
|
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
|
*
|
|
* This software is open source.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* Neither the name of the NLNET LABS nor the names of its contributors may
|
|
* be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/**
|
|
* \file
|
|
* Implementation of net_help.h.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "util/net_help.h"
|
|
#include "util/log.h"
|
|
#include "util/data/dname.h"
|
|
#include <fcntl.h>
|
|
|
|
/** returns true is string addr is an ip6 specced address. */
|
|
int
|
|
str_is_ip6(const char* str)
|
|
{
|
|
if(strchr(str, ':'))
|
|
return 1;
|
|
else return 0;
|
|
}
|
|
|
|
int
|
|
write_socket(int s, const void *buf, size_t size)
|
|
{
|
|
const char* data = (const char*)buf;
|
|
size_t total_count = 0;
|
|
|
|
while (total_count < size) {
|
|
ssize_t count
|
|
= write(s, data + total_count, size - total_count);
|
|
if (count == -1) {
|
|
if (errno != EAGAIN && errno != EINTR) {
|
|
return 0;
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
total_count += count;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
fd_set_nonblock(int s)
|
|
{
|
|
int flag;
|
|
if((flag = fcntl(s, F_GETFL)) == -1) {
|
|
log_err("can't fcntl F_GETFL: %s", strerror(errno));
|
|
flag = 0;
|
|
}
|
|
flag |= O_NONBLOCK;
|
|
if(fcntl(s, F_SETFL, flag) == -1) {
|
|
log_err("can't fcntl F_SETFL: %s", strerror(errno));
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
is_pow2(size_t num)
|
|
{
|
|
if(num == 0) return 1;
|
|
return (num & (num-1)) == 0;
|
|
}
|
|
|
|
void
|
|
write_iov_buffer(ldns_buffer* buffer, struct iovec* iov, size_t iovlen)
|
|
{
|
|
size_t i;
|
|
size_t s = 0;
|
|
ldns_buffer_clear(buffer);
|
|
for(i=0; i<iovlen; i++) {
|
|
log_assert(ldns_buffer_position(buffer)+iov[i].iov_len
|
|
<= ldns_buffer_capacity(buffer));
|
|
s += iov[i].iov_len;
|
|
ldns_buffer_write(buffer, iov[i].iov_base, iov[i].iov_len);
|
|
}
|
|
ldns_buffer_flip(buffer);
|
|
}
|
|
|
|
void*
|
|
memdup(void* data, size_t len)
|
|
{
|
|
void* d;
|
|
if(!data) return NULL;
|
|
if(len == 0) return NULL;
|
|
d = malloc(len);
|
|
if(!d) return NULL;
|
|
memcpy(d, data, len);
|
|
return d;
|
|
}
|
|
|
|
void
|
|
log_addr(const char* str, struct sockaddr_storage* addr, socklen_t addrlen)
|
|
{
|
|
uint16_t port;
|
|
const char* family = "unknown";
|
|
char dest[100];
|
|
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
|
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
|
switch(af) {
|
|
case AF_INET: family="ip4"; break;
|
|
case AF_INET6: family="ip6";
|
|
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
|
break;
|
|
case AF_UNIX: family="unix"; break;
|
|
default: break;
|
|
}
|
|
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
|
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
|
}
|
|
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
|
verbose(VERB_DETAIL, "%s %s %s %d (len %d)",
|
|
str, family, dest, (int)port, (int)addrlen);
|
|
}
|
|
|
|
int
|
|
ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
|
|
socklen_t* addrlen)
|
|
{
|
|
uint16_t p;
|
|
if(!ip) return 0;
|
|
p = (uint16_t) port;
|
|
if(str_is_ip6(ip)) {
|
|
struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
|
|
*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
|
|
memset(sa, 0, *addrlen);
|
|
sa->sin6_family = AF_INET6;
|
|
sa->sin6_port = (in_port_t)htons(p);
|
|
if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
|
|
log_err("Bad ip6 address %s", ip);
|
|
return 0;
|
|
}
|
|
} else { /* ip4 */
|
|
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
|
|
*addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
|
memset(sa, 0, *addrlen);
|
|
sa->sin_family = AF_INET;
|
|
sa->sin_port = (in_port_t)htons(p);
|
|
if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
|
|
log_err("Bad ip4 address %s", ip);
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
|
|
uint16_t type, uint16_t dclass)
|
|
{
|
|
char buf[LDNS_MAX_DOMAINLEN+1];
|
|
char t[12], c[12];
|
|
const char *ts, *cs;
|
|
if(verbosity < v)
|
|
return;
|
|
dname_str(name, buf);
|
|
if(ldns_rr_descript(type) && ldns_rr_descript(type)->_name)
|
|
ts = ldns_rr_descript(type)->_name;
|
|
else {
|
|
snprintf(t, 12, "TYPE%d", (int)type);
|
|
ts = t;
|
|
}
|
|
if(ldns_lookup_by_id(ldns_rr_classes, (int)dclass) &&
|
|
ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name)
|
|
cs = ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name;
|
|
else {
|
|
snprintf(c, 12, "CLASS%d", (int)dclass);
|
|
cs = c;
|
|
}
|
|
log_info("%s <%s %s %s>", str, buf, ts, cs);
|
|
}
|
|
|
|
void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
|
|
struct sockaddr_storage* addr, socklen_t addrlen)
|
|
{
|
|
uint16_t port;
|
|
const char* family = "unknown_family ";
|
|
char namebuf[LDNS_MAX_DOMAINLEN+1];
|
|
char dest[100];
|
|
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
|
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
|
if(verbosity < v)
|
|
return;
|
|
switch(af) {
|
|
case AF_INET: family=""; break;
|
|
case AF_INET6: family="";
|
|
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
|
break;
|
|
case AF_UNIX: family="unix_family "; break;
|
|
default: break;
|
|
}
|
|
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
|
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
|
}
|
|
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
|
dname_str(zone, namebuf);
|
|
if(af != AF_INET && af != AF_INET6)
|
|
verbose(VERB_DETAIL, "%s <%s> %s%s#%d (addrlen %d)",
|
|
str, namebuf, family, dest, (int)port, (int)addrlen);
|
|
else verbose(VERB_DETAIL, "%s <%s> %s%s#%d",
|
|
str, namebuf, family, dest, (int)port);
|
|
}
|
|
|
|
int
|
|
addr_is_ip6(struct sockaddr_storage* addr)
|
|
{
|
|
short family = *(short*)addr;
|
|
if(family == AF_INET6)
|
|
return 1;
|
|
else return 0;
|
|
}
|