1168925Smtm/*-
2168925Smtm * Copyright (c) 2007 Michael Telahun Makonnen
3168925Smtm * All rights reserved.
4168925Smtm *
5168925Smtm * Redistribution and use in source and binary forms, with or without
6168925Smtm * modification, are permitted provided that the following conditions
7168925Smtm * are met:
8168925Smtm * 1. Redistributions of source code must retain the above copyright
9168925Smtm *    notice, this list of conditions and the following disclaimer.
10168925Smtm * 2. Redistributions in binary form must reproduce the above copyright
11168925Smtm *    notice, this list of conditions and the following disclaimer in the
12168925Smtm *    documentation and/or other materials provided with the distribution.
13168925Smtm *
14168925Smtm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15168925Smtm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16168925Smtm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17168925Smtm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18168925Smtm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19168925Smtm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20168925Smtm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21168925Smtm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22168925Smtm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23168925Smtm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24168925Smtm * SUCH DAMAGE.
25168925Smtm *
26168925Smtm */
27168925Smtm
28168925Smtm#include <sys/cdefs.h>
29168925Smtm__FBSDID("$FreeBSD$");
30168925Smtm
31168925Smtm#include <sys/types.h>
32168925Smtm#include <sys/socket.h>
33168925Smtm
34168925Smtm#include <netinet/in.h>
35168925Smtm#include <netinet/ip6.h>
36168925Smtm
37168925Smtm#include <netdb.h>
38168925Smtm#include <stdio.h>
39168925Smtm#include <stdlib.h>
40168925Smtm#include <string.h>
41168925Smtm
42168925Smtm#include "test_subr.h"
43168925Smtm
44168925Smtmstatic void init_hdrs(struct msghdr *, struct cmsghdr *, char *, size_t);
45168925Smtmstatic void test_cmsg_firsthdr();
46168925Smtmstatic void test_cmsg_nexthdr();
47168925Smtmstatic void test_rth_space();
48168925Smtmstatic void test_rth_segments();
49168925Smtmstatic void test_rth_add();
50168925Smtmstatic void test_rth_init();
51168925Smtm
52168925Smtmint
53168925Smtmmain(int argc, char* argv[])
54168925Smtm{
55168925Smtm	/*
56168925Smtm	 * Initialize global variables.
57168925Smtm	 */
58168925Smtm	g_total = 0;
59168925Smtm	g_pass = 0;
60168925Smtm	g_fail = 0;
61168925Smtm	memset(g_funcname, 0, sizeof(g_funcname));
62168925Smtm
63168925Smtm	/*
64168925Smtm	 * Start the tests.
65168925Smtm	 */
66168925Smtm	printf("Starting inet6_rth_* and cmsg macro regression tests...\n");
67168925Smtm
68168925Smtm	test_cmsg_firsthdr();			/* CMSG_FIRSTHDR    */
69168925Smtm	test_cmsg_nexthdr();			/* CMSG_NEXTHDR	    */
70168925Smtm	test_rth_space();			/* inet6_rth_space  */
71168925Smtm	test_rth_segments();			/* inet6_rth_segments */
72168925Smtm	test_rth_add();				/* inet6_rth_add    */
73168925Smtm	test_rth_init();			/* inet6_rth_space  */
74168925Smtm
75168925Smtm	if (g_fail == 0)
76168925Smtm		printf("OK. ");
77168925Smtm	else
78168925Smtm		printf("NOT OK. ");
79168925Smtm	printf("Total: %d  Pass: %d  Fail: %d\n", g_total, g_pass, g_fail);
80168925Smtm
81168925Smtm	return (g_fail);
82168925Smtm}
83168925Smtm
84168925Smtmvoid
85168925Smtmtest_rth_init()
86168925Smtm{
87168925Smtm	char buf[10240];
88168925Smtm	char *pbuf;
89168925Smtm
90168925Smtm	set_funcname("test_rth_init", sizeof("test_rth_init\0"));
91168925Smtm
92168925Smtm	pbuf = inet6_rth_init((void *)buf, 10, IPV6_RTHDR_TYPE_0, 100);
93168925Smtm	checkptr(NULL, pbuf, "buffer too small\0");
94168925Smtm
95168925Smtm	pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0);
96168925Smtm	checkptr((caddr_t)&buf, pbuf, "0 segments\0");
97168925Smtm
98168925Smtm	pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127);
99168925Smtm	checkptr((caddr_t)&buf, pbuf, "127 segments\0");
100168925Smtm
101168925Smtm	pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, -1);
102168925Smtm	checkptr(NULL, pbuf, "negative number of segments\0");
103168925Smtm
104168925Smtm	pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 128);
105168925Smtm	checkptr(NULL, pbuf, "128 segments\0");
106168925Smtm}
107168925Smtm
108168925Smtmvoid
109168925Smtmtest_rth_add()
110168925Smtm{
111168925Smtm	int	i, ret;
112168925Smtm	char	buf[10240];
113168925Smtm	struct addrinfo *res;
114168925Smtm	struct addrinfo hints;
115168925Smtm
116168925Smtm	set_funcname("test_rth_add", sizeof("test_rth_add\0"));
117168925Smtm
118168925Smtm	if (NULL == inet6_rth_init(buf, 10240, IPV6_RTHDR_TYPE_0, 127))
119168925Smtm		abort();
120168925Smtm	memset((void *)&hints, 0, sizeof(struct addrinfo));
121168925Smtm	hints.ai_family = AF_INET6;
122168925Smtm	hints.ai_flags = AI_NUMERICHOST;
123168925Smtm	if (0 != getaddrinfo("::1", NULL, (const struct addrinfo *)&hints, &res))
124168925Smtm		abort();
125168925Smtm	for (i = 0; i < 127; i++)
126168925Smtm		inet6_rth_add((void *)buf,
127168925Smtm		    &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
128168925Smtm	checknum(127, ((struct ip6_rthdr0 *)buf)->ip6r0_segleft, 0,
129168925Smtm	    "add 127 segments\0");
130168925Smtm
131168925Smtm	ret = inet6_rth_add((void *)buf,
132168925Smtm	    &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
133168925Smtm	checknum(-1, ret, 0, "add 128th segment to 127 segment header\0");
134168925Smtm
135168925Smtm	freeaddrinfo(res);
136168925Smtm}
137168925Smtm
138168925Smtmvoid
139168925Smtmtest_rth_segments()
140168925Smtm{
141168925Smtm	int	seg;
142168925Smtm	char	buf[10240];
143168925Smtm
144168925Smtm	set_funcname("test_rth_segments", sizeof("test_rth_segments\0"));
145168925Smtm
146168925Smtm	/*
147168925Smtm	 * Test: invalid routing header type.
148168925Smtm	 */
149168925Smtm	if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
150168925Smtm		abort();
151168925Smtm	((struct ip6_rthdr *)buf)->ip6r_type = ~IPV6_RTHDR_TYPE_0;
152168925Smtm	seg = inet6_rth_segments((const void *)buf);
153168925Smtm	checknum(-1, seg, 0, "invalid routing header type\0");
154168925Smtm
155168925Smtm	/*
156168925Smtm	 * Test: 0 segments.
157168925Smtm	 */
158168925Smtm	if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
159168925Smtm		abort();
160168925Smtm	seg = inet6_rth_segments((const void *)buf);
161168925Smtm	checknum(0, seg, 0, "0 segments\0");
162168925Smtm
163168925Smtm	/*
164168925Smtm	 * Test: 127 segments.
165168925Smtm	 */
166168925Smtm	if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
167168925Smtm		abort();
168168925Smtm	seg = inet6_rth_segments((const void *)buf);
169168925Smtm	checknum(127, seg, 0, "127 segments\0");
170168925Smtm
171168925Smtm	/*
172168925Smtm	 * Test: -1 segments.
173168925Smtm	 */
174168925Smtm/*
175168925Smtm	if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
176168925Smtm		abort();
177168925Smtm	((struct ip6_rthdr0 *)buf)->ip6r0_len = -1 * 2;
178168925Smtm	seg = inet6_rth_segments((const void *)buf);
179168925Smtm	checknum(-1, seg, 0, "-1 segments\0");
180168925Smtm*/
181168925Smtm	/*
182168925Smtm	 * Test: 128 segments.
183168925Smtm	 */
184168925Smtm/*
185168925Smtm	if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
186168925Smtm		abort();
187168925Smtm	((struct ip6_rthdr0 *)buf)->ip6r0_len = 128 * 2;
188168925Smtm	seg = inet6_rth_segments((const void *)buf);
189168925Smtm	checknum(-1, seg, 0, "128 segments\0");
190168925Smtm*/
191168925Smtm}
192168925Smtm
193168925Smtmvoid
194168925Smtmtest_rth_space()
195168925Smtm{
196168925Smtm	socklen_t len;
197168925Smtm
198168925Smtm	set_funcname("test_rth_space", sizeof("test_rth_space\0"));
199168925Smtm
200168925Smtm	/*
201168925Smtm	 * Test: invalid routing header type.
202168925Smtm	 */
203168925Smtm	len = inet6_rth_space(~IPV6_RTHDR_TYPE_0, 0);
204168925Smtm	checknum(0, len, 0, "invalid routing header type\0");
205168925Smtm
206168925Smtm	/*
207168925Smtm	 * Test: valid number of segments.
208168925Smtm	 */
209168925Smtm	len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
210168925Smtm	checknum(0, len, 1, "0 segments\0");
211168925Smtm	len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 127);
212168925Smtm	checknum(0, len, 1, "0 segments\0");
213168925Smtm
214168925Smtm	/*
215168925Smtm	 * Test: invalid number of segments.
216168925Smtm	 */
217168925Smtm	len = inet6_rth_space(IPV6_RTHDR_TYPE_0, -1);
218168925Smtm	checknum(0, len, 0, "-1 segments\0");
219168925Smtm	len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 128);
220168925Smtm	checknum(0, len, 0, "128 segments\0");
221168925Smtm}
222168925Smtm
223168925Smtmvoid
224168925Smtmtest_cmsg_nexthdr()
225168925Smtm{
226168925Smtm	struct msghdr  mh;
227168925Smtm	struct cmsghdr cmh;
228168925Smtm	struct cmsghdr *cmhp, *cmhnextp;
229168925Smtm	char ancbuf[10240];
230168925Smtm	char magic[] = "MAGIC";
231168925Smtm
232168925Smtm	set_funcname("test_cmsg_nexthdr", sizeof("test_cmsg_nexthdr"));
233168925Smtm
234168925Smtm	/*
235168925Smtm	 * Test: More than one cmsghdr
236168925Smtm	 */
237168925Smtm	init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
238168925Smtm	mh.msg_control = (caddr_t)ancbuf;
239168925Smtm	mh.msg_controllen  = CMSG_SPACE(0) * 2;	/* 2 cmsghdr with no data */
240168925Smtm	cmh.cmsg_len = CMSG_LEN(0);
241168925Smtm
242168925Smtm	/*
243168925Smtm	 * Copy the same instance of cmsghdr twice. Use a magic value
244168925Smtm	 * to id the second copy.
245168925Smtm	 */
246168925Smtm	bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
247168925Smtm	strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
248168925Smtm	bcopy((void *)&cmh,
249168925Smtm	    (void *)((caddr_t)ancbuf + CMSG_SPACE(0)),
250168925Smtm	    sizeof(cmh));
251168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
252168925Smtm	cmhnextp = CMSG_NXTHDR(&mh, cmhp);
253168925Smtm	checkstr((const char *)&magic, (const char *)cmhnextp, sizeof(magic),
254168925Smtm	    "more than one cmsghdr\0");
255168925Smtm
256168925Smtm	/*
257168925Smtm	 * Test: only one cmsghdr
258168925Smtm	 */
259168925Smtm	init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
260168925Smtm	mh.msg_control = (caddr_t)ancbuf;
261168925Smtm	mh.msg_controllen  = CMSG_SPACE(0);
262168925Smtm	cmh.cmsg_len = CMSG_LEN(0);
263168925Smtm	bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
264168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
265168925Smtm	cmhnextp = CMSG_NXTHDR(&mh, cmhp);
266168925Smtm	checkptr(NULL, (caddr_t)cmhnextp, "only one cmsghdr\0");
267168925Smtm
268168925Smtm	/*
269168925Smtm	 * Test: NULL cmsg pointer
270168925Smtm	 */
271168925Smtm	init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
272168925Smtm	mh.msg_control = (caddr_t)ancbuf;
273168925Smtm	mh.msg_controllen  = sizeof(ancbuf);
274168925Smtm	cmh.cmsg_len = sizeof(ancbuf);
275168925Smtm	bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
276168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
277168925Smtm	cmhnextp = CMSG_NXTHDR(&mh, NULL);
278168925Smtm	checkptr((caddr_t)cmhp, (caddr_t)cmhnextp, "null second argument\0");
279168925Smtm}
280168925Smtm
281168925Smtmvoid
282168925Smtmtest_cmsg_firsthdr()
283168925Smtm{
284168925Smtm	struct msghdr  mh;
285168925Smtm	struct cmsghdr cmh;
286168925Smtm	struct cmsghdr *cmhp;
287168925Smtm	char ancbuf[1024];
288168925Smtm	char magic[] = "MAGIC";
289168925Smtm
290168925Smtm	set_funcname("test_cmsg_firsthdr", sizeof("test_cmsg_firsthdr"));
291168925Smtm
292168925Smtm	/* CMSG_FIRSTHDR() where msg_control is NULL */
293168925Smtm	init_hdrs(&mh, NULL, NULL, 0);
294168925Smtm	mh.msg_control = NULL;
295168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
296168925Smtm	checkptr(NULL, (caddr_t)cmhp,
297168925Smtm	    "msg_control is NULL\0");
298168925Smtm
299168925Smtm	/* - where msg_controllen < sizeof cmsghdr */
300168925Smtm	init_hdrs(&mh, NULL, NULL, 0);
301168925Smtm	mh.msg_control = (caddr_t)&cmh;
302168925Smtm	mh.msg_controllen = sizeof(cmh) - 1;
303168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
304168925Smtm	checkptr(NULL, (caddr_t)cmhp,
305168925Smtm	    "msg_controllen < sizeof cmsghdr\0");
306168925Smtm
307168925Smtm	/* - where msg_controllen == 0 */
308168925Smtm	init_hdrs(&mh, NULL, NULL, 0);
309168925Smtm	mh.msg_control = (caddr_t)&cmh;
310168925Smtm	mh.msg_controllen = 0;
311168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
312168925Smtm	checkptr(NULL, (caddr_t)cmhp,
313168925Smtm	    "msg_controllen == 0\0");
314168925Smtm
315168925Smtm	/* no errors */
316168925Smtm	init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
317168925Smtm	memset((void *)ancbuf, 0, sizeof(ancbuf));
318168925Smtm	mh.msg_control = (caddr_t)ancbuf;
319168925Smtm	mh.msg_controllen  = sizeof(ancbuf);
320168925Smtm	strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
321168925Smtm	bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
322168925Smtm	cmhp = CMSG_FIRSTHDR(&mh);
323168925Smtm	checkstr((const char *)&magic, (const char *)cmhp, sizeof(magic),
324168925Smtm	    "with payload\0");
325168925Smtm}
326168925Smtm
327168925Smtmvoid
328168925Smtminit_hdrs(struct msghdr *mhp, struct cmsghdr *cmhp, char *bufp, size_t bufsize)
329168925Smtm{
330168925Smtm	if (mhp != NULL)
331168925Smtm		memset((void *)mhp, 0, sizeof(struct msghdr));
332168925Smtm	if (cmhp != NULL)
333168925Smtm		memset((void *)cmhp, 0, sizeof(struct cmsghdr));
334168925Smtm	if (bufp != NULL)
335168925Smtm		memset((void *)bufp, 0, bufsize);
336168925Smtm}
337