Add accidentally omitted 'port' parameter to error messages
[trust_router.git] / trp / test / ptbl_test.c
1 /*
2  * Copyright (c) 2016, JANET(UK)
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  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <stdio.h>
36 #include <talloc.h>
37 #include <assert.h>
38
39 #include <tr_gss_names.h>
40 #include <trp_route.h>
41 #include <trp_internal.h>
42 #include <trp_peer.h>
43 #include <trp_ptable.h>
44
45 /* Can't do the updates test because trps_select_updates_for_peer() is now static */
46 #define VERIFY_UPDATES 0
47
48 struct peer_entry {
49   char *server;
50   char *gss_name;
51   unsigned int port;
52   unsigned int linkcost;
53 };
54
55 static struct peer_entry peer_data[]={
56   {"peer0", "trustrouter@peer0", 10000, 0x0001},
57   {"peer1", "trustrouter@peer1", 15000, 0x0002},
58   {"peer2", "trustrouter@peer2", 20000, 0x0004},
59   {"peer3", "trustrouter@peer3", 25000, 0x0008},
60   {"peer4", "trustrouter@peer4", 30000, 0x0010}
61 };
62 static size_t n_peers=sizeof(peer_data)/sizeof(peer_data[0]);
63
64 static void populate_ptable(TRPS_INSTANCE *trps)
65 {
66   TRP_PEER *new_peer;
67   int i;
68
69   for (i=0; i<n_peers; i++) {
70     new_peer=trp_peer_new(NULL);
71     assert(new_peer!=NULL);
72     trp_peer_set_server(new_peer, peer_data[i].server);
73     assert(trp_peer_get_server(new_peer)!=NULL);
74     trp_peer_add_gss_name(new_peer, tr_new_name(peer_data[i].gss_name));
75     assert(trp_peer_get_gss_names(new_peer)!=NULL);
76     trp_peer_set_port(new_peer, peer_data[i].port);
77     trp_peer_set_linkcost(new_peer, peer_data[i].linkcost);
78     assert(trps_add_peer(trps, new_peer)==TRP_SUCCESS);
79   }
80 }
81
82 static struct peer_entry *find_peer_entry(char *server)
83 {
84   int i;
85   for (i=0; i<n_peers; i++) {
86     if (0==strcmp(server, peer_data[i].server)) {
87       return (peer_data+i);
88     }
89   }
90   return NULL;
91 }
92
93 static void verify_ptable(TRPS_INSTANCE *trps)
94 {
95   struct peer_entry *peer_entry=NULL;
96   TRP_PEER *peer;
97   char *s;
98   TR_NAME *gssname;
99
100   peer=trps->ptable->head;
101   while (peer!=NULL) {
102     peer_entry=find_peer_entry(trp_peer_get_server(peer));
103     assert(peer_entry!=NULL);
104     assert(!strcmp(trp_peer_get_server(peer), peer_entry->server));
105     assert(trp_peer_get_port(peer)==peer_entry->port);
106     assert(trp_peer_get_linkcost(peer)==peer_entry->linkcost);
107     assert(0<asprintf(&s, "trustrouter@%s", peer_entry->server));
108     gssname=tr_new_name(s);
109     free(s);
110     assert(gssname!=NULL);
111     assert(tr_gss_names_matches(trp_peer_get_gss_names(peer), gssname));
112     tr_free_name(gssname);
113     peer=peer->next;
114   }
115 }
116
117 struct route_data {
118   char *apc;
119   char *realm;
120   char *peer;
121   unsigned int metric;
122   char *trust_router;
123   char *next_hop;
124   int selected;
125   unsigned int interval;
126   int verified; /* for testing */
127 };
128 static struct route_data route_table[]={
129   {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
130   {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
131   {"apc0", "realm0", "trustrouter@peer0", 1, "tr.r0.apc0", "trustrouter@peer0", 0, 60, 0},
132   {"apc0", "realm1", "trustrouter@peer0", 0, "tr.r1.apc0", "trustrouter@peer0", 0, 60, 0},
133   {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
134   {"apc0", "realm3", "trustrouter@peer0", 1, "tr.r3.apc0", "trustrouter@peer0", 0, 60, 0},
135   {"apc0", "realm4", "trustrouter@peer0", 2, "tr.r4.apc0", "trustrouter@peer0", 0, 60, 0},
136   {"apc0", "realm0", "trustrouter@peer1", 0, "tr.r0.apc0", "trustrouter@peer1", 0, 60, 0},
137   {"apc0", "realm1", "trustrouter@peer1", 1, "tr.r1.apc0", "trustrouter@peer1", 0, 60, 0},
138   {"apc0", "realm2", "trustrouter@peer1", 1, "tr.r2.apc0", "trustrouter@peer1", 0, 60, 0},
139   {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
140   {"apc0", "realm4", "trustrouter@peer1", 2, "tr.r4.apc0", "trustrouter@peer1", 0, 60, 0},
141   {"apc0", "realm0", "trustrouter@peer2", 0, "tr.r0.apc0", "trustrouter@peer2", 0, 60, 0},
142   {"apc0", "realm1", "trustrouter@peer2", 2, "tr.r1.apc0", "trustrouter@peer2", 0, 60, 0},
143   {"apc0", "realm2", "trustrouter@peer2", 2, "tr.r2.apc0", "trustrouter@peer2", 0, 60, 0},
144   {"apc0", "realm3", "trustrouter@peer2", 1, "tr.r3.apc0", "trustrouter@peer2", 0, 60, 0},
145   {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
146 };
147 static size_t n_routes=sizeof(route_table)/sizeof(route_table[0]);
148
149 #if VERIFY_UPDATES
150 /* These are the correct updates to select from the above route table for each peer.
151  * The rule is: send selected route unless it is through that peer, otherwise send
152  * the best (lowest metric) alternative route. 
153  *
154  * In a few cases there are multiple valid options (when a two non-selected routes
155  * exist). If these tests are failing, it may be that the trps code is selecting another
156  * valid option, so check that. Probably ought to tweak metrics to avoid that ambiguity. */
157 static struct route_data update_table[][10]={
158   { /* peer0 */
159     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
160     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
161     {"apc0", "realm2", "trustrouter@peer1", 1, "tr.r2.apc0", "trustrouter@peer1", 0, 60, 0},
162     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
163     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
164     {NULL}
165   },
166   { /* peer1 */
167     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
168     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
169     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
170     {"apc0", "realm3", "trustrouter@peer2", 1, "tr.r3.apc0", "trustrouter@peer2", 0, 60, 0},
171     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
172     {NULL}
173   },
174   { /* peer2 */
175     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
176     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
177     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
178     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
179     {"apc0", "realm4", "trustrouter@peer1", 2, "tr.r4.apc0", "trustrouter@peer1", 0, 60, 0},
180     {NULL}
181   },
182   { /* peer3 */
183     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
184     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
185     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
186     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
187     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
188     {NULL}
189   },
190   { /* peer4 */
191     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
192     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
193     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
194     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
195     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
196     {NULL}
197   }
198 };
199 #endif /* VERIFY_UPDATES */
200
201 static void populate_rtable(TRPS_INSTANCE *trps)
202 {
203   int i;
204   TRP_ROUTE *new;
205
206   for (i=0; i<n_routes; i++) {
207     new=trp_route_new(NULL);
208     assert(new!=NULL);
209     trp_route_set_comm(new, tr_new_name(route_table[i].apc));
210     trp_route_set_realm(new, tr_new_name(route_table[i].realm));
211     trp_route_set_peer(new, tr_new_name(route_table[i].peer));
212     trp_route_set_metric(new, route_table[i].metric);
213     trp_route_set_trust_router(new, tr_new_name(route_table[i].trust_router));
214     trp_route_set_next_hop(new, tr_new_name(route_table[i].next_hop));
215     trp_route_set_selected(new, route_table[i].selected);
216     trp_route_set_interval(new, route_table[i].interval);
217     /* do not set expiry */
218     trp_rtable_add(trps->rtable, new);
219     new=NULL;
220   }
221 }
222
223 #if VERIFY_UPDATES
224 static void verify_update(TRP_ROUTE **updates, size_t n_updates, struct route_data *expected)
225 {
226   int ii,jj;
227   int found;
228
229   for(jj=0; jj<n_updates; jj++) {
230     found=0;
231     for (ii=0; expected[ii].apc!=NULL; ii++) {
232       if ((0==strcmp(expected[ii].apc, updates[jj]->comm->buf))
233          &&(0==strcmp(expected[ii].realm, updates[jj]->realm->buf))
234          &&(0==strcmp(expected[ii].peer, updates[jj]->peer->buf))
235          &&(expected[ii].metric==updates[jj]->metric)
236          &&(0==strcmp(expected[ii].trust_router, updates[jj]->trust_router->buf))
237          &&(0==strcmp(expected[ii].next_hop, updates[jj]->next_hop->buf))
238          &&(expected[ii].selected==updates[jj]->selected)
239          &&(expected[ii].interval==updates[jj]->interval)) {
240         assert(expected[ii].verified==0); /* should only encounter each entry once */
241         expected[ii].verified=1;
242         found=1;
243         continue;
244       }
245     }
246     if (!found) {
247       printf("missing:\n%s\n", trp_route_to_str(NULL,updates[jj], " | "));
248       assert(0);
249     }
250   }
251   for(ii=0; expected[ii].apc!=NULL; ii++)
252     assert(expected[ii].verified==1);
253 }
254
255 static void verify_update_selection(TRPS_INSTANCE *trps)
256 {
257   int ii;
258   TRP_ROUTE **updates=NULL;
259   size_t n_updates;
260   TR_NAME *gssname=NULL;
261   char *s;
262
263   for (ii=0; ii<n_peers; ii++) {
264     assert(0<asprintf(&s, "trustrouter@%s", peer_data[ii].server));
265     assert(NULL!=(gssname=tr_new_name(s)));
266     free(s);
267
268     updates=trps_select_updates_for_peer(NULL, trps, gssname, &n_updates);
269     tr_free_name(gssname);
270     verify_update(updates, n_updates, update_table[ii]);
271     talloc_free(updates);
272   }
273 }
274 #endif /* VERIFY_UPDATES */
275
276 int main(void)
277 {
278   TALLOC_CTX *main_ctx=talloc_new(NULL);
279   TRPS_INSTANCE *trps;
280   char *s;
281
282   trps=trps_new(main_ctx);
283
284   printf("\nPopulating peer table...\n");
285   populate_ptable(trps);
286
287   printf("\nVerifying peer table...\n");
288   verify_ptable(trps);
289
290   printf("\nPopulating route table...\n");
291   populate_rtable(trps);
292   s=trp_rtable_to_str(main_ctx, trps->rtable, " | ", NULL);
293   printf("Route Table:\n%s---\n", s);
294
295 #if VERIFY_UPDATES
296   printf("\nVerifying route update selection...\n");
297   verify_update_selection(trps);
298 #endif /* VERIFY_UPDATES */
299
300   printf("\nDone\n\n");
301   talloc_report_full(main_ctx, stderr);
302   talloc_free(main_ctx);
303   talloc_report_full(NULL, stderr);
304   return 0;
305 }