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