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