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

source code of glibc/inet/test-inet6_opt.c