1 /*-
2 * Copyright (c) 2007 Michael Telahun Makonnen
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30
31 #include <netinet/in.h>
32 #include <netinet/ip6.h>
33
34 #include <netdb.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "test_subr.h"
40
41 static void init_hdrs(struct msghdr *, struct cmsghdr *, char *, size_t);
42 static void test_cmsg_firsthdr();
43 static void test_cmsg_nexthdr();
44 static void test_rth_space();
45 static void test_rth_segments();
46 static void test_rth_add();
47 static void test_rth_init();
48
49 int
main(int argc,char * argv[])50 main(int argc, char* argv[])
51 {
52 /*
53 * Initialize global variables.
54 */
55 g_total = 0;
56 g_pass = 0;
57 g_fail = 0;
58 memset(g_funcname, 0, sizeof(g_funcname));
59
60 /*
61 * Start the tests.
62 */
63 printf("Starting inet6_rth_* and cmsg macro regression tests...\n");
64
65 test_cmsg_firsthdr(); /* CMSG_FIRSTHDR */
66 test_cmsg_nexthdr(); /* CMSG_NEXTHDR */
67 test_rth_space(); /* inet6_rth_space */
68 test_rth_segments(); /* inet6_rth_segments */
69 test_rth_add(); /* inet6_rth_add */
70 test_rth_init(); /* inet6_rth_space */
71
72 if (g_fail == 0)
73 printf("OK. ");
74 else
75 printf("NOT OK. ");
76 printf("Total: %d Pass: %d Fail: %d\n", g_total, g_pass, g_fail);
77
78 return (g_fail);
79 }
80
81 void
test_rth_init()82 test_rth_init()
83 {
84 char buf[10240];
85 char *pbuf;
86
87 set_funcname("test_rth_init", sizeof("test_rth_init\0"));
88
89 pbuf = inet6_rth_init((void *)buf, 10, IPV6_RTHDR_TYPE_0, 100);
90 checkptr(NULL, pbuf, "buffer too small\0");
91
92 pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0);
93 checkptr((caddr_t)&buf, pbuf, "0 segments\0");
94
95 pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127);
96 checkptr((caddr_t)&buf, pbuf, "127 segments\0");
97
98 pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, -1);
99 checkptr(NULL, pbuf, "negative number of segments\0");
100
101 pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 128);
102 checkptr(NULL, pbuf, "128 segments\0");
103 }
104
105 void
test_rth_add()106 test_rth_add()
107 {
108 int i, ret;
109 char buf[10240];
110 struct addrinfo *res;
111 struct addrinfo hints;
112
113 set_funcname("test_rth_add", sizeof("test_rth_add\0"));
114
115 if (NULL == inet6_rth_init(buf, 10240, IPV6_RTHDR_TYPE_0, 127))
116 abort();
117 memset((void *)&hints, 0, sizeof(struct addrinfo));
118 hints.ai_family = AF_INET6;
119 hints.ai_flags = AI_NUMERICHOST;
120 if (0 != getaddrinfo("::1", NULL, (const struct addrinfo *)&hints, &res))
121 abort();
122 for (i = 0; i < 127; i++)
123 inet6_rth_add((void *)buf,
124 &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
125 checknum(127, ((struct ip6_rthdr0 *)buf)->ip6r0_segleft, 0,
126 "add 127 segments\0");
127
128 ret = inet6_rth_add((void *)buf,
129 &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
130 checknum(-1, ret, 0, "add 128th segment to 127 segment header\0");
131
132 freeaddrinfo(res);
133 }
134
135 void
test_rth_segments()136 test_rth_segments()
137 {
138 int seg;
139 char buf[10240];
140
141 set_funcname("test_rth_segments", sizeof("test_rth_segments\0"));
142
143 /*
144 * Test: invalid routing header type.
145 */
146 if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
147 abort();
148 ((struct ip6_rthdr *)buf)->ip6r_type = ~IPV6_RTHDR_TYPE_0;
149 seg = inet6_rth_segments((const void *)buf);
150 checknum(-1, seg, 0, "invalid routing header type\0");
151
152 /*
153 * Test: 0 segments.
154 */
155 if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
156 abort();
157 seg = inet6_rth_segments((const void *)buf);
158 checknum(0, seg, 0, "0 segments\0");
159
160 /*
161 * Test: 127 segments.
162 */
163 if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
164 abort();
165 seg = inet6_rth_segments((const void *)buf);
166 checknum(127, seg, 0, "127 segments\0");
167
168 /*
169 * Test: -1 segments.
170 */
171 /*
172 if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
173 abort();
174 ((struct ip6_rthdr0 *)buf)->ip6r0_len = -1 * 2;
175 seg = inet6_rth_segments((const void *)buf);
176 checknum(-1, seg, 0, "-1 segments\0");
177 */
178 /*
179 * Test: 128 segments.
180 */
181 /*
182 if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
183 abort();
184 ((struct ip6_rthdr0 *)buf)->ip6r0_len = 128 * 2;
185 seg = inet6_rth_segments((const void *)buf);
186 checknum(-1, seg, 0, "128 segments\0");
187 */
188 }
189
190 void
test_rth_space()191 test_rth_space()
192 {
193 socklen_t len;
194
195 set_funcname("test_rth_space", sizeof("test_rth_space\0"));
196
197 /*
198 * Test: invalid routing header type.
199 */
200 len = inet6_rth_space(~IPV6_RTHDR_TYPE_0, 0);
201 checknum(0, len, 0, "invalid routing header type\0");
202
203 /*
204 * Test: valid number of segments.
205 */
206 len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
207 checknum(0, len, 1, "0 segments\0");
208 len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 127);
209 checknum(0, len, 1, "0 segments\0");
210
211 /*
212 * Test: invalid number of segments.
213 */
214 len = inet6_rth_space(IPV6_RTHDR_TYPE_0, -1);
215 checknum(0, len, 0, "-1 segments\0");
216 len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 128);
217 checknum(0, len, 0, "128 segments\0");
218 }
219
220 void
test_cmsg_nexthdr()221 test_cmsg_nexthdr()
222 {
223 struct msghdr mh;
224 struct cmsghdr cmh;
225 struct cmsghdr *cmhp, *cmhnextp;
226 char ancbuf[10240];
227 char magic[] = "MAGIC";
228
229 set_funcname("test_cmsg_nexthdr", sizeof("test_cmsg_nexthdr"));
230
231 /*
232 * Test: More than one cmsghdr
233 */
234 init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
235 mh.msg_control = (caddr_t)ancbuf;
236 mh.msg_controllen = CMSG_SPACE(0) * 2; /* 2 cmsghdr with no data */
237 cmh.cmsg_len = CMSG_LEN(0);
238
239 /*
240 * Copy the same instance of cmsghdr twice. Use a magic value
241 * to id the second copy.
242 */
243 bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
244 strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
245 bcopy((void *)&cmh,
246 (void *)((caddr_t)ancbuf + CMSG_SPACE(0)),
247 sizeof(cmh));
248 cmhp = CMSG_FIRSTHDR(&mh);
249 cmhnextp = CMSG_NXTHDR(&mh, cmhp);
250 checkstr((const char *)&magic, (const char *)cmhnextp, sizeof(magic),
251 "more than one cmsghdr\0");
252
253 /*
254 * Test: only one cmsghdr
255 */
256 init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
257 mh.msg_control = (caddr_t)ancbuf;
258 mh.msg_controllen = CMSG_SPACE(0);
259 cmh.cmsg_len = CMSG_LEN(0);
260 bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
261 cmhp = CMSG_FIRSTHDR(&mh);
262 cmhnextp = CMSG_NXTHDR(&mh, cmhp);
263 checkptr(NULL, (caddr_t)cmhnextp, "only one cmsghdr\0");
264
265 /*
266 * Test: NULL cmsg pointer
267 */
268 init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
269 mh.msg_control = (caddr_t)ancbuf;
270 mh.msg_controllen = sizeof(ancbuf);
271 cmh.cmsg_len = sizeof(ancbuf);
272 bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
273 cmhp = CMSG_FIRSTHDR(&mh);
274 cmhnextp = CMSG_NXTHDR(&mh, NULL);
275 checkptr((caddr_t)cmhp, (caddr_t)cmhnextp, "null second argument\0");
276 }
277
278 void
test_cmsg_firsthdr()279 test_cmsg_firsthdr()
280 {
281 struct msghdr mh;
282 struct cmsghdr cmh;
283 struct cmsghdr *cmhp;
284 char ancbuf[1024];
285 char magic[] = "MAGIC";
286
287 set_funcname("test_cmsg_firsthdr", sizeof("test_cmsg_firsthdr"));
288
289 /* CMSG_FIRSTHDR() where msg_control is NULL */
290 init_hdrs(&mh, NULL, NULL, 0);
291 mh.msg_control = NULL;
292 cmhp = CMSG_FIRSTHDR(&mh);
293 checkptr(NULL, (caddr_t)cmhp,
294 "msg_control is NULL\0");
295
296 /* - where msg_controllen < sizeof cmsghdr */
297 init_hdrs(&mh, NULL, NULL, 0);
298 mh.msg_control = (caddr_t)&cmh;
299 mh.msg_controllen = sizeof(cmh) - 1;
300 cmhp = CMSG_FIRSTHDR(&mh);
301 checkptr(NULL, (caddr_t)cmhp,
302 "msg_controllen < sizeof cmsghdr\0");
303
304 /* - where msg_controllen == 0 */
305 init_hdrs(&mh, NULL, NULL, 0);
306 mh.msg_control = (caddr_t)&cmh;
307 mh.msg_controllen = 0;
308 cmhp = CMSG_FIRSTHDR(&mh);
309 checkptr(NULL, (caddr_t)cmhp,
310 "msg_controllen == 0\0");
311
312 /* no errors */
313 init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
314 memset((void *)ancbuf, 0, sizeof(ancbuf));
315 mh.msg_control = (caddr_t)ancbuf;
316 mh.msg_controllen = sizeof(ancbuf);
317 strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
318 bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
319 cmhp = CMSG_FIRSTHDR(&mh);
320 checkstr((const char *)&magic, (const char *)cmhp, sizeof(magic),
321 "with payload\0");
322 }
323
324 void
init_hdrs(struct msghdr * mhp,struct cmsghdr * cmhp,char * bufp,size_t bufsize)325 init_hdrs(struct msghdr *mhp, struct cmsghdr *cmhp, char *bufp, size_t bufsize)
326 {
327 if (mhp != NULL)
328 memset((void *)mhp, 0, sizeof(struct msghdr));
329 if (cmhp != NULL)
330 memset((void *)cmhp, 0, sizeof(struct cmsghdr));
331 if (bufp != NULL)
332 memset((void *)bufp, 0, bufsize);
333 }
334