2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2011
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
25 #include <sys/socket.h>
32 #define MAX_ADDRLEN 128
54 struct route_list routes
;
56 struct service_list services
;
63 #define ROUTE_MAXHOPS 7
67 int routes
[ROUTE_MAXHOPS
+ 1];
71 #define SEARCHQUERY_NEIGHSNOTQUERIED 1
72 #define SEARCHQUERY_NODEBYADDRESS 2
87 struct route_list localneighs
;
88 struct service_list localservices
;
91 static int node_matches_searchquery(struct node
*n
, struct search_query
*q
)
93 if (q
->type
== SEARCHQUERY_NEIGHSNOTQUERIED
) {
94 return n
->neighs_queried
== 0;
95 } else if (q
->type
== SEARCHQUERY_NODEBYADDRESS
) {
96 /* if (n->addrlen != q->query.nodebyaddress.addrlen)
98 if (memcmp(n->addr, q->query.nodebyaddress.addr,
103 __u16 cmplen
= n
->addrlen
;
106 if (q
->query
.nodebyaddress
.addrlen
< cmplen
)
107 cmplen
= q
->query
.nodebyaddress
.addrlen
;
109 if (memcmp(n
->addr
, q
->query
.nodebyaddress
.addr
, cmplen
) != 0)
112 for (u
=cmplen
;u
<n
->addrlen
;u
++) {
113 if (n
->addr
[u
] != 0) {
117 for (u
=cmplen
;u
<q
->query
.nodebyaddress
.addrlen
;u
++) {
118 if (q
->query
.nodebyaddress
.addr
[u
] != 0) {
129 static int try_find_neigh(struct e2e_route
*route
, struct search_query
*q
,
130 struct route_list
*curr
)
132 int *pos
= &(route
->routes
[route
->pos
]);
134 for (*pos
=0;*pos
<curr
->numroutes
;(*pos
)++) {
135 struct node
*n
= curr
->routes
[*pos
].dst
;
136 if (node_matches_searchquery(n
, q
)) {
142 if (route
->pos
>= ROUTE_MAXHOPS
)
147 for (*pos
=0;*pos
<curr
->numroutes
;(*pos
)++) {
148 int rc
= try_find_neigh(route
, q
,
149 &(curr
->routes
[*pos
].dst
->routes
));
159 static int try_find_neigh_byaddr(struct e2e_route
*route
, __u16 addrlen
,
162 struct search_query q
;
163 bzero(&q
, sizeof(struct search_query
));
164 q
.type
= SEARCHQUERY_NODEBYADDRESS
;
165 q
.query
.nodebyaddress
.addrlen
= addrlen
;
166 q
.query
.nodebyaddress
.addr
= addr
;
168 return try_find_neigh(route
, &q
, &localneighs
);
171 static int connect_to_host_recv(int fd
, struct e2e_route
*route
)
175 for (u
=0;route
!= 0 && u
<=route
->pos
;u
++) {
176 int rc
= read_resp(fd
);
178 return RC_CONNBROKEN
;
183 static int connect_to_host_send(int fd
, struct e2e_route
*route
)
185 struct route_list
*routes
= &localneighs
;
187 for (u
=0;u
<=route
->pos
;u
++) {
188 struct node
*n
= routes
->routes
[route
->routes
[u
]].dst
;
189 int rc
= send_connect_neigh(fd
, n
->addrlen
, n
->addr
);
191 return RC_CONNBROKEN
;
192 routes
= &(n
->routes
);
198 static int connect_to_host(int fd
, __u16 addrlen
, char *addr
)
201 struct e2e_route route
;
202 bzero(&route
, sizeof(struct e2e_route
));
204 if (try_find_neigh_byaddr(&route
, addrlen
, addr
) == 0)
205 return RC_CONNBROKEN
;
207 rc
= connect_to_host_send(fd
, &route
);
211 rc
= connect_to_host_recv(fd
, &route
);
217 void add_neigh(void *ptr
, __u32 addrlen
, char *addr
)
219 struct route_list
*list
= (struct route_list
*) ptr
;
221 struct e2e_route route
;
223 if (addrlen
> MAX_ADDRLEN
)
226 if (list
->numroutes
>= list
->rows_alloc
)
229 assert(list
->routes
[list
->numroutes
].dst
== 0);
231 bzero(&route
, sizeof(struct e2e_route
));
232 if (try_find_neigh_byaddr(&route
, addrlen
, addr
) == 0) {
233 node
= calloc(1, sizeof(struct node
));
235 node
->addr
= malloc(((int) addrlen
));
236 node
->addrlen
= addrlen
;
237 memcpy(node
->addr
, addr
, addrlen
);
242 list
->routes
[list
->numroutes
].dst
= node
;
246 void init_neighlist(void *ptr
, __u32 numneighs
)
248 struct route_list
*list
= (struct route_list
*) ptr
;
252 list
->rows_alloc
= (__u16
) numneighs
;
253 list
->routes
= calloc(numneighs
, sizeof(struct route
));
256 void add_service(void *ptr
, __be16 port
)
258 struct service_list
*list
= (struct service_list
*) ptr
;
260 printf("add service %u\n", ntohs(port
));
262 if (list
->numports
>= list
->rows_alloc
)
265 list
->ports
[list
->numports
] = port
;
269 void init_servicelist(void *ptr
, __u32 numservices
)
271 struct service_list
*list
= (struct service_list
*) ptr
;
273 printf("init servicelist %u\n", numservices
);
275 if (numservices
> 16)
277 list
->rows_alloc
= (__u16
) numservices
;
278 list
->ports
= calloc(numservices
, 2);
281 static void print_hex(char *buf
, int len
)
285 printf("%hhx ", buf
[u
]);
289 void neigh_printaddr(__u16 addrlen
, char *addr
)
291 printf("addrlen = %d addr: ", (int) addrlen
);
292 print_hex(addr
, addrlen
);
296 void load_neigh_list(struct e2e_route
*route
)
298 struct route_list
*list
;
299 struct service_list
*service
;
303 fd
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RAW
);
309 rc
= connect(fd
, 0, 0);
317 service
= &localservices
;
319 neigh_printaddr(route
->result
->addrlen
,
320 route
->result
->addr
);
321 list
= &(route
->result
->routes
);
322 service
= &(route
->result
->services
);
323 rc
= connect_to_host_send(fd
, route
);
326 printf("load_neigh_list: connect_to_host_send error\n");
331 rc
= send_list_neigh(fd
);
333 printf("load_neigh_list: send_list_neigh error\n");
337 rc
= send_list_services(fd
);
339 printf("load_neigh_list: send_list_services error\n");
344 rc
= connect_to_host_recv(fd
, route
);
346 printf("load_neigh_list: connect_to_host_recv error\n");
354 printf("load_neigh_list: read_resp error\n");
356 rc
= read_neigh_list(fd
, list
, init_neighlist
, add_neigh
);
358 printf("load_neigh_list: read_neigh_list error\n");
363 printf("load_neigh_list: read_resp error\n");
365 rc
= read_service_list(fd
, service
, init_servicelist
, add_service
);
367 printf("load_neigh_list: read_service_list error\n");
369 printf("load_neigh_list rc %d\n", rc
);
376 static void discover_network(void)
378 struct search_query q
;
379 bzero(&q
, sizeof(struct search_query
));
380 q
.type
= SEARCHQUERY_NEIGHSNOTQUERIED
;
383 struct e2e_route nextroute
;
384 bzero(&nextroute
, sizeof(struct e2e_route
));
385 int rc
= try_find_neigh(&nextroute
, &q
, &localneighs
);
388 load_neigh_list(&nextroute
);
389 nextroute
.result
->neighs_queried
= 1;
393 struct rdscmd_connect_data
{
397 static int rdscmd_void_connect(void *ptr
, __u64 cookie
,
398 struct cor_sockaddr
*addr
)
402 int rds_fd
= ((struct rdscmd_connect_data
*) ptr
)->rds_fd
;
404 printf("rds_connect %llu\n", cookie
);
406 if (addr
->sin_family
!= AF_COR
)
409 printf("rds_connect %llu, %u\n", cookie
, ntohs(addr
->port
));
411 fd
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RAW
);
417 rc
= connect(fd
, 0, 0);
424 printf("rds_connect addr: ");
425 print_hex(&(addr
->addr
[0]), sizeof(addr
->addr
));
426 printf(" port: %u\n", ntohs(addr
->port
));
428 rc
= connect_to_host(fd
, sizeof(addr
->addr
), &(addr
->addr
[0]));
431 printf("connect_to_host error\n");
436 rc
= send_connect_port(fd
, addr
->port
);
438 printf("send_connect_port error\n");
445 printf("read_resp error\n");
449 rc
= pass_socket(fd
, cookie
);
451 printf("pass_socket error\n");
459 printf("send_rdsock_connecterror\n");
460 rc
= send_rdsock_connecterror(rds_fd
, cookie
,
461 CONNECTERROR_NETUNREACH
);
463 printf("send_rdsock_connecterror returned %d\n", rc
);
471 static int proc_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
473 if (cmd
->cmd
== CRD_KTU_CONNECT
) {
474 struct rdscmd_connect_data data
;
476 return parse_rdsock_connect(&data
, cmd
, rdscmd_void_connect
);
478 printf("error in proc_rdsock_cmd: unknown cmd: %u\n", cmd
->cmd
);
481 return RC_CONNBROKEN
;
485 static int parse_hexchar(char c
)
507 else if (c
== 'A' || c
== 'a')
509 else if (c
== 'B' || c
== 'b')
511 else if (c
== 'C' || c
== 'c')
513 else if (c
== 'D' || c
== 'd')
515 else if (c
== 'E' || c
== 'e')
517 else if (c
== 'F' || c
== 'f')
523 static int parse_hex(char *target
, char *src
, int srclen
)
530 assert((srclen
%2) == 0);
532 for(u
=0;u
<(srclen
/2);u
++) {
533 int high
= parse_hexchar(src
[u
*2]);
534 int low
= parse_hexchar(src
[u
*2+1]);
536 if (high
== -1 || low
== -1)
539 target
[u
] = (char) ((high
<< 4) + low
);
545 int parse_addr(char *argv_addr
)
548 int len
= strlen(argv_addr
);
549 char *noaddr
= "noaddr";
551 if (strncmp(argv_addr
, noaddr
, len
) == 0) {
557 if ((len
< 2) || (len
%2) != 0)
560 localaddr
= malloc(len
/2);
561 localaddrlen
= len
/2;
563 rc
= parse_hex(localaddr
, argv_addr
, len
);
570 fprintf(stderr
, "error: argv_addr is not a valid address (contains "
571 "non-hex characters or number of hex characters is not "
572 "a multiple of 2)\n");
576 int main(int argc
, char *argv
[])
584 rc
= parse_addr(argv
[1]);
588 rdsock
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RDEAMON
);
594 rc
= connect(rdsock
, 0, 0);
600 send_rdsock_version(rdsock
, 0);
601 send_rdsock_up(rdsock
, localaddr
, localaddrlen
);
608 struct rdsock_cmd cmd
;
610 rc
= read_rdsock_cmd(rdsock
, &cmd
);
612 printf("read_rdsock_cmd rc = %d\n", rc
);
616 rc
= proc_rdsock_cmd(rdsock
, &cmd
);
617 free_rdsockcmd_data(&cmd
);
619 printf("proc_rdsock_cmd rc = %d\n", rc
);
628 fprintf(stderr
, "usage test_routed addr\n");