f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2000, 2001 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Permission to use, copy, modify, and distribute this software for any
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * purpose with or without fee is hereby granted, provided that the above
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * copyright notice and this permission notice appear in all copies.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2004 - 2015 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Permission to use, copy, modify, and distribute this software and its
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * documentation for any purpose with or without fee is hereby granted,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * provided that the above copyright notice and this permission notice
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * appear in all copies.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <errno.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <fcntl.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdio.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdlib.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <string.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/result.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/sockaddr.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <bind9/getaddresses.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "log.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "net.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "opt.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntint
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntperf_net_parsefamily(const char *family)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (family == NULL || strcmp(family, "any") == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return AF_UNSPEC;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else if (strcmp(family, "inet") == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return AF_INET;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#ifdef AF_INET6
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else if (strcmp(family, "inet6") == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return AF_INET6;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#endif
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(stderr, "invalid family %s\n", family);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_usage();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt exit(1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntvoid
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntperf_net_parseserver(int family, const char *name, unsigned int port,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t *addr)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t addrs[8];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int count, i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (port == 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(stderr, "server port cannot be 0\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_usage();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt exit(1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt count = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = bind9_getaddresses(name, port, addrs, 8, &count);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result == ISC_R_SUCCESS) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < count; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (isc_sockaddr_pf(&addrs[i]) == family ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt family == AF_UNSPEC)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *addr = addrs[i];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(stderr, "invalid server address %s\n", name);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_usage();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt exit(1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntvoid
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntperf_net_parselocal(int family, const char *name, unsigned int port,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t *addr)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt struct in_addr in4a;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt struct in6_addr in6a;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (name == NULL) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_anyofpf(addr, family);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_setport(addr, port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else if (inet_pton(AF_INET, name, &in4a) == 1) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_fromin(addr, &in4a, port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else if (inet_pton(AF_INET6, name, &in6a) == 1) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_fromin6(addr, &in6a, port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(stderr, "invalid local address %s\n", name);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_usage();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt exit(1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntint
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntperf_net_opensocket(const isc_sockaddr_t *server, const isc_sockaddr_t *local,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int offset, int bufsize)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int family;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t tmp;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int port;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int ret;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int flags;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt family = isc_sockaddr_pf(server);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (isc_sockaddr_pf(local) != family)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("server and local addresses have "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "different families");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sock = socket(family, SOCK_DGRAM, 0);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (sock == -1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("Error: socket: %s\n", strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#if defined(AF_INET6) && defined(IPV6_V6ONLY)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (family == AF_INET6) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int on = 1;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &on, sizeof(on)) == -1) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("setsockopt(IPV6_V6ONLY) failed");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#endif
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tmp = *local;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt port = isc_sockaddr_getport(&tmp);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (port != 0 && offset != 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt port += offset;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (port >= 0xFFFF)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("port %d out of range", port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_setport(&tmp, port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (bind(sock, &tmp.type.sa, tmp.length) == -1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("bind: %s\n", strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (bufsize > 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bufsize *= 1024;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &bufsize, sizeof(bufsize));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (ret < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("setsockbuf(SO_RCVBUF) failed");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &bufsize, sizeof(bufsize));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (ret < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("setsockbuf(SO_SNDBUF) failed");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt flags = fcntl(sock, F_GETFL, 0);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (flags < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("fcntl(F_GETFL)");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ret = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (ret < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("fcntl(F_SETFL)");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}