Merge branch 'master' into bug13658-branch
[platform/upstream/glibc.git] / inet / test-inet6_opt.c
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   /* Estimate the length */
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   /* Canary.  */
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 }