1: #include <netinet/in.h>
2: #include <stdio.h>
3: #include <stdlib.h>
4: #include <string.h>
5:
6: #define OPT_X 42
7: #define OPT_Y 43
8: #define OPT_Z 44
9:
10: static void *
11: encode_inet6_opt (socklen_t *elp)
12: {
13: void *eb = NULL;
14: socklen_t el;
15: int cl;
16: void *db;
17: int offset;
18: uint8_t val1;
19: uint16_t val2;
20: uint32_t val4;
21: uint64_t val8;
22:
23: *elp = 0;
24: #define CHECK() \
25: if (cl == -1) \
26: { \
27: printf ("cl == -1 on line %d\n", __LINE__); \
28: free (eb); \
29: return NULL; \
30: }
31:
32:
33: cl = inet6_opt_init (NULL, 0);
34: CHECK ();
35: cl = inet6_opt_append (NULL, 0, cl, OPT_X, 12, 8, NULL);
36: CHECK ();
37: cl = inet6_opt_append (NULL, 0, cl, OPT_Y, 7, 4, NULL);
38: CHECK ();
39: cl = inet6_opt_append (NULL, 0, cl, OPT_Z, 7, 1, NULL);
40: CHECK ();
41: cl = inet6_opt_finish (NULL, 0, cl);
42: CHECK ();
43: el = cl;
44:
45: eb = malloc (el + 8);
46: if (eb == NULL)
47: {
48: puts ("malloc failed");
49: return NULL;
50: }
51:
52: memcpy (eb + el, "deadbeef", 8);
53:
54: cl = inet6_opt_init (eb, el);
55: CHECK ();
56:
57: cl = inet6_opt_append (eb, el, cl, OPT_X, 12, 8, &db);
58: CHECK ();
59: val4 = 0x12345678;
60: offset = inet6_opt_set_val (db, 0, &val4, sizeof (val4));
61: val8 = 0x0102030405060708LL;
62: inet6_opt_set_val (db, offset, &val8, sizeof (val8));
63:
64: cl = inet6_opt_append (eb, el, cl, OPT_Y, 7, 4, &db);
65: CHECK ();
66: val1 = 0x01;
67: offset = inet6_opt_set_val (db, 0, &val1, sizeof (val1));
68: val2 = 0x1331;
69: offset = inet6_opt_set_val (db, offset, &val2, sizeof (val2));
70: val4 = 0x01020304;
71: inet6_opt_set_val (db, offset, &val4, sizeof (val4));
72:
73: cl = inet6_opt_append (eb, el, cl, OPT_Z, 7, 1, &db);
74: CHECK ();
75: inet6_opt_set_val (db, 0, (void *) "abcdefg", 7);
76:
77: cl = inet6_opt_finish (eb, el, cl);
78: CHECK ();
79:
80: if (memcmp (eb + el, "deadbeef", 8) != 0)
81: {
82: puts ("Canary corrupted");
83: free (eb);
84: return NULL;
85: }
86: *elp = el;
87: return eb;
88: }
89:
90: int
91: decode_inet6_opt (void *eb, socklen_t el)
92: {
93: int ret = 0;
94: int seq = 0;
95: int cl = 0;
96: int offset;
97: uint8_t type;
98: socklen_t len;
99: uint8_t val1;
100: uint16_t val2;
101: uint32_t val4;
102: uint64_t val8;
103: void *db;
104: char buf[8];
105:
106: while ((cl = inet6_opt_next (eb, el, cl, &type, &len, &db)) != -1)
107: switch (type)
108: {
109: case OPT_X:
110: if (seq++ != 0)
111: {
112: puts ("OPT_X is not first");
113: ret = 1;
114: }
115: if (len != 12)
116: {
117: printf ("OPT_X's length %d != 12\n", len);
118: ret = 1;
119: }
120: offset = inet6_opt_get_val (db, 0, &val4, sizeof (val4));
121: if (val4 != 0x12345678)
122: {
123: printf ("OPT_X's val4 %x != 0x12345678\n", val4);
124: ret = 1;
125: }
126: offset = inet6_opt_get_val (db, offset, &val8, sizeof (val8));
127: if (offset != len || val8 != 0x0102030405060708LL)
128: {
129: printf ("OPT_X's val8 %llx != 0x0102030405060708\n",
130: (long long) val8);
131: ret = 1;
132: }
133: break;
134: case OPT_Y:
135: if (seq++ != 1)
136: {
137: puts ("OPT_Y is not second");
138: ret = 1;
139: }
140: if (len != 7)
141: {
142: printf ("OPT_Y's length %d != 7\n", len);
143: ret = 1;
144: }
145: offset = inet6_opt_get_val (db, 0, &val1, sizeof (val1));
146: if (val1 != 0x01)
147: {
148: printf ("OPT_Y's val1 %x != 0x01\n", val1);
149: ret = 1;
150: }
151: offset = inet6_opt_get_val (db, offset, &val2, sizeof (val2));
152: if (val2 != 0x1331)
153: {
154: printf ("OPT_Y's val2 %x != 0x1331\n", val2);
155: ret = 1;
156: }
157: offset = inet6_opt_get_val (db, offset, &val4, sizeof (val4));
158: if (offset != len || val4 != 0x01020304)
159: {
160: printf ("OPT_Y's val4 %x != 0x01020304\n", val4);
161: ret = 1;
162: }
163: break;
164: case OPT_Z:
165: if (seq++ != 2)
166: {
167: puts ("OPT_Z is not third");
168: ret = 1;
169: }
170: if (len != 7)
171: {
172: printf ("OPT_Z's length %d != 7\n", len);
173: ret = 1;
174: }
175: offset = inet6_opt_get_val (db, 0, buf, 7);
176: if (offset != len || memcmp (buf, "abcdefg", 7) != 0)
177: {
178: buf[7] = '\0';
179: printf ("OPT_Z's buf \"%s\" != \"abcdefg\"\n", buf);
180: ret = 1;
181: }
182: break;
183: default:
184: printf ("Unknown option %d\n", type);
185: ret = 1;
186: break;
187: }
188: if (seq != 3)
189: {
190: puts ("Didn't see all of OPT_X, OPT_Y and OPT_Z");
191: ret = 1;
192: }
193: return ret;
194: }
195:
196: int
197: main (void)
198: {
199: void *eb;
200: socklen_t el;
201: eb = encode_inet6_opt (&el);
202: if (eb == NULL)
203: return 1;
204: if (decode_inet6_opt (eb, el))
205: return 1;
206: return 0;
207: }