SO_LINGER test
[corutils.git] / test_route.c
bloba804d62bdc85b4c19732d412664afe8c2ab903d6
1 /**
2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2011
4 * Authors:
5 * Michael Blizek
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
27 #include "libcor.h"
30 #define MAX_ADDRLEN 128
33 struct route{
34 struct node *dst;
37 struct route_list{
38 struct route *routes;
39 __u16 rows_alloc;
40 __u16 numroutes;
43 struct route_list localneighs;
45 struct node{
46 char *addr;
48 struct route_list routes;
50 __u16 addrlen;
51 __u16 minhops;
52 __u8 neighs_queried;
55 #define ROUTE_MAXHOPS 7
57 struct e2e_route{
58 struct node *result;
59 int routes[ROUTE_MAXHOPS + 1];
60 int pos;
63 #define SEARCHQUERY_NEIGHSNOTQUERIED 1
64 #define SEARCHQUERY_NODEBYADDRESS 2
65 struct search_query{
66 int type;
67 union {
68 struct {
69 __u16 addrlen;
70 char *addr;
71 }nodebyaddress;
72 }query;
75 static int node_matches_searchquery(struct node *n, struct search_query *q)
77 if (q->type == SEARCHQUERY_NEIGHSNOTQUERIED) {
78 return n->neighs_queried == 0;
79 } else if (q->type == SEARCHQUERY_NODEBYADDRESS) {
80 if (n->addrlen != q->query.nodebyaddress.addrlen)
81 return 0;
82 if (memcmp(n->addr, q->query.nodebyaddress.addr,
83 n->addrlen) != 0)
84 return 0;
85 return 1;
86 } else {
87 assert(0);
88 return 0;
92 static int try_find_neigh(struct e2e_route *route, struct search_query *q,
93 struct route_list *curr)
95 int *pos = &(route->routes[route->pos]);
97 for (*pos=0;*pos<curr->numroutes;(*pos)++) {
98 struct node *n = curr->routes[*pos].dst;
99 if (node_matches_searchquery(n, q)) {
100 route->result = n;
101 return 1;
105 if (route->pos >= ROUTE_MAXHOPS)
106 return 0;
108 route->pos++;
110 for (*pos=0;*pos<curr->numroutes;(*pos)++) {
111 int rc = try_find_neigh(route, q,
112 &(curr->routes[*pos].dst->routes));
113 if (rc)
114 return rc;
117 route->pos--;
119 return 0;
122 static int try_find_neigh_byaddr(struct e2e_route *route, __u16 addrlen,
123 char *addr)
125 struct search_query q;
126 bzero(&q, sizeof(struct search_query));
127 q.type = SEARCHQUERY_NODEBYADDRESS;
128 q.query.nodebyaddress.addrlen = addrlen;
129 q.query.nodebyaddress.addr = addr;
131 return try_find_neigh(route, &q, &localneighs);
134 static int connect_to_host_recv(int fd, struct e2e_route *route)
136 int u;
137 for (u=0;route != 0 && u<=route->pos;u++) {
138 int rc = read_resp(fd);
139 if (rc != RC_OK)
140 return RC_CONNBROKEN;
142 return RC_OK;
145 static int connect_to_host_send(int fd, struct e2e_route *route)
147 struct route_list *routes = &localneighs;
148 int u;
149 for (u=0;u<=route->pos;u++) {
150 struct node *n = routes->routes[route->routes[u]].dst;
151 int rc = send_connect_neigh(fd, n->addrlen, n->addr);
152 if (rc != RC_OK)
153 return RC_CONNBROKEN;
154 routes = &(n->routes);
157 return RC_OK;
160 static int connect_to_host(int fd, __u16 addrlen, char *addr)
162 int rc;
163 struct e2e_route route;
164 bzero(&route, sizeof(struct e2e_route));
166 if (try_find_neigh_byaddr(&route, addrlen, addr) == 0)
167 return RC_CONNBROKEN;
169 rc = connect_to_host_send(fd, &route);
170 if (rc != RC_OK)
171 goto out;
173 rc = connect_to_host_recv(fd, &route);
175 out:
176 return rc;
179 void add_neigh(void *ptr, __u32 addrlen, char *addr)
181 struct route_list *list = (struct route_list *) ptr;
182 struct node *node;
183 struct e2e_route route;
185 if (addrlen > MAX_ADDRLEN)
186 return;
188 if (list->numroutes >= list->rows_alloc)
189 return;
191 assert(list->routes[list->numroutes].dst == 0);
193 bzero(&route, sizeof(struct e2e_route));
194 if (try_find_neigh_byaddr(&route, addrlen, addr) == 0) {
195 node = calloc(1, sizeof(struct node));
197 node->addr = malloc(((int) addrlen));
198 node->addrlen = addrlen;
199 memcpy(node->addr, addr, addrlen);
200 } else {
201 node = route.result;
204 list->routes[list->numroutes].dst = node;
205 list->numroutes++;
208 void init_neighlist(void *ptr, __u32 numneighs)
210 struct route_list *list = (struct route_list *) ptr;
211 if (numneighs > 16)
212 numneighs = 16;
213 #warning todo limit
214 list->rows_alloc = (__u16) numneighs;
215 list->routes = calloc(numneighs, sizeof(struct route));
218 static void print_hex(char *buf, int len)
220 int u;
221 for(u=0;u<len;u++) {
222 printf("%hhx ", buf[u]);
226 void neigh_printaddr(__u16 addrlen, char *addr)
228 printf("addrlen = %d addr: ", (int) addrlen);
229 print_hex(addr, addrlen);
230 printf("\n");
233 void load_neigh_list(struct e2e_route *route)
235 struct route_list *list;
236 int fd, rc;
237 int u;
239 fd = socket(PF_COR, SOCK_RAW, PROTO_COR_RAW);
240 if(fd < 0) {
241 perror("socket");
242 goto early_out;
245 rc = connect(fd, 0, 0);
246 if(rc < 0) {
247 perror("connect");
248 goto out;
251 if (route == 0) {
252 list = &localneighs;
253 } else {
254 neigh_printaddr(route->result->addrlen,
255 route->result->addr);
256 list = &(route->result->routes);
257 rc = connect_to_host_send(fd, route);
259 if (rc != RC_OK) {
260 printf("connect_to_host_send error\n");
261 goto out;
264 rc = send_list_neigh(fd);
265 if (rc != RC_OK) {
266 printf("send_list_neigh error\n");
267 goto out;
270 if (route != 0) {
271 rc = connect_to_host_recv(fd, route);
272 if (rc != RC_OK) {
273 printf("connect_to_host_recv error\n");
274 goto out;
277 rc = read_resp(fd);
278 if (rc != RC_OK)
279 printf("read_resp error\n");
281 rc = read_neigh_list(fd, list, init_neighlist, add_neigh);
282 if (rc != RC_OK)
283 printf("read_neigh_list error\n");
284 out:
285 printf("load_neigh_list rc %d\n", rc);
286 close(fd);
288 early_out:
289 return;
292 int main(void)
294 struct search_query q;
295 bzero(&q, sizeof(struct search_query));
296 q.type = SEARCHQUERY_NEIGHSNOTQUERIED;
297 load_neigh_list(0);
298 while (1) {
299 struct e2e_route nextroute;
300 bzero(&nextroute, sizeof(struct e2e_route));
301 int rc = try_find_neigh(&nextroute, &q, &localneighs);
302 if (rc == 0)
303 break;
304 load_neigh_list(&nextroute);
305 nextroute.result->neighs_queried = 1;
307 return 0;