#include #include #include #include #include #define OPT_X 42 #define OPT_Y 43 #define OPT_Z 44 static void * encode_inet6_opt (socklen_t *elp) { void *eb = NULL; socklen_t el; int cl; void *db; int offset; uint8_t val1; uint16_t val2; uint32_t val4; uint64_t val8; *elp = 0; #define CHECK() \ if (cl == -1) \ { \ printf ("cl == -1 on line %d\n", __LINE__); \ free (eb); \ return NULL; \ } /* Estimate the length */ cl = inet6_opt_init (NULL, 0); CHECK (); cl = inet6_opt_append (NULL, 0, cl, OPT_X, 12, 8, NULL); CHECK (); cl = inet6_opt_append (NULL, 0, cl, OPT_Y, 7, 4, NULL); CHECK (); cl = inet6_opt_append (NULL, 0, cl, OPT_Z, 7, 1, NULL); CHECK (); cl = inet6_opt_finish (NULL, 0, cl); CHECK (); el = cl; eb = malloc (el + 8); if (eb == NULL) { puts ("malloc failed"); return NULL; } /* Canary. */ memcpy (eb + el, "deadbeef", 8); cl = inet6_opt_init (eb, el); CHECK (); cl = inet6_opt_append (eb, el, cl, OPT_X, 12, 8, &db); CHECK (); val4 = 0x12345678; offset = inet6_opt_set_val (db, 0, &val4, sizeof (val4)); val8 = 0x0102030405060708LL; inet6_opt_set_val (db, offset, &val8, sizeof (val8)); cl = inet6_opt_append (eb, el, cl, OPT_Y, 7, 4, &db); CHECK (); val1 = 0x01; offset = inet6_opt_set_val (db, 0, &val1, sizeof (val1)); val2 = 0x1331; offset = inet6_opt_set_val (db, offset, &val2, sizeof (val2)); val4 = 0x01020304; inet6_opt_set_val (db, offset, &val4, sizeof (val4)); cl = inet6_opt_append (eb, el, cl, OPT_Z, 7, 1, &db); CHECK (); inet6_opt_set_val (db, 0, (void *) "abcdefg", 7); cl = inet6_opt_finish (eb, el, cl); CHECK (); if (memcmp (eb + el, "deadbeef", 8) != 0) { puts ("Canary corrupted"); free (eb); return NULL; } *elp = el; return eb; } int decode_inet6_opt (void *eb, socklen_t el) { int ret = 0; int seq = 0; int cl = 0; int offset; uint8_t type; socklen_t len; uint8_t val1; uint16_t val2; uint32_t val4; uint64_t val8; void *db; char buf[8]; while ((cl = inet6_opt_next (eb, el, cl, &type, &len, &db)) != -1) switch (type) { case OPT_X: if (seq++ != 0) { puts ("OPT_X is not first"); ret = 1; } if (len != 12) { printf ("OPT_X's length %d != 12\n", len); ret = 1; } offset = inet6_opt_get_val (db, 0, &val4, sizeof (val4)); if (val4 != 0x12345678) { printf ("OPT_X's val4 %x != 0x12345678\n", val4); ret = 1; } offset = inet6_opt_get_val (db, offset, &val8, sizeof (val8)); if (offset != len || val8 != 0x0102030405060708LL) { printf ("OPT_X's val8 %llx != 0x0102030405060708\n", (long long) val8); ret = 1; } break; case OPT_Y: if (seq++ != 1) { puts ("OPT_Y is not second"); ret = 1; } if (len != 7) { printf ("OPT_Y's length %d != 7\n", len); ret = 1; } offset = inet6_opt_get_val (db, 0, &val1, sizeof (val1)); if (val1 != 0x01) { printf ("OPT_Y's val1 %x != 0x01\n", val1); ret = 1; } offset = inet6_opt_get_val (db, offset, &val2, sizeof (val2)); if (val2 != 0x1331) { printf ("OPT_Y's val2 %x != 0x1331\n", val2); ret = 1; } offset = inet6_opt_get_val (db, offset, &val4, sizeof (val4)); if (offset != len || val4 != 0x01020304) { printf ("OPT_Y's val4 %x != 0x01020304\n", val4); ret = 1; } break; case OPT_Z: if (seq++ != 2) { puts ("OPT_Z is not third"); ret = 1; } if (len != 7) { printf ("OPT_Z's length %d != 7\n", len); ret = 1; } offset = inet6_opt_get_val (db, 0, buf, 7); if (offset != len || memcmp (buf, "abcdefg", 7) != 0) { buf[7] = '\0'; printf ("OPT_Z's buf \"%s\" != \"abcdefg\"\n", buf); ret = 1; } break; default: printf ("Unknown option %d\n", type); ret = 1; break; } if (seq != 3) { puts ("Didn't see all of OPT_X, OPT_Y and OPT_Z"); ret = 1; } return ret; } static int do_test (void) { void *eb; socklen_t el; eb = encode_inet6_opt (&el); if (eb == NULL) return 1; if (decode_inet6_opt (eb, el)) return 1; return 0; } #define TEST_FUNCTION do_test () #include "../test-skeleton.c"