t_rfc6056.c revision 1.3 1 1.3 christos /* $NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $ */
2 1.1 christos
3 1.2 jruoho /*-
4 1.2 jruoho * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 1.2 jruoho * All rights reserved.
6 1.2 jruoho *
7 1.2 jruoho * This code is derived from software contributed to The NetBSD Foundation
8 1.2 jruoho * by Christos Zoulas.
9 1.2 jruoho *
10 1.2 jruoho * Redistribution and use in source and binary forms, with or without
11 1.2 jruoho * modification, are permitted provided that the following conditions
12 1.2 jruoho * are met:
13 1.2 jruoho * 1. Redistributions of source code must retain the above copyright
14 1.2 jruoho * notice, this list of conditions and the following disclaimer.
15 1.2 jruoho * 2. Redistributions in binary form must reproduce the above copyright
16 1.2 jruoho * notice, this list of conditions and the following disclaimer in the
17 1.2 jruoho * documentation and/or other materials provided with the distribution.
18 1.2 jruoho *
19 1.2 jruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.2 jruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.2 jruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.2 jruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.2 jruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.2 jruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.2 jruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.2 jruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.2 jruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.2 jruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.2 jruoho * POSSIBILITY OF SUCH DAMAGE.
30 1.2 jruoho */
31 1.1 christos #include <sys/cdefs.h>
32 1.3 christos __RCSID("$NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $");
33 1.1 christos
34 1.1 christos #include <sys/types.h>
35 1.1 christos #include <sys/socket.h>
36 1.1 christos #include <netinet/in.h>
37 1.1 christos #include <netinet/udp.h>
38 1.1 christos #include <arpa/inet.h>
39 1.1 christos #include <string.h>
40 1.1 christos #include <strings.h>
41 1.1 christos #include <stdio.h>
42 1.1 christos #include <unistd.h>
43 1.1 christos #include <errno.h>
44 1.1 christos #include <stdlib.h>
45 1.1 christos #include <netdb.h>
46 1.1 christos #include <err.h>
47 1.1 christos
48 1.1 christos #include <atf-c.h>
49 1.1 christos
50 1.1 christos static void
51 1.1 christos test(const char *hostname, const char *service, int family, int al)
52 1.1 christos {
53 1.1 christos static const char hello[] = "hello\n";
54 1.3 christos int s, error, proto, option;
55 1.1 christos struct sockaddr_storage ss;
56 1.1 christos struct addrinfo hints, *res;
57 1.1 christos
58 1.1 christos memset(&hints, 0, sizeof(hints));
59 1.1 christos hints.ai_family = family;
60 1.1 christos hints.ai_socktype = SOCK_DGRAM;
61 1.1 christos
62 1.3 christos switch (family) {
63 1.3 christos case AF_INET:
64 1.3 christos proto = IPPROTO_IP;
65 1.3 christos option = IP_PORTALGO;
66 1.3 christos break;
67 1.3 christos case AF_INET6:
68 1.3 christos proto = IPPROTO_IPV6;
69 1.3 christos option = IPV6_PORTALGO;
70 1.3 christos break;
71 1.3 christos default:
72 1.3 christos abort();
73 1.3 christos }
74 1.3 christos
75 1.1 christos error = getaddrinfo(hostname, service, &hints, &res);
76 1.1 christos if (error)
77 1.1 christos errx(EXIT_FAILURE, "Cannot get address for %s (%s)",
78 1.1 christos hostname, gai_strerror(error));
79 1.1 christos
80 1.1 christos s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
81 1.1 christos if (s == -1)
82 1.1 christos err(EXIT_FAILURE, "socket");
83 1.1 christos
84 1.3 christos if (setsockopt(s, proto, option, &al, sizeof(al)) == -1)
85 1.1 christos err(EXIT_FAILURE, "setsockopt");
86 1.1 christos
87 1.1 christos memset(&ss, 0, sizeof(ss));
88 1.1 christos ss.ss_len = res->ai_addrlen;
89 1.1 christos ss.ss_family = res->ai_family;
90 1.1 christos
91 1.1 christos if (bind(s, (struct sockaddr *)&ss, ss.ss_len) == -1)
92 1.1 christos err(EXIT_FAILURE, "bind");
93 1.1 christos
94 1.1 christos if (sendto(s, hello, sizeof(hello) - 1, 0,
95 1.1 christos res->ai_addr, res->ai_addrlen) == -1)
96 1.1 christos err(EXIT_FAILURE, "sendto");
97 1.1 christos
98 1.1 christos if (close(s) == -1)
99 1.1 christos err(EXIT_FAILURE, "close");
100 1.1 christos
101 1.1 christos s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
102 1.1 christos if (s == -1)
103 1.1 christos err(EXIT_FAILURE, "socket");
104 1.1 christos
105 1.3 christos if (setsockopt(s, proto, option, &al, sizeof(al)) == -1)
106 1.1 christos err(EXIT_FAILURE, "setsockopt");
107 1.1 christos
108 1.1 christos if (connect(s, res->ai_addr, res->ai_addrlen) == -1)
109 1.1 christos err(EXIT_FAILURE, "connect");
110 1.1 christos
111 1.1 christos if (send(s, hello, sizeof(hello) - 1, 0) == -1)
112 1.1 christos err(EXIT_FAILURE, "send");
113 1.1 christos
114 1.1 christos if (close(s) == -1)
115 1.1 christos err(EXIT_FAILURE, "close");
116 1.1 christos
117 1.1 christos freeaddrinfo(res);
118 1.1 christos }
119 1.1 christos
120 1.1 christos ATF_TC(inet4);
121 1.1 christos ATF_TC_HEAD(inet4, tc)
122 1.1 christos {
123 1.1 christos atf_tc_set_md_var(tc, "descr", "Checks random port allocation "
124 1.1 christos "for ipv4");
125 1.1 christos }
126 1.1 christos
127 1.1 christos ATF_TC_BODY(inet4, tc)
128 1.1 christos {
129 1.1 christos for (int i = 0; i < 6; i++)
130 1.1 christos test("localhost", "http", AF_INET, i);
131 1.1 christos }
132 1.1 christos
133 1.1 christos ATF_TC(inet6);
134 1.1 christos ATF_TC_HEAD(inet6, tc)
135 1.1 christos {
136 1.1 christos atf_tc_set_md_var(tc, "descr", "Checks random port allocation "
137 1.1 christos "for ipv6");
138 1.1 christos }
139 1.1 christos
140 1.1 christos ATF_TC_BODY(inet6, tc)
141 1.1 christos {
142 1.1 christos for (int i = 0; i < 6; i++)
143 1.1 christos test("localhost", "http", AF_INET6, i);
144 1.1 christos }
145 1.1 christos
146 1.1 christos ATF_TP_ADD_TCS(tp)
147 1.1 christos {
148 1.1 christos ATF_TP_ADD_TC(tp, inet4);
149 1.1 christos ATF_TP_ADD_TC(tp, inet6);
150 1.1 christos
151 1.1 christos return atf_no_error();
152 1.1 christos }
153