]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/netinet6/inet6_rth/inet6_rth-segments.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / regression / netinet6 / inet6_rth / inet6_rth-segments.c
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/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/types.h>
32 #include <sys/socket.h>
33
34 #include <netinet/in.h>
35 #include <netinet/ip6.h>
36
37 #include <netdb.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "test_subr.h"
43
44 static void init_hdrs(struct msghdr *, struct cmsghdr *, char *, size_t);
45 static void test_cmsg_firsthdr();
46 static void test_cmsg_nexthdr();
47 static void test_rth_space();
48 static void test_rth_segments();
49 static void test_rth_add();
50 static void test_rth_init();
51
52 int
53 main(int argc, char* argv[])
54 {
55         /*
56          * Initialize global variables.
57          */
58         g_total = 0;
59         g_pass = 0;
60         g_fail = 0;
61         memset(g_funcname, 0, sizeof(g_funcname));
62
63         /*
64          * Start the tests.
65          */
66         printf("Starting inet6_rth_* and cmsg macro regression tests...\n");
67
68         test_cmsg_firsthdr();                   /* CMSG_FIRSTHDR    */
69         test_cmsg_nexthdr();                    /* CMSG_NEXTHDR     */
70         test_rth_space();                       /* inet6_rth_space  */
71         test_rth_segments();                    /* inet6_rth_segments */
72         test_rth_add();                         /* inet6_rth_add    */
73         test_rth_init();                        /* inet6_rth_space  */
74
75         if (g_fail == 0)
76                 printf("OK. ");
77         else
78                 printf("NOT OK. ");
79         printf("Total: %d  Pass: %d  Fail: %d\n", g_total, g_pass, g_fail);
80
81         return (g_fail);
82 }
83
84 void
85 test_rth_init()
86 {
87         char buf[10240];
88         char *pbuf;
89
90         set_funcname("test_rth_init", sizeof("test_rth_init\0"));
91
92         pbuf = inet6_rth_init((void *)buf, 10, IPV6_RTHDR_TYPE_0, 100);
93         checkptr(NULL, pbuf, "buffer too small\0");
94
95         pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0);
96         checkptr((caddr_t)&buf, pbuf, "0 segments\0");
97
98         pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127);
99         checkptr((caddr_t)&buf, pbuf, "127 segments\0");
100
101         pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, -1);
102         checkptr(NULL, pbuf, "negative number of segments\0");
103
104         pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 128);
105         checkptr(NULL, pbuf, "128 segments\0");
106 }
107
108 void
109 test_rth_add()
110 {
111         int     i, ret;
112         char    buf[10240];
113         struct addrinfo *res;
114         struct addrinfo hints;
115
116         set_funcname("test_rth_add", sizeof("test_rth_add\0"));
117
118         if (NULL == inet6_rth_init(buf, 10240, IPV6_RTHDR_TYPE_0, 127))
119                 abort();
120         memset((void *)&hints, 0, sizeof(struct addrinfo));
121         hints.ai_family = AF_INET6;
122         hints.ai_flags = AI_NUMERICHOST;
123         if (0 != getaddrinfo("::1", NULL, (const struct addrinfo *)&hints, &res))
124                 abort();
125         for (i = 0; i < 127; i++)
126                 inet6_rth_add((void *)buf,
127                     &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
128         checknum(127, ((struct ip6_rthdr0 *)buf)->ip6r0_segleft, 0,
129             "add 127 segments\0");
130
131         ret = inet6_rth_add((void *)buf,
132             &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr);
133         checknum(-1, ret, 0, "add 128th segment to 127 segment header\0");
134
135         freeaddrinfo(res);
136 }
137
138 void
139 test_rth_segments()
140 {
141         int     seg;
142         char    buf[10240];
143
144         set_funcname("test_rth_segments", sizeof("test_rth_segments\0"));
145
146         /*
147          * Test: invalid routing header type.
148          */
149         if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
150                 abort();
151         ((struct ip6_rthdr *)buf)->ip6r_type = ~IPV6_RTHDR_TYPE_0;
152         seg = inet6_rth_segments((const void *)buf);
153         checknum(-1, seg, 0, "invalid routing header type\0");
154
155         /*
156          * Test: 0 segments.
157          */
158         if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
159                 abort();
160         seg = inet6_rth_segments((const void *)buf);
161         checknum(0, seg, 0, "0 segments\0");
162
163         /*
164          * Test: 127 segments.
165          */
166         if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
167                 abort();
168         seg = inet6_rth_segments((const void *)buf);
169         checknum(127, seg, 0, "127 segments\0");
170
171         /*
172          * Test: -1 segments.
173          */
174 /*
175         if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0))
176                 abort();
177         ((struct ip6_rthdr0 *)buf)->ip6r0_len = -1 * 2;
178         seg = inet6_rth_segments((const void *)buf);
179         checknum(-1, seg, 0, "-1 segments\0");
180 */
181         /*
182          * Test: 128 segments.
183          */
184 /*
185         if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127))
186                 abort();
187         ((struct ip6_rthdr0 *)buf)->ip6r0_len = 128 * 2;
188         seg = inet6_rth_segments((const void *)buf);
189         checknum(-1, seg, 0, "128 segments\0");
190 */
191 }
192
193 void
194 test_rth_space()
195 {
196         socklen_t len;
197
198         set_funcname("test_rth_space", sizeof("test_rth_space\0"));
199
200         /*
201          * Test: invalid routing header type.
202          */
203         len = inet6_rth_space(~IPV6_RTHDR_TYPE_0, 0);
204         checknum(0, len, 0, "invalid routing header type\0");
205
206         /*
207          * Test: valid number of segments.
208          */
209         len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
210         checknum(0, len, 1, "0 segments\0");
211         len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 127);
212         checknum(0, len, 1, "0 segments\0");
213
214         /*
215          * Test: invalid number of segments.
216          */
217         len = inet6_rth_space(IPV6_RTHDR_TYPE_0, -1);
218         checknum(0, len, 0, "-1 segments\0");
219         len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 128);
220         checknum(0, len, 0, "128 segments\0");
221 }
222
223 void
224 test_cmsg_nexthdr()
225 {
226         struct msghdr  mh;
227         struct cmsghdr cmh;
228         struct cmsghdr *cmhp, *cmhnextp;
229         char ancbuf[10240];
230         char magic[] = "MAGIC";
231
232         set_funcname("test_cmsg_nexthdr", sizeof("test_cmsg_nexthdr"));
233
234         /*
235          * Test: More than one cmsghdr
236          */
237         init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
238         mh.msg_control = (caddr_t)ancbuf;
239         mh.msg_controllen  = CMSG_SPACE(0) * 2; /* 2 cmsghdr with no data */
240         cmh.cmsg_len = CMSG_LEN(0);
241
242         /* 
243          * Copy the same instance of cmsghdr twice. Use a magic value
244          * to id the second copy.
245          */
246         bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
247         strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
248         bcopy((void *)&cmh,
249             (void *)((caddr_t)ancbuf + CMSG_SPACE(0)),
250             sizeof(cmh));
251         cmhp = CMSG_FIRSTHDR(&mh);
252         cmhnextp = CMSG_NXTHDR(&mh, cmhp);
253         checkstr((const char *)&magic, (const char *)cmhnextp, sizeof(magic),
254             "more than one cmsghdr\0");
255
256         /*
257          * Test: only one cmsghdr
258          */
259         init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
260         mh.msg_control = (caddr_t)ancbuf;
261         mh.msg_controllen  = CMSG_SPACE(0);
262         cmh.cmsg_len = CMSG_LEN(0);
263         bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
264         cmhp = CMSG_FIRSTHDR(&mh);
265         cmhnextp = CMSG_NXTHDR(&mh, cmhp);
266         checkptr(NULL, (caddr_t)cmhnextp, "only one cmsghdr\0");
267
268         /*
269          * Test: NULL cmsg pointer
270          */
271         init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
272         mh.msg_control = (caddr_t)ancbuf;
273         mh.msg_controllen  = sizeof(ancbuf);
274         cmh.cmsg_len = sizeof(ancbuf);
275         bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
276         cmhp = CMSG_FIRSTHDR(&mh);
277         cmhnextp = CMSG_NXTHDR(&mh, NULL);
278         checkptr((caddr_t)cmhp, (caddr_t)cmhnextp, "null second argument\0");
279 }
280
281 void
282 test_cmsg_firsthdr()
283 {
284         struct msghdr  mh;
285         struct cmsghdr cmh;
286         struct cmsghdr *cmhp;
287         char ancbuf[1024];
288         char magic[] = "MAGIC";
289
290         set_funcname("test_cmsg_firsthdr", sizeof("test_cmsg_firsthdr"));
291
292         /* CMSG_FIRSTHDR() where msg_control is NULL */
293         init_hdrs(&mh, NULL, NULL, 0);
294         mh.msg_control = NULL;
295         cmhp = CMSG_FIRSTHDR(&mh);
296         checkptr(NULL, (caddr_t)cmhp,
297             "msg_control is NULL\0");
298
299         /* - where msg_controllen < sizeof cmsghdr */
300         init_hdrs(&mh, NULL, NULL, 0);
301         mh.msg_control = (caddr_t)&cmh;
302         mh.msg_controllen = sizeof(cmh) - 1;
303         cmhp = CMSG_FIRSTHDR(&mh);
304         checkptr(NULL, (caddr_t)cmhp,
305             "msg_controllen < sizeof cmsghdr\0");
306
307         /* - where msg_controllen == 0 */
308         init_hdrs(&mh, NULL, NULL, 0);
309         mh.msg_control = (caddr_t)&cmh;
310         mh.msg_controllen = 0;
311         cmhp = CMSG_FIRSTHDR(&mh);
312         checkptr(NULL, (caddr_t)cmhp,
313             "msg_controllen == 0\0");
314
315         /* no errors */
316         init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf));
317         memset((void *)ancbuf, 0, sizeof(ancbuf));
318         mh.msg_control = (caddr_t)ancbuf;
319         mh.msg_controllen  = sizeof(ancbuf);
320         strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic));
321         bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh));
322         cmhp = CMSG_FIRSTHDR(&mh);
323         checkstr((const char *)&magic, (const char *)cmhp, sizeof(magic),
324             "with payload\0");
325 }
326
327 void
328 init_hdrs(struct msghdr *mhp, struct cmsghdr *cmhp, char *bufp, size_t bufsize)
329 {
330         if (mhp != NULL)
331                 memset((void *)mhp, 0, sizeof(struct msghdr));
332         if (cmhp != NULL)
333                 memset((void *)cmhp, 0, sizeof(struct cmsghdr));
334         if (bufp != NULL)
335                 memset((void *)bufp, 0, bufsize);
336 }