blob: 8efbadb62b7d9c684cc4727e659995b71c405f08 [file] [log] [blame]
mridge949c5b12006-01-03 23:01:28 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
mridge949c5b12006-01-03 23:01:28 +000018 */
19
20/*
21 * Test Name: asapi_05
22 *
23 * Test Description:
24 * These tests are for the "Advanced Sockets API" (RFC 3542)
25 * Verify that in6 and sockaddr fields are present.
26 *
27 * Usage: <for command-line>
28 * asapi_05
29 *
30 * HISTORY
31 * 04/2005 written by David L Stevens
32 *
33 * RESTRICTIONS:
34 * None.
35 *
36 */
37
38#include <stdio.h>
39#include <unistd.h>
40#include <errno.h>
41
42#include <sys/wait.h>
subrata_modak7fe64512008-12-12 13:41:11 +000043#include <sys/socket.h>
mridge949c5b12006-01-03 23:01:28 +000044
45#include <netinet/in.h>
46#include <netinet/ip6.h>
47#include <netinet/icmp6.h>
48
49#include "test.h"
mridge949c5b12006-01-03 23:01:28 +000050#include "runcc.h"
51
Wanlong Gao354ebb42012-12-07 10:10:04 +080052char *TCID = "asapi_05"; /* Test program identifier. */
mridge949c5b12006-01-03 23:01:28 +000053
Garrett Cooper38097ab2010-12-17 03:23:52 -080054void setup(void);
55void cleanup(void);
mridge949c5b12006-01-03 23:01:28 +000056
Garrett Cooper38097ab2010-12-17 03:23:52 -080057void icmp6_et(void);
58void icmp6_ft(void);
mridge949c5b12006-01-03 23:01:28 +000059
Wanlong Gao354ebb42012-12-07 10:10:04 +080060int main(int argc, char *argv[])
mridge949c5b12006-01-03 23:01:28 +000061{
Wanlong Gao354ebb42012-12-07 10:10:04 +080062 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020063 const char *msg;
mridge949c5b12006-01-03 23:01:28 +000064
65 /* Parse standard options given to run the test. */
Garrett Cooper38097ab2010-12-17 03:23:52 -080066 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
Garrett Cooper53740502010-12-16 00:04:01 -080067 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
mridge949c5b12006-01-03 23:01:28 +000068
69 setup();
70
71 for (lc = 0; TEST_LOOPING(lc); ++lc) {
72 icmp6_et();
73 icmp6_ft();
74 }
75
76 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -080077
78 tst_exit();
mridge949c5b12006-01-03 23:01:28 +000079}
80
81enum ttype { EXISTS, ALIAS, VALUE, DEFINED };
82
83struct etent {
Wanlong Gao354ebb42012-12-07 10:10:04 +080084 char *et_tname; /* test name */
85 int et_type; /* test type */
86 char *et_incl; /* include file list */
87 char *et_struct; /* structure name */
88 char *et_field; /* field name */
89 char *et_offset; /* field offset */
mridge949c5b12006-01-03 23:01:28 +000090 union {
Wanlong Gao354ebb42012-12-07 10:10:04 +080091 char *fu_value; /* field size or value */
92 char *fu_dname; /* #define name */
mridge949c5b12006-01-03 23:01:28 +000093 } ftun;
94#define et_value ftun.fu_value
95#define et_dname ftun.fu_dname
96} etab[] = {
97/* existence checks, RFC 3542 section 3 */
Wanlong Gao354ebb42012-12-07 10:10:04 +080098 {
99 "icmp6_filter icmp6_filt", EXISTS, ICMP6_H, "icmp6_filter",
100 "icmp6_filt", "0", {
101 "32"}}, {
102 "icmp6_filter icmp6_filt[0]", EXISTS, ICMP6_H, "icmp6_filter",
103 "icmp6_filt[0]", "0", {
104 "4"}}, {
105 "ICMP6_FILTER_WILLPASS", DEFINED, ICMP6_H,
106 "ICMP6_FILTER_WILLPASS", NULL, NULL, {
107 0}}, {
108 "ICMP6_FILTER_WILLBLOCK", DEFINED, ICMP6_H,
109 "ICMP6_FILTER_WILLBLOCK", NULL, NULL, {
110 0}}, {
111 "ICMP6_FILTER_SETPASS", DEFINED, ICMP6_H,
112 "ICMP6_FILTER_SETPASS", NULL, NULL, {
113 0}}, {
114 "ICMP6_FILTER_SETBLOCK", DEFINED, ICMP6_H,
115 "ICMP6_FILTER_SETBLOCK", NULL, NULL, {
116 0}}, {
117 "ICMP6_FILTER_SETPASSALL", DEFINED, ICMP6_H,
118 "ICMP6_FILTER_SETPASSALL", NULL, NULL, {
119 0}}, {
120 "ICMP6_FILTER_SETBLOCKALL", DEFINED, ICMP6_H,
121 "ICMP6_FILTER_SETBLOCKALL", NULL, NULL, {
122 0}}, {
123 "ICMP6_FILTER", DEFINED, ICMP6_H, "ICMP6_FILTER", NULL, NULL, {
124 0}},
mridge949c5b12006-01-03 23:01:28 +0000125/* existence checks, RFC 3542 section 4 */
126/* socket options */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800127 {
128 "IPV6_RECVPKTINFO", VALUE, IN_H, "IPV6_RECVPKTINFO", NULL, NULL, {
129 "IPV6_RECVPKTINFO"}}, {
130 "IPV6_RECVHOPLIMIT", VALUE, IN_H, "IPV6_RECVHOPLIMIT", NULL,
131 NULL, {
132 "IPV6_RECVHOPLIMIT"}}, {
133 "IPV6_RECVRTHDR", VALUE, IN_H, "IPV6_RECVRTHDR", NULL, NULL, {
134 "IPV6_RECVRTHDR"}}, {
135 "IPV6_RECVHOPOPTS", VALUE, IN_H, "IPV6_RECVHOPOPTS", NULL, NULL, {
136 "IPV6_RECVHOPOPTS"}}, {
137 "IPV6_RECVDSTOPTS", VALUE, IN_H, "IPV6_RECVDSTOPTS", NULL, NULL, {
138 "IPV6_RECVDSTOPTS"}}, {
139 "IPV6_RECVTCLASS", VALUE, IN_H, "IPV6_RECVTCLASS", NULL, NULL, {
140 "IPV6_RECVTCLASS"}},
mridge949c5b12006-01-03 23:01:28 +0000141/* cmsg types */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800142 {
143 "IPV6_PKTINFO", DEFINED, IN_H, "IPV6_PKTINFO", NULL, NULL, {
144 0}}, {
145 "IPV6_HOPLIMIT", DEFINED, IN_H, "IPV6_HOPLIMIT", NULL, NULL, {
146 0}}, {
147 "IPV6_NEXTHOP", DEFINED, IN_H, "IPV6_NEXTHOP", NULL, NULL, {
148 0}}, {
149 "IPV6_RTHDR", DEFINED, IN_H, "IPV6_RTHDR", NULL, NULL, {
150 0}}, {
151 "IPV6_HOPOPTS", DEFINED, IN_H, "IPV6_HOPOPTS", NULL, NULL, {
152 0}}, {
153 "IPV6_DSTOPTS", DEFINED, IN_H, "IPV6_DSTOPTS", NULL, NULL, {
154 0}}, {
155 "IPV6_RTHDRDSTOPTS", DEFINED, IN_H, "IPV6_RTHDRDSTOPTS", NULL,
156 NULL, {
157 0}}, {
158 "IPV6_TCLASS", DEFINED, IN_H, "IPV6_TCLASS", NULL, NULL, {
1590}},};
mridge949c5b12006-01-03 23:01:28 +0000160
161#define ETCOUNT (sizeof(etab)/sizeof(etab[0]))
162
163/* existence tests */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164void icmp6_et(void)
mridge949c5b12006-01-03 23:01:28 +0000165{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 int i;
mridge949c5b12006-01-03 23:01:28 +0000167
Wanlong Gao354ebb42012-12-07 10:10:04 +0800168 for (i = 0; i < ETCOUNT; ++i) {
mridge949c5b12006-01-03 23:01:28 +0000169 switch (etab[i].et_type) {
170 case EXISTS:
171 structcheck(etab[i].et_tname, etab[i].et_incl,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800172 etab[i].et_struct, etab[i].et_field,
173 etab[i].et_offset, etab[i].et_value);
mridge949c5b12006-01-03 23:01:28 +0000174 break;
175 case ALIAS:
176 aliascheck(etab[i].et_tname, etab[i].et_incl,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800177 etab[i].et_struct, etab[i].et_field,
178 etab[i].et_dname);
mridge949c5b12006-01-03 23:01:28 +0000179 break;
180 case VALUE:
181 valuecheck(etab[i].et_tname, etab[i].et_incl,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800182 etab[i].et_struct, etab[i].et_dname);
mridge949c5b12006-01-03 23:01:28 +0000183 break;
184 case DEFINED:
185 funccheck(etab[i].et_tname, etab[i].et_incl,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186 etab[i].et_struct);
mridge949c5b12006-01-03 23:01:28 +0000187 break;
188 default:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800189 tst_resm(TBROK, "invalid type %d", etab[i].et_type);
mridge949c5b12006-01-03 23:01:28 +0000190 break;
191 }
192 }
193}
194
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195void setup(void)
mridge949c5b12006-01-03 23:01:28 +0000196{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 TEST_PAUSE; /* if -P option specified */
Garrett Cooper38097ab2010-12-17 03:23:52 -0800198 tst_require_root(NULL);
mridge949c5b12006-01-03 23:01:28 +0000199}
200
Wanlong Gao354ebb42012-12-07 10:10:04 +0800201void cleanup(void)
mridge949c5b12006-01-03 23:01:28 +0000202{
mridge949c5b12006-01-03 23:01:28 +0000203}
204
205/*
206 * This is for old, broken glibc-header icmp6_filter structure definitions.
207 * If icmp6.h has struct icmp6_filter with field named "data" instead
208 * of the standard "icmp_filt", uncomment this line.
209 */
210/*#define icmp_filt data */
211
212enum tt { T_WILLPASS, T_WILLBLOCK, T_SETPASS, T_SETBLOCK, T_SETPASSALL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800213 T_SETBLOCKALL
mridge949c5b12006-01-03 23:01:28 +0000214};
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215struct ftent {
216 char *ft_tname; /* test name, for logging */
217 unsigned char ft_sndtype; /* send type field */
218 unsigned char ft_flttype; /* filter type field */
219 enum tt ft_test; /* what macro to test */
220 int ft_expected; /* packet should pass? */
221} ftab[] = {
222 {
223 "ICMP6_FILTER_SETPASS s 20 f 20", 20, 20, T_SETPASS, 1}, {
224 "ICMP6_FILTER_SETPASS s 20 f 21", 20, 21, T_SETPASS, 0}, {
225 "ICMP6_FILTER_SETBLOCK s 20 f 20", 20, 20, T_SETBLOCK, 0}, {
226 "ICMP6_FILTER_SETBLOCK s 20 f 21", 20, 21, T_SETBLOCK, 1}, {
227 "ICMP6_FILTER_PASSALL s 20", 20, 0, T_SETPASSALL, 1}, {
228 "ICMP6_FILTER_PASSALL s 20", 21, 0, T_SETPASSALL, 1}, {
229 "ICMP6_FILTER_BLOCKALL s 20", 20, 0, T_SETBLOCKALL, 0}, {
230 "ICMP6_FILTER_BLOCKALL s 20", 21, 0, T_SETBLOCKALL, 0}, {
231 "ICMP6_FILTER_WILLBLOCK s 20 f 21", 20, 21, T_WILLBLOCK, 0}, {
232 "ICMP6_FILTER_WILLBLOCK s 20 f 20", 20, 20, T_WILLBLOCK, 1}, {
233 "ICMP6_FILTER_WILLPASS s 20 f 21", 20, 21, T_WILLPASS, 0}, {
234"ICMP6_FILTER_WILLPASS s 22 f 22", 22, 22, T_WILLPASS, 1},};
mridge949c5b12006-01-03 23:01:28 +0000235
236#define FTCOUNT (sizeof(ftab)/sizeof(ftab[0]))
237
Wanlong Gao354ebb42012-12-07 10:10:04 +0800238int ic6_send1(char *tname, unsigned char type)
mridge949c5b12006-01-03 23:01:28 +0000239{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800240 struct sockaddr_in6 sin6;
241 struct icmp6_hdr ic6;
242 int s;
mridge949c5b12006-01-03 23:01:28 +0000243
244 s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
Garrett Cooper38097ab2010-12-17 03:23:52 -0800245 if (s == -1) {
246 tst_resm(TBROK, "%s: socket failed", tname);
mridge949c5b12006-01-03 23:01:28 +0000247 return 1;
248 }
249 memset(&ic6, 0, sizeof(ic6));
250 ic6.icmp6_type = type;
251 ic6.icmp6_data32[0] = htonl(getpid());
252
253 memset(&sin6, 0, sizeof(sin6));
254 sin6.sin6_family = AF_INET6;
255 sin6.sin6_addr = in6addr_loopback;
256 if (sendto(s, &ic6, sizeof(ic6), 0, (struct sockaddr *)&sin6,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800257 sizeof(sin6)) == -1) {
258 tst_resm(TBROK | TERRNO, "%s: sendto failed", tname);
mridge949c5b12006-01-03 23:01:28 +0000259 return 1;
260 }
261 return 0;
262}
263
Wanlong Gao354ebb42012-12-07 10:10:04 +0800264int ic6_recv1(char *tname, int sall, int sf)
mridge949c5b12006-01-03 23:01:28 +0000265{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800266 fd_set readfds, readfds_saved;
267 struct timeval tv;
268 int maxfd, nfds;
269 int gotall, gotone;
270 int cc;
271 static unsigned char rbuf[2048];
mridge949c5b12006-01-03 23:01:28 +0000272
273 tv.tv_sec = 0;
274 tv.tv_usec = 250000;
275
276 FD_ZERO(&readfds_saved);
277 FD_SET(sall, &readfds_saved);
278 FD_SET(sf, &readfds_saved);
279 maxfd = MAX(sall, sf);
280
281 memcpy(&readfds, &readfds_saved, sizeof(readfds));
282
283 gotall = gotone = 0;
284 /*
285 * Note: this relies on linux-specific behavior (select
286 * updating tv with time elapsed)
287 */
288 while (!gotall || !gotone) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800289 struct icmp6_hdr *pic6 = (struct icmp6_hdr *)rbuf;
mridge949c5b12006-01-03 23:01:28 +0000290
Wanlong Gao354ebb42012-12-07 10:10:04 +0800291 nfds = select(maxfd + 1, &readfds, 0, 0, &tv);
mridge949c5b12006-01-03 23:01:28 +0000292 if (nfds == 0)
293 break; /* timed out */
294 if (nfds < 0) {
295 if (errno == EINTR)
296 continue;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800297 tst_resm(TBROK | TERRNO, "%s: select failed", tname);
mridge949c5b12006-01-03 23:01:28 +0000298 }
299 if (FD_ISSET(sall, &readfds)) {
300 cc = recv(sall, rbuf, sizeof(rbuf), 0);
301 if (cc < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800302 tst_resm(TBROK | TERRNO,
303 "%s: recv(sall, ..) failed", tname);
mridge949c5b12006-01-03 23:01:28 +0000304 return -1;
305 }
306 /* if packet check succeeds... */
307 if (htonl(pic6->icmp6_data32[0]) == getpid())
308 gotall = 1;
309 }
310 if (FD_ISSET(sf, &readfds)) {
311 cc = recv(sf, rbuf, sizeof(rbuf), 0);
312 if (cc < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800313 tst_resm(TBROK | TERRNO,
314 "%s: recv(sf, ..) failed", tname);
mridge949c5b12006-01-03 23:01:28 +0000315 return -1;
316 }
317 /* if packet check succeeds... */
318 if (htonl(pic6->icmp6_data32[0]) == getpid())
319 gotone = 1;
320 }
321 memcpy(&readfds, &readfds_saved, sizeof(readfds));
322 }
323 if (!gotall) {
Garrett Cooper38097ab2010-12-17 03:23:52 -0800324 tst_resm(TBROK, "%s: recv all timed out", tname);
mridge949c5b12006-01-03 23:01:28 +0000325 return -1;
326 }
327 if (gotone)
328 return 1;
329 return 0;
330}
331
332/* functional tests */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800333void icmp6_ft(void)
mridge949c5b12006-01-03 23:01:28 +0000334{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800335 struct icmp6_filter i6f;
mridge949c5b12006-01-03 23:01:28 +0000336 int sall, sf;
337 int i;
338
339 sall = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
340 if (sall < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800341 tst_resm(TBROK | TERRNO,
342 "icmp6_ft socket: can't create sall socket");
mridge949c5b12006-01-03 23:01:28 +0000343 return;
344 }
345 ICMP6_FILTER_SETPASSALL(&i6f);
346 if (setsockopt(sall, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800347 sizeof(i6f)) < 0) {
348 tst_resm(TBROK | TERRNO,
349 "setsockopt pass all ICMP6_FILTER failed");
mridge949c5b12006-01-03 23:01:28 +0000350 }
351
352 sf = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
353 if (sf < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800354 tst_resm(TBROK | TERRNO,
355 "icmp6_ft socket: can't create test socket");
mridge949c5b12006-01-03 23:01:28 +0000356 return;
357 }
Garrett Cooper38097ab2010-12-17 03:23:52 -0800358
359 int rv;
360
361 for (i = 0; i < FTCOUNT; ++i) {
362
363 rv = -1;
mridge949c5b12006-01-03 23:01:28 +0000364
365 switch (ftab[i].ft_test) {
366 case T_SETPASS:
367 ICMP6_FILTER_SETBLOCKALL(&i6f);
368 ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
369 break;
370 case T_SETPASSALL:
371 ICMP6_FILTER_SETPASSALL(&i6f);
372 break;
373 case T_SETBLOCK:
374 ICMP6_FILTER_SETPASSALL(&i6f);
375 ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
376 break;
377 case T_SETBLOCKALL:
378 ICMP6_FILTER_SETBLOCKALL(&i6f);
379 break;
380 case T_WILLBLOCK:
381 ICMP6_FILTER_SETPASSALL(&i6f);
382 ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
383 rv = ICMP6_FILTER_WILLBLOCK(ftab[i].ft_sndtype, &i6f);
384 break;
385 case T_WILLPASS:
386 ICMP6_FILTER_SETBLOCKALL(&i6f);
387 ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
388 rv = ICMP6_FILTER_WILLPASS(ftab[i].ft_sndtype, &i6f);
389 break;
390 default:
Garrett Cooper38097ab2010-12-17 03:23:52 -0800391 tst_resm(TBROK, "%s: unknown test type %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 ftab[i].ft_tname, ftab[i].ft_test);
mridge949c5b12006-01-03 23:01:28 +0000393 continue;
394 }
395 if (ftab[i].ft_test != T_WILLBLOCK &&
396 ftab[i].ft_test != T_WILLPASS) {
397 if (setsockopt(sf, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800398 sizeof(i6f)) < 0) {
399 tst_resm(TFAIL | TERRNO,
400 "setsockopt ICMP6_FILTER");
mridge949c5b12006-01-03 23:01:28 +0000401 continue;
402 }
403 if (ic6_send1(ftab[i].ft_tname, ftab[i].ft_sndtype))
404 continue;
405 rv = ic6_recv1(ftab[i].ft_tname, sall, sf);
Garrett Cooper38097ab2010-12-17 03:23:52 -0800406 } else
407 rv = -1;
mridge949c5b12006-01-03 23:01:28 +0000408
409 if (rv < 0)
410 continue;
411 if (rv != ftab[i].ft_expected)
Garrett Cooper38097ab2010-12-17 03:23:52 -0800412 tst_resm(TFAIL, "%s: rv %d != expected %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800413 ftab[i].ft_tname, rv, ftab[i].ft_expected);
mridge949c5b12006-01-03 23:01:28 +0000414 else
Ken Dreyer8c97e9d2014-12-09 16:26:00 -0700415 tst_resm(TPASS, "%s", ftab[i].ft_tname);
mridge949c5b12006-01-03 23:01:28 +0000416 }
417}
418
Chris Dearmanec6edca2012-10-17 19:54:01 -0700419int TST_TOTAL = ETCOUNT;