blob: 0693e3aa411418150d18248f67fe95dde61e8095 [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_06
22 *
23 * Test Description:
24 * Tests for RFC 3542 section 4 socket options and ancillary data
25 *
26 * Usage: <for command-line>
27 * asapi_06
28 *
29 * HISTORY
30 * 05/2005 written by David L Stevens
31 *
32 * RESTRICTIONS:
33 * None.
34 *
35 */
36
subrata_modak52568192008-12-12 13:43:40 +000037#include "config.h"
38
mridge949c5b12006-01-03 23:01:28 +000039#include <stdio.h>
40#include <unistd.h>
41#include <errno.h>
42#include <netdb.h>
43#include <libgen.h>
44#include <pthread.h>
45#include <semaphore.h>
46
47#include <sys/time.h>
48#include <netinet/in.h>
49#include <netinet/ip6.h>
mridge949c5b12006-01-03 23:01:28 +000050#include <sys/types.h>
51#include <sys/socket.h>
52#include <net/if.h>
53#include <sys/ioctl.h>
subrata_modak52568192008-12-12 13:43:40 +000054#ifdef HAVE_IFADDRS_H
mridge949c5b12006-01-03 23:01:28 +000055#include <ifaddrs.h>
subrata_modak52568192008-12-12 13:43:40 +000056#endif
subrata_modakaa588ae2008-09-18 13:18:36 +000057#include <arpa/inet.h>
mridge949c5b12006-01-03 23:01:28 +000058
59#include "test.h"
mridge949c5b12006-01-03 23:01:28 +000060
Wanlong Gao354ebb42012-12-07 10:10:04 +080061char *TCID = "asapi_06"; /* Test program identifier. */
mridge949c5b12006-01-03 23:01:28 +000062
63int TST_TOTAL = 1;
64
65pid_t pid;
66
67struct {
Wanlong Gao354ebb42012-12-07 10:10:04 +080068 char *prt_name;
69 int prt_value;
mridge949c5b12006-01-03 23:01:28 +000070} ptab[] = {
71};
72
73#define PTCOUNT (sizeof(ptab)/sizeof(ptab[0]))
74
75#define READ_TIMEOUT 5 /* secs */
76
77void do_tests(void);
78void setup(void), cleanup(void);
79
Wanlong Gao354ebb42012-12-07 10:10:04 +080080int main(int argc, char *argv[])
mridge949c5b12006-01-03 23:01:28 +000081{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020082 const char *msg;
mridge949c5b12006-01-03 23:01:28 +000083 int lc;
mridge949c5b12006-01-03 23:01:28 +000084
85 /* Parse standard options given to run the test. */
86 msg = parse_opts(argc, argv, 0, 0);
Garrett Cooperdf3eb162010-11-28 22:44:32 -080087 if (msg != NULL) {
Garrett Cooper53740502010-12-16 00:04:01 -080088 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
mridge949c5b12006-01-03 23:01:28 +000089 }
90
91 pid = getpid();
92
93 setup();
94
95 for (lc = 0; TEST_LOOPING(lc); ++lc)
96 do_tests();
97
98 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -080099
100 tst_exit();
101}
mridge949c5b12006-01-03 23:01:28 +0000102
103#define NH_TEST 0x9f
104
105#ifndef IPV6_RECVPKTINFO
106#define IPV6_RECVPKTINFO -1
107#endif
108#ifndef IPV6_RECVHOPLIMIT
109#define IPV6_RECVHOPLIMIT -1
110#endif
111#ifndef IPV6_RECVRTHDR
112#define IPV6_RECVRTHDR -1
113#endif
114#ifndef IPV6_RECVHOPOPTS
115#define IPV6_RECVHOPOPTS -1
116#endif
117#ifndef IPV6_RECVDSTOPTS
118#define IPV6_RECVDSTOPTS -1
119#endif
120#ifndef IPV6_RECVTCLASS
121#define IPV6_RECVTCLASS -1
122#endif
123#ifndef IPV6_TCLASS
124#define IPV6_TCLASS -1
125#endif
126#ifndef IPV6_2292PKTINFO
127#define IPV6_2292PKTINFO -1
128#endif
129#ifndef IPV6_2292HOPLIMIT
130#define IPV6_2292HOPLIMIT -1
131#endif
132#ifndef IPV6_2292RTHDR
133#define IPV6_2292RTHDR -1
134#endif
135#ifndef IPV6_2292HOPOPTS
136#define IPV6_2292HOPOPTS -1
137#endif
138#ifndef IPV6_2292DSTOPTS
139#define IPV6_2292DSTOPTS -1
140#endif
141
142union soval {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800143 struct in6_pktinfo sou_pktinfo;
144 int sou_hoplimit;
145 struct sockaddr_in6 sou_nexthop;
146 struct ip6_rthdr sou_rthdr;
147 struct ip6_hbh sou_hopopts;
148 struct ip6_dest sou_dstopts;
149 struct ip6_dest sou_rthdrdstopts;
150 int sou_tclass;
151 int sou_bool;
mridge949c5b12006-01-03 23:01:28 +0000152};
153
154/* in6_addr initializer for loopback interface */
155#define IN6_LOOP {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }
156#define IN6_ANY {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
157
subrata_modak005dc012008-12-12 13:39:59 +0000158/* so_clrval and so_setval members are initilized in the body */
mridge949c5b12006-01-03 23:01:28 +0000159struct soent {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800160 char *so_tname;
161 int so_opt;
162 int so_dorecv; /* do receive test? */
163 int so_cmtype;
164 int so_clear; /* get fresh socket? */
165 union soval so_clrval;
166 union soval so_setval;
167 socklen_t so_valsize;
mridge949c5b12006-01-03 23:01:28 +0000168} sotab[] = {
169/* RFC 3542, Section 4 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800170 {
171 "IPV6_RECVPKTINFO", IPV6_RECVPKTINFO, 1, IPV6_PKTINFO, 1, { { { { {
172 0}}}}}, { { { { {
173 0}}}}}, sizeof(int)}, {
174 "IPV6_RECVHOPLIMIT", IPV6_RECVHOPLIMIT, 1, IPV6_HOPLIMIT, 1, { { { { {
175 0}}}}}, { { { { {
176 0}}}}}, sizeof(int)}, {
177 "IPV6_RECVRTHDR", IPV6_RECVRTHDR, 0, IPV6_RTHDR, 1, { { { { {
178 0}}}}}, { { { { {
179 0}}}}}, sizeof(int)}, {
180 "IPV6_RECVHOPOPTS", IPV6_RECVHOPOPTS, 0, IPV6_HOPOPTS, 1, { { { { {
181 0}}}}}, { { { { {
182 0}}}}}, sizeof(int)}, {
183 "IPV6_RECVDSTOPTS", IPV6_RECVDSTOPTS, 0, IPV6_DSTOPTS, 1, { { { { {
184 0}}}}}, { { { { {
185 0}}}}}, sizeof(int)}, {
186 "IPV6_RECVTCLASS", IPV6_RECVTCLASS, 1, IPV6_TCLASS, 1, { { { { {
187 0}}}}}, { { { { {
188 0}}}}}, sizeof(int)},
mridge949c5b12006-01-03 23:01:28 +0000189/* make sure TCLASS stays when setting another opt */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 {
191 "IPV6_RECVTCLASS (2)", IPV6_RECVHOPLIMIT, 1, IPV6_TCLASS, 0, { { { { {
192 0}}}}}, { { { { {
193 0}}}}}, sizeof(int)},
mridge949c5b12006-01-03 23:01:28 +0000194/* OLD values */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195 {
196 "IPV6_2292PKTINFO", IPV6_2292PKTINFO, 1, IPV6_2292PKTINFO, 1, { { { { {
197 0}}}}}, { { { { {
198 0}}}}}, sizeof(int)}, {
199 "IPV6_2292HOPLIMIT", IPV6_2292HOPLIMIT, 1, IPV6_2292HOPLIMIT, 1, { { { { {
200 0}}}}}, { { { { {
201 0}}}}}, sizeof(int)}, {
202 "IPV6_2292RTHDR", IPV6_2292RTHDR, 0, IPV6_2292RTHDR, 1, { { { { {
203 0}}}}}, { { { { {
204 0}}}}}, sizeof(int)}, {
205 "IPV6_2292HOPOPTS", IPV6_2292HOPOPTS, 0, IPV6_2292HOPOPTS, 1, { { { { {
206 0}}}}}, { { { { {
207 0}}}}}, sizeof(int)}, {
208 "IPV6_2292DSTOPTS", IPV6_2292DSTOPTS, 0, IPV6_2292DSTOPTS, 1, { { { { {
209 0}}}}}, { { { { {
2100}}}}}, sizeof(int)},};
mridge949c5b12006-01-03 23:01:28 +0000211
212#define SOCOUNT (sizeof(sotab)/sizeof(sotab[0]))
213
214struct soprot {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215 int sop_pid; /* sender PID */
216 int sop_seq; /* sequence # */
217 int sop_dlen; /* tp_dat length */
218 unsigned char sop_dat[0]; /* user data */
mridge949c5b12006-01-03 23:01:28 +0000219};
220
221unsigned char tpbuf[sizeof(struct soprot) + 2048];
222unsigned char rpbuf[sizeof(struct soprot) + 2048];
223
224unsigned char control[2048];
225int clen;
226
227int seq;
228
Wanlong Gao354ebb42012-12-07 10:10:04 +0800229int setupso(void)
mridge949c5b12006-01-03 23:01:28 +0000230{
231/* add routing headers, other ancillary data here */
232 return 0;
233}
234
235struct cme {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236 int cm_len;
237 int cm_level;
238 int cm_type;
mridge949c5b12006-01-03 23:01:28 +0000239 union {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800240 uint32_t cmu_tclass;
mreed101c069252006-09-22 19:57:07 +0000241 uint32_t cmu_hops;
mridge949c5b12006-01-03 23:01:28 +0000242 } cmu;
243} cmtab[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800244 {
245 sizeof(uint32_t), SOL_IPV6, IPV6_TCLASS, {
246 0x12}
247 }
248 , {
249 sizeof(uint32_t), SOL_IPV6, IPV6_HOPLIMIT, {
250 0x21}
251 }
252,};
mridge949c5b12006-01-03 23:01:28 +0000253
254#define CMCOUNT (sizeof(cmtab)/sizeof(cmtab[0]))
255
Wanlong Gao354ebb42012-12-07 10:10:04 +0800256ssize_t sendall(int st)
mridge949c5b12006-01-03 23:01:28 +0000257{
258 struct sockaddr_in6 sin6;
259 struct msghdr msg;
260 struct iovec iov;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800261 struct soprot *psop;
mridge949c5b12006-01-03 23:01:28 +0000262 unsigned char *pd;
263 int i, ctotal;
264
265 psop = (struct soprot *)tpbuf;
266 psop->sop_pid = htonl(getpid());
267 psop->sop_seq = ++seq;
268 psop->sop_dlen = 0;
269
270 memset(&sin6, 0, sizeof(sin6));
271 sin6.sin6_family = AF_INET6;
272 sin6.sin6_addr = in6addr_loopback;
273
274 memset(&msg, 0, sizeof(msg));
275 msg.msg_name = &sin6;
276 msg.msg_namelen = sizeof(sin6);
277 iov.iov_base = tpbuf;
278 iov.iov_len = sizeof(struct soprot) + ntohl(psop->sop_dlen);
279 msg.msg_iov = &iov;
280 msg.msg_iovlen = 1;
281
282 pd = control;
283 ctotal = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800284 for (i = 0; i < CMCOUNT; ++i) {
285 struct cmsghdr *pcmsg = (struct cmsghdr *)pd;
mridge949c5b12006-01-03 23:01:28 +0000286
287 pcmsg->cmsg_len = CMSG_LEN(cmtab[i].cm_len);
288 pcmsg->cmsg_level = cmtab[i].cm_level;
289 pcmsg->cmsg_type = cmtab[i].cm_type;
290 memcpy(CMSG_DATA(pcmsg), &cmtab[i].cmu, cmtab[i].cm_len);
291 pd += CMSG_SPACE(cmtab[i].cm_len);
292 ctotal += CMSG_SPACE(cmtab[i].cm_len);
293 }
294 msg.msg_control = ctotal ? control : 0;
295 msg.msg_controllen = ctotal;
296
297 return sendmsg(st, &msg, 0);
298}
299
Wanlong Gao354ebb42012-12-07 10:10:04 +0800300void so_test(struct soent *psoe)
mridge949c5b12006-01-03 23:01:28 +0000301{
302 struct sockaddr_in6 sin6;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800303 union soval sobuf;
304 socklen_t valsize;
mridge949c5b12006-01-03 23:01:28 +0000305 static int sr = -1;
306 int st;
307
Garrett Cooper8fb1cdb2010-11-28 22:56:35 -0800308 if (psoe->so_opt == -1) {
mridge949c5b12006-01-03 23:01:28 +0000309 tst_resm(TBROK, "%s not present at compile time",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 psoe->so_tname);
mridge949c5b12006-01-03 23:01:28 +0000311 return;
312 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800313 if (psoe->so_clear || sr < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800314 if (sr < 0)
mridge949c5b12006-01-03 23:01:28 +0000315 close(sr);
316 sr = socket(PF_INET6, SOCK_RAW, NH_TEST);
317 if (sr < 0) {
318 tst_resm(TBROK, "%s socket: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800319 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000320 return;
321 }
322 }
323 memset(&sin6, 0, sizeof(sin6));
324 sin6.sin6_family = AF_INET6;
325 sin6.sin6_addr = in6addr_loopback;
326 if (bind(sr, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
327 tst_resm(TBROK, "%s: bind: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800328 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000329 }
330 if (setsockopt(sr, SOL_IPV6, psoe->so_opt, &psoe->so_clrval,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800331 psoe->so_valsize) < 0) {
mridge949c5b12006-01-03 23:01:28 +0000332 tst_resm(TBROK, "%s: setsockopt: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800333 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000334 return;
335 }
336 TEST(setsockopt(sr, SOL_IPV6, psoe->so_opt, &psoe->so_setval,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800337 psoe->so_valsize));
mridge949c5b12006-01-03 23:01:28 +0000338 if (TEST_RETURN != 0) {
339 tst_resm(TFAIL, "%s set-get: setsockopt: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800340 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000341 return;
342 }
343 valsize = psoe->so_valsize;
vapier0559d692006-08-21 07:02:02 +0000344 TEST(getsockopt(sr, SOL_IPV6, psoe->so_opt, &sobuf, &valsize));
mridge949c5b12006-01-03 23:01:28 +0000345 if (TEST_RETURN != 0) {
346 tst_resm(TBROK, "%s set-get: getsockopt: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800347 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000348 return;
349 } else if (memcmp(&psoe->so_setval, &sobuf, psoe->so_valsize))
350 tst_resm(TFAIL, "%s set-get optval != setval", psoe->so_tname);
351 else
352 tst_resm(TPASS, "%s set-get", psoe->so_tname);
353
354 st = socket(PF_INET6, SOCK_RAW, NH_TEST);
355 if (st < 0) {
356 tst_resm(TBROK, "%s transmit socket: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800357 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000358 return;
359 }
360 if (sendall(st) < 0) {
361 tst_resm(TBROK, "%s transmit sendto: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800362 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000363 close(st);
364 return;
365 }
366 close(st);
367
368 /* receiver processing */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800369 {
370 fd_set rfds, rfds_saved;
371 int nfds, cc;
372 int gotone;
373 struct timeval tv;
374 struct msghdr msg;
375 unsigned char cmsg[2048];
376 struct cmsghdr *pcmsg;
377 struct iovec iov;
mridge949c5b12006-01-03 23:01:28 +0000378
379 FD_ZERO(&rfds_saved);
380 FD_SET(sr, &rfds_saved);
381
382 tv.tv_sec = 0;
383 tv.tv_usec = 250000;
384
385 while (1) {
386 memcpy(&rfds, &rfds_saved, sizeof(rfds));
Wanlong Gao354ebb42012-12-07 10:10:04 +0800387 nfds = select(sr + 1, &rfds, 0, 0, &tv);
mridge949c5b12006-01-03 23:01:28 +0000388 if (nfds < 0) {
389 if (errno == EINTR)
390 continue;
391 tst_resm(TBROK, "%s select: %s", psoe->so_tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000393 return;
394 }
395 if (nfds == 0) {
396 tst_resm(TBROK, "%s recvmsg timed out",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800397 psoe->so_tname);
mridge949c5b12006-01-03 23:01:28 +0000398 return;
399 }
400 /* else, nfds == 1 */
401 if (!FD_ISSET(sr, &rfds))
402 continue;
403
404 memset(&msg, 0, sizeof(msg));
405 iov.iov_base = rpbuf;
406 iov.iov_len = sizeof(rpbuf);
407 msg.msg_iov = &iov;
408 msg.msg_iovlen = 1;
409 msg.msg_control = cmsg;
410 msg.msg_controllen = sizeof(cmsg);
411
412 cc = recvmsg(sr, &msg, 0);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800413 if (cc < 0) {
mridge949c5b12006-01-03 23:01:28 +0000414 tst_resm(TBROK, "%s recvmsg: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800415 psoe->so_tname, strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000416 return;
417 }
418/* check pid & seq here */
419 break;
420 }
421 gotone = 0;
subrata_modak0102c2c2008-09-18 13:17:31 +0000422 for (pcmsg = CMSG_FIRSTHDR(&msg); pcmsg != NULL;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800423 pcmsg = CMSG_NXTHDR(&msg, pcmsg)) {
mridge949c5b12006-01-03 23:01:28 +0000424 if (!psoe->so_dorecv)
425 break;
mridge949c5b12006-01-03 23:01:28 +0000426 gotone = pcmsg->cmsg_level == SOL_IPV6 &&
427 pcmsg->cmsg_type == psoe->so_cmtype;
428 if (gotone)
429 break;
430 else if (psoe->so_clear) {
431 tst_resm(TFAIL, "%s receive: extraneous data "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800432 "in control: level %d type %d len %zu",
433 psoe->so_tname, pcmsg->cmsg_level,
434 pcmsg->cmsg_type, pcmsg->cmsg_len);
mridge949c5b12006-01-03 23:01:28 +0000435 return;
436 }
437 }
mridge949c5b12006-01-03 23:01:28 +0000438/* check contents here */
439 if (psoe->so_dorecv)
440 tst_resm(gotone ? TPASS : TFAIL, "%s receive",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800441 psoe->so_tname);
mridge949c5b12006-01-03 23:01:28 +0000442 }
443}
444
445#define IPV6_ADDR_NODE 1
446#define IPV6_ADDR_LINK 2
447#define IPV6_ADDR_GLOBAL 3
448
subrata_modak52568192008-12-12 13:43:40 +0000449#ifdef HAVE_IFADDRS_H
mridge949c5b12006-01-03 23:01:28 +0000450static int ipv6_addr_scope(struct in6_addr *pin6)
451{
452 if ((ntohl(pin6->s6_addr32[0]) & 0xFFC00000) == 0xFE800000)
453 return IPV6_ADDR_LINK;
454 if (memcmp(pin6, &in6addr_loopback, sizeof(*pin6)) == 0)
455 return IPV6_ADDR_NODE;
456 return IPV6_ADDR_GLOBAL;
457}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800458#endif /* HAVE_IFADDRS_H */
mridge949c5b12006-01-03 23:01:28 +0000459
460int getsock(char *tname, struct sockaddr_in6 *psin6_arg, int scope)
461{
subrata_modak52568192008-12-12 13:43:40 +0000462#ifdef HAVE_IFADDRS_H
mridge949c5b12006-01-03 23:01:28 +0000463 static struct ifaddrs *pifa_head;
464 struct ifaddrs *pifa;
465 struct sockaddr_in6 *psin6;
466 char strbuf[128];
467 int ifindex = 0;
468 int s;
469
470 if (!pifa_head && getifaddrs(&pifa_head)) {
471 tst_resm(TBROK, "%s: getifaddrs failed", tname);
472 return -1;
473 }
474 if (psin6_arg)
475 ifindex = psin6_arg->sin6_scope_id;
476
477 /* first, find a global address */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800478 for (pifa = pifa_head; pifa; pifa = pifa->ifa_next) {
mridge949c5b12006-01-03 23:01:28 +0000479 int this_scope;
480
481 if (!(pifa->ifa_flags & IFF_UP))
482 continue;
483 if (pifa->ifa_addr->sa_family != AF_INET6)
484 continue;
485 psin6 = (struct sockaddr_in6 *)pifa->ifa_addr;
486 this_scope = ipv6_addr_scope(&psin6->sin6_addr);
487 if (this_scope &&
488 ((this_scope < 0 && -this_scope == scope) ||
489 (this_scope > 0 && this_scope != scope)))
490 continue;
491 psin6->sin6_scope_id = if_nametoindex(pifa->ifa_name);
492 if ((ifindex < 0 && -ifindex == psin6->sin6_scope_id) ||
493 (ifindex > 0 && ifindex != psin6->sin6_scope_id))
494 continue;
495 s = socket(PF_INET6, SOCK_DGRAM, 0);
496 if (s < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800497 tst_resm(TBROK, "%s: socket %s", tname,
498 strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000499 return -1;
500 }
501 if (bind(s, pifa->ifa_addr, sizeof(struct sockaddr_in6)) < 0) {
502 tst_resm(TBROK, "%s: bind \"%s\": %s", tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800503 inet_ntop(AF_INET6, &psin6->sin6_addr, strbuf,
504 sizeof(strbuf)), strerror(errno));
mridge949c5b12006-01-03 23:01:28 +0000505 return -1;
506 }
507 if (psin6_arg) {
508 *psin6_arg = *psin6;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800509 psin6_arg->sin6_scope_id =
510 if_nametoindex(pifa->ifa_name);
mridge949c5b12006-01-03 23:01:28 +0000511 }
512 return s;
513 }
514 {
515 char *scopestr, *intfstr;
516
517 switch (scope) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800518 case IPV6_ADDR_NODE:
519 scopestr = " node-local";
520 break;
521 case IPV6_ADDR_LINK:
522 scopestr = " link-local";
523 break;
524 case IPV6_ADDR_GLOBAL:
525 scopestr = " global";
526 break;
mridge949c5b12006-01-03 23:01:28 +0000527 default:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800528 scopestr = "";
529 break;
mridge949c5b12006-01-03 23:01:28 +0000530 }
531 if (ifindex < 0) {
532 intfstr = " not on ifindex";
533 ifindex = -ifindex;
534 } else if (ifindex)
535 intfstr = " on ifindex";
536 else
537 intfstr = 0;
Garrett Cooper2c282152010-12-16 00:55:50 -0800538
mridge949c5b12006-01-03 23:01:28 +0000539 if (intfstr)
540 tst_resm(TBROK, "%s: getsock : no%s addresses%s %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800541 tname, scopestr, intfstr, ifindex);
mridge949c5b12006-01-03 23:01:28 +0000542 else
543 tst_resm(TBROK, "%s: getsock : no%s addresses",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800544 tname, scopestr);
mridge949c5b12006-01-03 23:01:28 +0000545 }
546 return -1;
subrata_modak52568192008-12-12 13:43:40 +0000547#else /* HAVE_IFADDRS_H */
548 return -1;
549#endif
mridge949c5b12006-01-03 23:01:28 +0000550}
551
552#ifdef notyet
553/*
554 * RFC 3542 IPV6_PKTINFO not in mainline yet (as of 2.6.15). The get/set
555 * tests are below, and comments for some further tests to be added later
556 */
557void test_pktinfo(void)
558{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800559 int s_snd, s_rcv[3] = { -1, -1, -1 };
560 struct sockaddr_in6 sa_rcv[3];
mridge949c5b12006-01-03 23:01:28 +0000561 int s, i;
562 struct ifaddrs *pifa_head, *pifa;
563 struct sockaddr_in6 *psin6;
564 char strbuf[128];
565 char *tname = "IPV6_PKTINFO";
Wanlong Gao354ebb42012-12-07 10:10:04 +0800566 struct in6_pktinfo pi, pi_tmp;
mridge949c5b12006-01-03 23:01:28 +0000567 int sinlen;
568 int optlen;
569
570 s_snd = getsock(tname, 0, IPV6_ADDR_GLOBAL);
571 if (s_snd < 0) {
572 tst_resm(TBROK, "%s: can't create send socket", tname);
573 return;
574 }
575 /* global-scope address, interface X */
576 sa_rcv[0].sin6_scope_id = 0;
577 s_rcv[0] = getsock(tname, &sa_rcv[0], IPV6_ADDR_GLOBAL);
578 if (s_rcv[0] == -1) {
579 tst_resm(TBROK, "%s: only link-scope addresses", tname);
580 return;
581 }
582 /* link-local-scope address, interface X */
583 sa_rcv[1].sin6_scope_id = sa_rcv[0].sin6_scope_id;
584 s_rcv[1] = getsock(tname, &sa_rcv[1], IPV6_ADDR_LINK);
585 if (s_rcv[1] < 0) {
586 tst_resm(TBROK, "%s: no link-local address on ifindex %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800587 tname, sa_rcv[0].sin6_scope_id);
mridge949c5b12006-01-03 23:01:28 +0000588 return;
589 }
590 /* link-local-scope address, interface Y */
591 sa_rcv[2].sin6_scope_id = -sa_rcv[0].sin6_scope_id;
592 s_rcv[2] = getsock(tname, &sa_rcv[2], IPV6_ADDR_LINK);
593 if (s_rcv[2] < 0) {
594 tst_resm(TBROK, "%s: only one interface?", tname);
595 return;
596 }
597 /* send to rcv1 to verify communication */
598 /* force to rcv2 w/ PKTINFO */
599/* TESTS: */
600/* sticky set-get */
601 tname = "IPV6_PKTINFO set";
602 pi.ipi6_addr = sa_rcv[1].sin6_addr;
603 pi.ipi6_ifindex = sa_rcv[1].sin6_scope_id;
604 TEST(setsockopt(s_snd, SOL_IPV6, IPV6_PKTINFO, &pi, sizeof(pi)));
605 if (TEST_RETURN != 0)
606 tst_resm(TFAIL, "%s: %s", tname, strerror(errno));
607 else
608 tst_resm(TPASS, "%s", tname);
609
610 tname = "IPV6_PKTINFO get";
611 optlen = sizeof(pi_tmp);
612 TEST(getsockopt(s_snd, SOL_IPV6, IPV6_PKTINFO, &pi_tmp, &optlen));
613 if (TEST_RETURN != 0)
614 tst_resm(TFAIL, "%s: %s", tname, strerror(errno));
615 else if (memcmp(&pi, &pi_tmp, sizeof(pi)) != 0) {
616 char strbuf2[64];
617 tst_resm(TFAIL, "%s: {\"%s\",%d} != {\"%s\",%d}", tname,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800618 inet_ntop(AF_INET6, &pi_tmp.ipi6_addr, strbuf,
619 sizeof(strbuf)), pi_tmp.ipi6_ifindex,
620 inet_ntop(AF_INET6, &pi.ipi6_addr, strbuf2,
621 sizeof(strbuf2)), pi.ipi6_ifindex);
mridge949c5b12006-01-03 23:01:28 +0000622 } else
623 tst_resm(TPASS, "%s", tname);
624/* ancillary data override */
625/* link-local, wrong interface */
626 tname = "IPV6_PKTINFO invalid {lladdr, intf}";
627 pi.ipi6_addr = sa_rcv[1].sin6_addr;
628 pi.ipi6_ifindex = sa_rcv[2].sin6_scope_id;
629 TEST(setsockopt(s_snd, SOL_IPV6, IPV6_PKTINFO, &pi, sizeof(pi)));
630 if (TEST_RETURN == 0)
631 tst_resm(TFAIL, "%s returns success, should be -1, EINVAL",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800632 tname);
mridge949c5b12006-01-03 23:01:28 +0000633 else if (TEST_ERRNO != EINVAL)
634 tst_resm(TFAIL, "%s errno %d != %d", tname, TEST_ERRNO, EINVAL);
635 else
636 tst_resm(TPASS, "%s", tname);
637/* nonexistent interface */
638/* non-local address */
639/* clear address */
640/* clear interface */
641/* sendmsg() sin6_scope differs with ancillary data interface */
642}
643#endif /* notyet */
644
Wanlong Gao354ebb42012-12-07 10:10:04 +0800645void do_tests(void)
mridge949c5b12006-01-03 23:01:28 +0000646{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800647 int i;
mridge949c5b12006-01-03 23:01:28 +0000648
Wanlong Gao354ebb42012-12-07 10:10:04 +0800649 for (i = 0; i < SOCOUNT; ++i) {
subrata_modak005dc012008-12-12 13:39:59 +0000650 sotab[i].so_clrval.sou_bool = 0;
651 sotab[i].so_setval.sou_bool = 1;
mridge949c5b12006-01-03 23:01:28 +0000652 so_test(&sotab[i]);
653 }
654#ifdef notyet
655 test_pktinfo();
656#endif /* notyet - see test_pktinfo() comment above */
657}
658
Wanlong Gao354ebb42012-12-07 10:10:04 +0800659void setup(void)
mridge949c5b12006-01-03 23:01:28 +0000660{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800661 TEST_PAUSE; /* if -P option specified */
mridge949c5b12006-01-03 23:01:28 +0000662}
663
Wanlong Gao354ebb42012-12-07 10:10:04 +0800664void cleanup(void)
mridge949c5b12006-01-03 23:01:28 +0000665{
Markos Chandrasc0762b82012-01-03 13:23:39 +0000666}