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 } 337