1272343Sngie/* $NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Christos Zoulas. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie#include <sys/cdefs.h> 32272343Sngie__RCSID("$NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $"); 33272343Sngie 34272343Sngie#include <sys/types.h> 35272343Sngie#include <sys/socket.h> 36272343Sngie#include <netinet/in.h> 37272343Sngie#include <netinet/udp.h> 38272343Sngie#include <arpa/inet.h> 39272343Sngie#include <string.h> 40272343Sngie#include <strings.h> 41272343Sngie#include <stdio.h> 42272343Sngie#include <unistd.h> 43272343Sngie#include <errno.h> 44272343Sngie#include <stdlib.h> 45272343Sngie#include <netdb.h> 46272343Sngie#include <err.h> 47272343Sngie 48272343Sngie#include <atf-c.h> 49272343Sngie 50272343Sngiestatic void 51272343Sngietest(const char *hostname, const char *service, int family, int al) 52272343Sngie{ 53272343Sngie static const char hello[] = "hello\n"; 54272343Sngie int s, error, proto, option; 55272343Sngie struct sockaddr_storage ss; 56272343Sngie struct addrinfo hints, *res; 57272343Sngie 58272343Sngie memset(&hints, 0, sizeof(hints)); 59272343Sngie hints.ai_family = family; 60272343Sngie hints.ai_socktype = SOCK_DGRAM; 61272343Sngie 62272343Sngie switch (family) { 63272343Sngie case AF_INET: 64272343Sngie proto = IPPROTO_IP; 65272343Sngie option = IP_PORTALGO; 66272343Sngie break; 67272343Sngie case AF_INET6: 68272343Sngie proto = IPPROTO_IPV6; 69272343Sngie option = IPV6_PORTALGO; 70272343Sngie break; 71272343Sngie default: 72272343Sngie abort(); 73272343Sngie } 74272343Sngie 75272343Sngie error = getaddrinfo(hostname, service, &hints, &res); 76272343Sngie if (error) 77272343Sngie errx(EXIT_FAILURE, "Cannot get address for %s (%s)", 78272343Sngie hostname, gai_strerror(error)); 79272343Sngie 80272343Sngie s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 81272343Sngie if (s == -1) 82272343Sngie err(EXIT_FAILURE, "socket"); 83272343Sngie 84272343Sngie if (setsockopt(s, proto, option, &al, sizeof(al)) == -1) 85272343Sngie err(EXIT_FAILURE, "setsockopt"); 86272343Sngie 87272343Sngie memset(&ss, 0, sizeof(ss)); 88272343Sngie ss.ss_len = res->ai_addrlen; 89272343Sngie ss.ss_family = res->ai_family; 90272343Sngie 91272343Sngie if (bind(s, (struct sockaddr *)&ss, ss.ss_len) == -1) 92272343Sngie err(EXIT_FAILURE, "bind"); 93272343Sngie 94272343Sngie if (sendto(s, hello, sizeof(hello) - 1, 0, 95272343Sngie res->ai_addr, res->ai_addrlen) == -1) 96272343Sngie err(EXIT_FAILURE, "sendto"); 97272343Sngie 98272343Sngie if (close(s) == -1) 99272343Sngie err(EXIT_FAILURE, "close"); 100272343Sngie 101272343Sngie s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 102272343Sngie if (s == -1) 103272343Sngie err(EXIT_FAILURE, "socket"); 104272343Sngie 105272343Sngie if (setsockopt(s, proto, option, &al, sizeof(al)) == -1) 106272343Sngie err(EXIT_FAILURE, "setsockopt"); 107272343Sngie 108272343Sngie if (connect(s, res->ai_addr, res->ai_addrlen) == -1) 109272343Sngie err(EXIT_FAILURE, "connect"); 110272343Sngie 111272343Sngie if (send(s, hello, sizeof(hello) - 1, 0) == -1) 112272343Sngie err(EXIT_FAILURE, "send"); 113272343Sngie 114272343Sngie if (close(s) == -1) 115272343Sngie err(EXIT_FAILURE, "close"); 116272343Sngie 117272343Sngie freeaddrinfo(res); 118272343Sngie} 119272343Sngie 120272343SngieATF_TC(inet4); 121272343SngieATF_TC_HEAD(inet4, tc) 122272343Sngie{ 123272343Sngie atf_tc_set_md_var(tc, "descr", "Checks random port allocation " 124272343Sngie "for ipv4"); 125272343Sngie} 126272343Sngie 127272343SngieATF_TC_BODY(inet4, tc) 128272343Sngie{ 129272343Sngie for (int i = 0; i < 6; i++) 130272343Sngie test("localhost", "http", AF_INET, i); 131272343Sngie} 132272343Sngie 133272343SngieATF_TC(inet6); 134272343SngieATF_TC_HEAD(inet6, tc) 135272343Sngie{ 136272343Sngie atf_tc_set_md_var(tc, "descr", "Checks random port allocation " 137272343Sngie "for ipv6"); 138272343Sngie} 139272343Sngie 140272343SngieATF_TC_BODY(inet6, tc) 141272343Sngie{ 142272343Sngie for (int i = 0; i < 6; i++) 143272343Sngie test("localhost", "http", AF_INET6, i); 144272343Sngie} 145272343Sngie 146272343SngieATF_TP_ADD_TCS(tp) 147272343Sngie{ 148272343Sngie ATF_TP_ADD_TC(tp, inet4); 149272343Sngie ATF_TP_ADD_TC(tp, inet6); 150272343Sngie 151272343Sngie return atf_no_error(); 152272343Sngie} 153