2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2014
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>
29 #include <arpa/inet.h>
31 #include <sys/epoll.h>
37 #define U32_MAX ((__u32) ((1LL << 32) - 1))
40 #define MAX_ADDRLEN 128
42 #define ASSERT_ERR() \
53 if (!(a)) { ASSERT_ERR(); } \
73 #define ROUTE_MAXHOPS 7
78 struct route_list routes
;
80 struct service_list services
;
86 struct list_head node_list
;
88 __u32 route
[ROUTE_MAXHOPS
+ 1];
92 #define SEARCHQUERY_NEIGHSNOTQUERIED 1
93 #define SEARCHQUERY_NODEBYADDRESS 2
94 #define SEARCHQUERY_NODEBYSERVICEPORT 3
111 __u8 export_servicelist_enabled
= 0;
113 struct route_list localneighs
;
114 struct service_list localservices
;
116 struct list_head node_list
;
118 int discover_finished
= 0;
123 #define EPOLL_EVENTS 16
125 #define EPOLLDATA_DISCOVERNETWORK 1
126 #define EPOLLDATA_RDSCONNECT 2
127 #define EPOLLDATA_RDSOCKCMD 3
128 #define EPOLLDATA_FWD_TO_R 4
129 #define EPOLLDATA_FWD_TO_LSERVICE 5
130 #define EPOLLDATA_FORWARD 6
132 struct nonblock_resumeinfo_connect_to_host_send
{
138 struct route_list
*routes
;
142 struct nonblock_resumeinfo_connect_to_host_recv
{
151 #define FORWARD_BUF_SIZE 4096
153 struct nonblock_resumeinfo
{
164 struct route_list
*list
;
165 struct service_list
*service
;
167 struct nonblock_resumeinfo_connect_to_host_send connect_send
;
168 struct nonblock_resumeinfo_connect_to_host_recv connect_recv
;
170 struct libcor_nonblock_resumeinfo lnr
;
180 struct nonblock_resumeinfo_connect_to_host_send connect_send
;
181 struct nonblock_resumeinfo_connect_to_host_recv connect_resp
;
183 struct libcor_nonblock_resumeinfo lnr
;
187 struct libcor_nonblock_resumeinfo lnr
;
199 struct sockaddr
*saddr
;
205 * buf gets filled by reversedir and written into
214 struct nonblock_resumeinfo
*reversedir
;
219 struct fwd_to_r_item
{
220 struct list_head allfwds
;
230 struct fwd_to_lservice_item
{
231 struct list_head allfwds
;
236 struct sockaddr
*saddr
;
242 #define offsetof(type, member) __builtin_offsetof (type, member)
244 #define container_of(ptr, type, member) ({ \
245 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
246 (type *)( (char *)__mptr - offsetof(type,member) );})
249 static void set_nonblock(int fd
, int value
)
253 flags
= fcntl(fd
, F_GETFL
, 0);
255 perror("set_nonblock F_GETFL");
259 flags
= (flags
& (~(O_NONBLOCK
)));
261 flags
= flags
| O_NONBLOCK
;
263 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
264 perror("set_nonblock F_SETFL");
269 static int addr_eq(char *addr1
, __u32 addrlen1
,
270 char *addr2
, __u32 addrlen2
)
273 if (addr1
[addrlen1
-1] == 0) {
281 if (addr2
[addrlen2
-1] == 0) {
288 if (addrlen1
!= addrlen2
)
291 if (addrlen1
> MAX_ADDRLEN
)
294 if (addrlen1
!= 0 && memcmp(addr1
, addr2
, addrlen1
) != 0)
300 static int service_list_contains(struct service_list
*services
, __be16 port
)
304 for (u
=0;u
<services
->numports
;u
++) {
305 if (services
->ports
[u
] == port
) {
313 static int node_matches_searchquery(struct node
*n
, struct search_query
*q
)
315 if (q
->type
== SEARCHQUERY_NEIGHSNOTQUERIED
) {
316 return n
->neighs_queried
== 0 &&
317 addr_eq(n
->addr
, n
->addrlen
, localaddr
,
319 } else if (q
->type
== SEARCHQUERY_NODEBYADDRESS
) {
320 return addr_eq(n
->addr
, n
->addrlen
,
321 q
->query
.nodebyaddress
.addr
,
322 q
->query
.nodebyaddress
.addrlen
);
323 } else if (q
->type
== SEARCHQUERY_NODEBYSERVICEPORT
) {
324 return service_list_contains(&(n
->services
),
325 q
->query
.serviceport
);
332 static struct node
* try_find_neigh(struct search_query
*q
)
334 struct list_head
*curr
= node_list
.next
;
336 while (curr
!= &node_list
) {
337 struct node
*currnode
= container_of(curr
, struct node
,
340 if (node_matches_searchquery(currnode
, q
)) {
350 static struct node
* try_find_neigh_byaddr(__u16 addrlen
, char *addr
)
352 struct search_query q
;
353 bzero(&q
, sizeof(struct search_query
));
354 q
.type
= SEARCHQUERY_NODEBYADDRESS
;
355 q
.query
.nodebyaddress
.addrlen
= addrlen
;
356 q
.query
.nodebyaddress
.addr
= addr
;
357 return try_find_neigh(&q
);
360 static struct node
* try_find_neigh_byservice(__be16 serviceport
)
362 struct search_query q
;
363 bzero(&q
, sizeof(struct search_query
));
364 q
.type
= SEARCHQUERY_NODEBYSERVICEPORT
;
365 q
.query
.serviceport
= serviceport
;
366 return try_find_neigh(&q
);
370 static int check_rc(int rc
, char *errormsg
)
372 if (rc
!= RC_OK
&& rc
!= RC_WOULDBLOCK
)
373 printf("%s\n", errormsg
);
374 return (rc
!= RC_OK
);
377 static int connect_to_host_recv(int fd
, struct libcor_nonblock_resumeinfo
*lnr
,
378 struct nonblock_resumeinfo_connect_to_host_recv
*rcr
,
381 if (rcr
->state
== 0) {
389 ASSERT(rcr
->fd
= fd
);
390 ASSERT(rcr
->node
= node
);
392 ASSERT(node
->hopcount
!= 0);
394 for (;rcr
->u
< node
->hopcount
;rcr
->u
++) {
395 int rc
= read_resp_nonblock(fd
, lnr
);
399 bzero(rcr
, sizeof(struct nonblock_resumeinfo_connect_to_host_recv
));
403 static int connect_to_host_send(int fd
,
404 struct libcor_nonblock_resumeinfo
*lnr
,
405 struct nonblock_resumeinfo_connect_to_host_send
*cth
,
408 if (cth
->state
== 0) {
412 cth
->routes
= &localneighs
;
418 ASSERT(cth
->fd
= fd
);
419 ASSERT(cth
->node
= node
);
421 ASSERT(node
->hopcount
!= 0);
423 for (;cth
->u
< node
->hopcount
;) {
424 struct node
*n
= cth
->routes
->routes
[node
->route
[cth
->u
]].dst
;
425 int rc
= send_connect_neigh_nonblock(fd
, lnr
, n
->addrlen
,
430 cth
->routes
= &(n
->routes
);
432 bzero(cth
, sizeof(struct nonblock_resumeinfo_connect_to_host_send
));
436 static void add_neigh(void *ptr
, __u32 addrlen
, char *addr
)
438 struct route_list
*list
= (struct route_list
*) ptr
;
441 if (addrlen
> MAX_ADDRLEN
)
444 if (addr_eq(addr
, addrlen
, 0, 0))
447 if (list
->numroutes
>= list
->rows_alloc
)
450 ASSERT(list
->routes
[list
->numroutes
].dst
== 0);
452 node
= try_find_neigh_byaddr(addrlen
, addr
);
455 node
= calloc(1, sizeof(struct node
));
457 node
->addr
= malloc(((int) addrlen
));
458 node
->addrlen
= addrlen
;
459 memcpy(node
->addr
, addr
, addrlen
);
461 list_add_tail(&(node
->node_list
), &node_list
);
464 list
->routes
[list
->numroutes
].dst
= node
;
468 static void init_neighlist(void *ptr
, __u32 numneighs
)
470 struct route_list
*list
= (struct route_list
*) ptr
;
474 list
->rows_alloc
= (__u16
) numneighs
;
475 list
->routes
= calloc(numneighs
, sizeof(struct route
));
478 static void add_service(void *ptr
, __be16 port
)
480 struct service_list
*list
= (struct service_list
*) ptr
;
482 printf("add service %u\n", ntohs(port
));
484 if (list
->numports
>= list
->rows_alloc
)
487 list
->ports
[list
->numports
] = port
;
491 static void init_servicelist(void *ptr
, __u32 numservices
)
493 struct service_list
*list
= (struct service_list
*) ptr
;
495 printf("init servicelist %u\n", numservices
);
497 if (numservices
> 16)
499 list
->rows_alloc
= (__u16
) numservices
;
501 list
->ports
= calloc(numservices
, 2);
504 static void print_hex(char *buf
, __u32 len
)
508 ASSERT(len
!= U32_MAX
);
511 printf("%hhx ", buf
[u
]);
515 static void neigh_printaddr(__u16 addrlen
, char *addr
)
517 printf("addrlen = %d addr: ", (int) addrlen
);
518 print_hex(addr
, addrlen
);
523 static int __export_servicelist(int fd
, char *data
, __u32 len
)
525 __u32 totalwritten
= 0;
527 ASSERT(len
!= U32_MAX
);
529 while (totalwritten
< len
) {
530 int written
= write(fd
, data
+ totalwritten
, len
-totalwritten
);
536 perror("export servicelist");
540 totalwritten
+= written
;
546 static int _export_servicelist(int fd
, char *addr
, __u32 addrlen
, __u32 cost
,
547 struct service_list
*services
)
553 for (u
=0;u
<services
->numports
;u
++) {
556 ASSERT(addrlen
!= U32_MAX
);
558 for(v
=0;v
<addrlen
;v
++) {
559 if (((__u8
) addr
[v
]) < 16)
560 rc
= snprintf(&(buf
[0]), 20, "0%hhx", addr
[v
]);
562 rc
= snprintf(&(buf
[0]), 20, "%hhx", addr
[v
]);
566 rc
= __export_servicelist(fd
, &(buf
[0]), rc
);
571 rc
= snprintf(&(buf
[0]), 20, ":%hu:%u\n",
572 ntohs(services
->ports
[u
]), cost
);
576 rc
= __export_servicelist(fd
, &(buf
[0]), rc
);
584 static void export_servicelist(void)
586 char *servicelist_txtfile
= "/var/lib/cor/services/txt";
587 char *servicelist_tmpfile
= "/var/lib/cor/services/tmp";
590 struct list_head
*curr
;
592 if (export_servicelist_enabled
== 0)
595 fd
= open(servicelist_tmpfile
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
597 perror("export servicelist");
601 if (_export_servicelist(fd
, 0, 0, 0, &localservices
) != 0)
604 curr
= node_list
.next
;
605 while (curr
!= &node_list
) {
606 struct node
*currnode
= container_of(curr
, struct node
,
611 if (addr_eq(currnode
->addr
, currnode
->addrlen
, localaddr
,
615 if (_export_servicelist(fd
, currnode
->addr
, currnode
->addrlen
,
616 currnode
->hopcount
, &(currnode
->services
)) != 0)
623 if (rename(servicelist_tmpfile
, servicelist_txtfile
) != 0) {
624 perror("export servicelist");
632 unlink(servicelist_tmpfile
);
636 static void __recalc_routes(struct node
*node
)
638 struct list_head
*curr
;
640 curr
= node_list
.next
;
641 while (curr
!= &node_list
) {
642 struct node
*currnode
= container_of(curr
, struct node
,
645 if (currnode
->hopcount
< node
->hopcount
)
651 list_del(&(node
->node_list
));
652 list_add_tail(&(node
->node_list
), curr
);
655 static void _recalc_routes(struct node
*node
)
657 struct route_list
*routes
= (node
== 0 ?
658 &localneighs
: &(node
->routes
));
662 for (u
=0;u
<routes
->numroutes
;u
++) {
663 struct node
*target
= routes
->routes
[u
].dst
;
665 __u32 hopcount
= (node
== 0 ? 0 : node
->hopcount
) + 1;
667 if (target
->hopcount
!= 0 && target
->hopcount
<= hopcount
)
671 bzero(&(target
->route
[0]), sizeof(target
->route
));
673 memcpy(&(target
->route
[0]), &(node
->route
[0]),
674 sizeof(target
->route
));
677 target
->hopcount
= hopcount
;
678 target
->route
[hopcount
-1] = u
;
680 __recalc_routes(target
);
684 static void recalc_routes(void)
686 struct list_head oldnodes
;
687 struct list_head
*curr
;
689 list_add(&oldnodes
, &node_list
);
690 list_del(&node_list
);
691 init_list_head(&node_list
);
694 curr
= oldnodes
.next
;
695 while (curr
!= &oldnodes
) {
696 struct node
*currnode
= container_of(curr
, struct node
,
699 bzero(&(currnode
->route
[0]), sizeof(currnode
->route
));
700 currnode
->hopcount
= 0;
708 curr
= node_list
.next
;
709 while (curr
!= &node_list
) {
710 struct node
*currnode
= container_of(curr
, struct node
,
713 _recalc_routes(currnode
);
719 curr
= oldnodes
.next
;
720 while (curr
!= &oldnodes
) {
721 struct node
*currnode
= container_of(curr
, struct node
,
726 list_del(&(currnode
->node_list
));
728 if (currnode
->addr
!= 0) {
729 free(currnode
->addr
);
736 export_servicelist();
739 static int load_neigh_list(int fd
, struct nonblock_resumeinfo
*nr
,
742 struct libcor_nonblock_resumeinfo
*lnr
;
743 int rc
= RC_CONNBROKEN
;
745 ASSERT((fd
== 0 && nr
== 0) || (fd
!= 0 && nr
!= 0));
747 if (fd
== 0 && nr
== 0) {
748 struct epoll_event epe
;
750 fd
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RAW
);
756 rc
= connect(fd
, 0, 0);
764 nr
= (struct nonblock_resumeinfo
*)
765 malloc(sizeof(struct nonblock_resumeinfo
));
766 bzero(nr
, sizeof(struct nonblock_resumeinfo
));
768 nr
->type
= EPOLLDATA_DISCOVERNETWORK
;
769 nr
->data
.discover_network
.node
= node
;
771 bzero(&epe
, sizeof(struct epoll_event
));
772 epe
.events
= (EPOLLIN
| EPOLLOUT
| EPOLLRDHUP
| EPOLLERR
|
775 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, fd
, &epe
);
778 lnr
= &(nr
->data
.discover_network
.lnr
);
780 ASSERT(nr
->type
== EPOLLDATA_DISCOVERNETWORK
);
781 ASSERT(nr
->data
.discover_network
.node
== node
);
783 if (nr
->data
.discover_network
.state
== 1) {
785 } else if (nr
->data
.discover_network
.state
== 2) {
787 } else if (nr
->data
.discover_network
.state
== 3) {
789 } else if (nr
->data
.discover_network
.state
== 4) {
791 } else if (nr
->data
.discover_network
.state
== 5) {
793 } else if (nr
->data
.discover_network
.state
== 6) {
795 } else if (nr
->data
.discover_network
.state
== 7) {
797 } else if (nr
->data
.discover_network
.state
== 8) {
799 } else if (nr
->data
.discover_network
.state
!= 0) {
804 nr
->data
.discover_network
.list
= &localneighs
;
805 nr
->data
.discover_network
.service
= &localservices
;
807 neigh_printaddr(node
->addrlen
,
809 nr
->data
.discover_network
.list
= &(node
->routes
);
810 nr
->data
.discover_network
.service
= &(node
->services
);
812 nr
->data
.discover_network
.state
= 1;
814 rc
= connect_to_host_send(fd
, lnr
,
815 &(nr
->data
.discover_network
.connect_send
),
818 if (check_rc(rc
, "load_neigh_list: connect_to_host_send error"))
822 rc
= send_list_neigh_nonblock(fd
, lnr
);
823 nr
->data
.discover_network
.state
= 2;
824 if (check_rc(rc
, "load_neigh_list: send_list_neigh error"))
828 rc
= send_list_services_nonblock(fd
, lnr
);
829 nr
->data
.discover_network
.state
= 3;
830 if (check_rc(rc
, "load_neigh_list: send_list_services error"))
835 nr
->data
.discover_network
.state
= 4;
837 rc
= connect_to_host_recv(fd
, lnr
,
838 &(nr
->data
.discover_network
.connect_recv
),
840 if (check_rc(rc
, "load_neigh_list: connect_to_host_recv error"))
844 nr
->data
.discover_network
.state
= 5;
846 rc
= read_resp_nonblock(fd
, lnr
);
847 if (check_rc(rc
, "load_neigh_list: read_resp error"))
850 nr
->data
.discover_network
.state
= 6;
852 rc
= read_neigh_list_nonblock(fd
, lnr
, nr
->data
.discover_network
.list
,
853 init_neighlist
, add_neigh
);
854 if (check_rc(rc
, "load_neigh_list: read_neigh_list error"))
857 nr
->data
.discover_network
.state
= 7;
859 rc
= read_resp_nonblock(fd
, lnr
);
860 if (check_rc(rc
, "load_neigh_list: read_resp error"))
863 nr
->data
.discover_network
.state
= 8;
865 rc
= read_service_list_nonblock(fd
, lnr
,
866 nr
->data
.discover_network
.service
,
867 init_servicelist
, add_service
);
868 if (check_rc(rc
, "load_neigh_list: read_service_list error"))
871 #warning todo rollback node->routes and node->services on error
874 //printf("load_neigh_list state %d\n", nr->data.discover_network.state);
875 if (rc
!= RC_WOULDBLOCK
) {
876 //printf("load_neigh_list rc %d\n", rc);
886 static void discover_network(int fd
, struct nonblock_resumeinfo
*nr
)
889 struct search_query q
;
890 bzero(&q
, sizeof(struct search_query
));
891 q
.type
= SEARCHQUERY_NEIGHSNOTQUERIED
;
893 ASSERT((fd
== 0 && nr
== 0) || (fd
!= 0 && nr
!= 0));
895 #warning todo catch RC_CONNBROKEN
896 if (fd
== 0 && nr
== 0) {
897 rc
= load_neigh_list(fd
, nr
, 0);
898 if (rc
== RC_WOULDBLOCK
)
905 node
= try_find_neigh(&q
);
909 ASSERT(nr
->type
== EPOLLDATA_DISCOVERNETWORK
);
910 node
= nr
->data
.discover_network
.node
;
913 rc
= load_neigh_list(fd
, nr
, node
);
914 if (rc
== RC_WOULDBLOCK
)
916 node
->neighs_queried
= 1;
920 discover_finished
= 1;
923 static void send_unreach_error(__u64 cookie
)
926 // printf("send_rdsock_connecterror\n");
927 set_nonblock(rdsock_fd
, 0);
928 rc
= send_rdsock_connecterror(rdsock_fd
, cookie
,
929 CONNECTERROR_NETUNREACH
);
930 set_nonblock(rdsock_fd
, 1);
934 //cookie+addr are not passed on nonblocking resume
935 static void _rdscmd_connect(struct nonblock_resumeinfo
*nr
)
939 struct libcor_nonblock_resumeinfo
*lnr
= &(nr
->data
.rds_connect
.lnr
);
941 ASSERT(nr
->type
== EPOLLDATA_RDSCONNECT
);
943 if (nr
->data
.rds_connect
.state
== 1) {
945 } else if (nr
->data
.rds_connect
.state
== 2) {
947 } else if (nr
->data
.rds_connect
.state
== 3) {
949 } else if (nr
->data
.rds_connect
.state
!= 0) {
953 if (nr
->data
.rds_connect
.node
== 0)
956 rc
= connect_to_host_send(nr
->fd
, lnr
,
957 &(nr
->data
.rds_connect
.connect_send
),
958 nr
->data
.rds_connect
.node
);
959 nr
->data
.rds_connect
.state
= 1;
960 if (check_rc(rc
, "_rdscmd_connect: connect_to_host_send error"))
964 rc
= send_connect_port_nonblock(nr
->fd
, lnr
, nr
->data
.rds_connect
.port
);
965 nr
->data
.rds_connect
.state
= 2;
966 if (check_rc(rc
, "_rdscmd_connect: send_connect_port error"))
970 if (nr
->data
.rds_connect
.node
== 0)
973 rc
= connect_to_host_recv(nr
->fd
, lnr
,
974 &(nr
->data
.rds_connect
.connect_resp
),
975 nr
->data
.rds_connect
.node
);
976 if (check_rc(rc
, "_rdscmd_void_connect: connect_to_host_recv error"))
979 nr
->data
.rds_connect
.state
= 3;
981 rc
= read_resp_nonblock(nr
->fd
, lnr
);
982 if (check_rc(rc
, "_rdscmd_connect: read_resp error"))
985 rc
= pass_socket(nr
->fd
, nr
->data
.rds_connect
.cookie
);
987 printf("pass_socket error\n");
994 if (rc
== RC_WOULDBLOCK
)
999 send_unreach_error(nr
->data
.rds_connect
.cookie
);
1002 static int rdscmd_connect(void *ptr
, __u64 cookie
,
1003 struct cor_sockaddr
*addr
)
1006 struct nonblock_resumeinfo
*nr
;
1008 struct epoll_event epe
;
1011 if (addr
->sin_family
!= AF_COR
) {
1012 printf("rds_connect %llu not af_cor\n", cookie
);
1016 printf("rds_connect cookie: %llu, addr: ", cookie
);
1017 print_hex(&(addr
->addr
[0]), sizeof(addr
->addr
));
1018 printf(" port: %u\n", ntohs(addr
->port
));
1020 if (addr_eq(addr
->addr
, sizeof(addr
->addr
), 0, 0) != 0 ||
1021 addr_eq(addr
->addr
, sizeof(addr
->addr
), localaddr
,
1022 localaddrlen
) != 0) {
1024 } else if ((node
= try_find_neigh_byaddr(sizeof(addr
->addr
),
1025 &(addr
->addr
[0]))) == 0) {
1026 printf("connect_to_host host not found\n");
1031 fd
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RAW
);
1037 rc
= connect(fd
, 0, 0);
1043 set_nonblock(fd
, 1);
1045 nr
= (struct nonblock_resumeinfo
*)
1046 malloc(sizeof(struct nonblock_resumeinfo
));
1047 bzero(nr
, sizeof(struct nonblock_resumeinfo
));
1049 nr
->type
= EPOLLDATA_RDSCONNECT
;
1050 nr
->data
.rds_connect
.cookie
= cookie
;
1051 nr
->data
.rds_connect
.node
= node
;
1052 nr
->data
.rds_connect
.port
= addr
->port
;
1054 bzero(&epe
, sizeof(struct epoll_event
));
1055 epe
.events
= (EPOLLIN
| EPOLLOUT
| EPOLLRDHUP
| EPOLLERR
|
1058 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, fd
, &epe
);
1060 _rdscmd_connect(nr
);
1066 send_unreach_error(cookie
);
1071 static int proc_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
1073 if (cmd
->cmd
== CRD_KTU_CONNECT
) {
1074 return parse_rdsock_connect(0, cmd
, rdscmd_connect
);
1076 printf("error in proc_rdsock_cmd: unknown cmd: %u\n", cmd
->cmd
);
1082 static struct nonblock_resumeinfo
*_init_fwd(int fd
, __u8 is_connected
)
1084 struct nonblock_resumeinfo
*nr
=
1085 malloc(sizeof(struct nonblock_resumeinfo
));
1087 struct epoll_event epe
;
1089 bzero(nr
, sizeof(struct nonblock_resumeinfo
));
1091 nr
->type
= EPOLLDATA_FORWARD
;
1092 nr
->data
.forward
.buf
= malloc(FORWARD_BUF_SIZE
);
1093 nr
->data
.forward
.is_connected
= is_connected
;
1094 bzero(&epe
, sizeof(struct epoll_event
));
1095 epe
.events
= (EPOLLIN
| EPOLLOUT
| EPOLLRDHUP
| EPOLLERR
| EPOLLET
);
1098 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, nr
->fd
, &epe
);
1103 static void init_fwd(int fd0
, __u8 fd0connected
, int fd1
, __u8 fd1connected
)
1105 struct nonblock_resumeinfo
*dir0
= _init_fwd(fd0
, fd0connected
);
1106 struct nonblock_resumeinfo
*dir1
= _init_fwd(fd1
, fd1connected
);
1108 dir0
->data
.forward
.reversedir
= dir1
;
1109 dir1
->data
.forward
.reversedir
= dir0
;
1112 static void fwd_to_r_accept(int listenerfd
, __u8 fwd_to_host
, char *hostaddr
,
1113 __u32 hostaddrlen
, __be16 targetport
)
1118 struct cor_sockaddr addr
;
1120 __u8 remote_fd_isconnected
= 0;
1122 #warning todo remote_fd_isconnected = 1 bug
1124 localfd
= accept(listenerfd
, 0, 0);
1128 set_nonblock(localfd
, 1);
1130 if (fwd_to_host
!= 0) {
1131 if (addr_eq(hostaddr
, hostaddrlen
, 0, 0) != 0 ||
1132 addr_eq(hostaddr
, hostaddrlen
,
1133 localaddr
, localaddrlen
) != 0) {
1135 } else if ((node
= try_find_neigh_byaddr(hostaddrlen
,
1137 printf("fwd_to_r_accept host not found\n");
1141 if (service_list_contains(&(localservices
), targetport
)
1144 } else if ((node
= try_find_neigh_byservice(targetport
))
1146 printf("fwd_to_r_accept no host with service found\n");
1151 bzero(&addr
, sizeof(struct cor_sockaddr
));
1152 addr
.sin_family
= AF_COR
;
1153 addr
.port
= targetport
;
1156 if (node
->addrlen
> MAX_ADDRLEN
)
1158 memcpy(&(addr
.addr
[0]), node
->addr
, node
->addrlen
);
1162 remotefd
= socket(PF_COR
, SOCK_STREAM
, 0);
1163 if (remotefd
== -1) {
1168 set_nonblock(remotefd
, 1);
1170 if (connect(remotefd
, (struct sockaddr
*) &addr
,
1171 sizeof(struct cor_sockaddr
)) != 0) {
1172 if (errno
== EINPROGRESS
) {
1173 remote_fd_isconnected
= 0;
1180 init_fwd(localfd
, 1, remotefd
, remote_fd_isconnected
);
1189 static void fwd_to_lservice_accept(int listenerfd
, int af
,
1190 struct sockaddr
*saddr
, socklen_t saddrlen
)
1195 __u8 remote_fd_isconnected
= 1;
1197 localfd
= accept(listenerfd
, 0, 0);
1202 set_nonblock(localfd
, 1);
1204 remotefd
= socket(af
, SOCK_STREAM
, 0);
1205 if (remotefd
== -1) {
1210 set_nonblock(remotefd
, 1);
1212 if (connect(remotefd
, saddr
, saddrlen
) != 0) {
1213 if (errno
== EINPROGRESS
) {
1214 remote_fd_isconnected
= 0;
1221 init_fwd(localfd
, 1, remotefd
, remote_fd_isconnected
);
1232 #define RC_FORWARD_OK 1
1233 #define RC_FORWARD_WOULDBLOCK 2
1234 #define RC_FORWARD_ERROR 3
1236 static int forward_write(struct nonblock_resumeinfo
*nr
)
1238 __u32 buffill
= nr
->data
.forward
.buffill
;
1241 ASSERT(buffill
<= FORWARD_BUF_SIZE
);
1242 ASSERT(nr
->data
.forward
.bufwritten
<= buffill
);
1244 if (buffill
== FORWARD_BUF_SIZE
) {
1249 while (nr
->data
.forward
.bufwritten
< buffill
) {
1250 int rc
= send(nr
->fd
, nr
->data
.forward
.buf
+
1251 nr
->data
.forward
.bufwritten
,
1252 buffill
- nr
->data
.forward
.bufwritten
,
1253 more
== 0 ? 0 : MSG_MORE
);
1255 if (rc
< 0 && (errno
== EAGAIN
||
1256 errno
== EWOULDBLOCK
)) {
1257 return RC_FORWARD_WOULDBLOCK
;
1258 } else if (rc
<= 0) {
1262 perror("forward_write");
1263 return RC_FORWARD_ERROR
;
1265 nr
->data
.forward
.bufwritten
+= rc
;
1266 ASSERT(nr
->data
.forward
.bufwritten
<= buffill
);
1270 return RC_FORWARD_OK
;
1273 static int forward_read(struct nonblock_resumeinfo
*nr
)
1275 int readfd
= nr
->data
.forward
.reversedir
->fd
;
1278 ASSERT(nr
->data
.forward
.bufwritten
<= nr
->data
.forward
.buffill
);
1280 if (nr
->data
.forward
.bufwritten
== nr
->data
.forward
.buffill
) {
1281 nr
->data
.forward
.buffill
= 0;
1282 nr
->data
.forward
.bufwritten
= 0;
1283 } else if (nr
->data
.forward
.bufwritten
* 3 > nr
->data
.forward
.buffill
) {
1284 memmove(nr
->data
.forward
.buf
, nr
->data
.forward
.buf
+
1285 nr
->data
.forward
.bufwritten
,
1286 nr
->data
.forward
.buffill
-
1287 nr
->data
.forward
.bufwritten
);
1288 nr
->data
.forward
.buffill
-= nr
->data
.forward
.bufwritten
;
1289 nr
->data
.forward
.bufwritten
= 0;
1292 if (nr
->data
.forward
.buffill
== FORWARD_BUF_SIZE
)
1293 return RC_FORWARD_OK
;
1295 while (nr
->data
.forward
.buffill
< FORWARD_BUF_SIZE
) {
1296 rc
= recv(readfd
, nr
->data
.forward
.buf
+
1297 nr
->data
.forward
.buffill
,
1298 FORWARD_BUF_SIZE
- nr
->data
.forward
.buffill
, 0);
1302 return RC_FORWARD_OK
;
1303 } else if (rc
< 0) {
1304 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
) {
1305 return RC_FORWARD_WOULDBLOCK
;
1306 } else if (errno
== EINTR
) {
1309 perror("forward_read");
1310 return RC_FORWARD_ERROR
;
1313 nr
->data
.forward
.buffill
+= rc
;
1314 ASSERT(nr
->data
.forward
.buffill
<= FORWARD_BUF_SIZE
);
1318 return RC_FORWARD_OK
;
1321 static void _forward(struct nonblock_resumeinfo
*nr
)
1326 rc
= forward_read(nr
);
1327 if (rc
== RC_FORWARD_ERROR
)
1329 if (nr
->data
.forward
.bufwritten
== nr
->data
.forward
.buffill
)
1332 rc
= forward_write(nr
);
1333 if (rc
== RC_FORWARD_ERROR
)
1335 else if (rc
== RC_FORWARD_WOULDBLOCK
)
1339 #warning todo call EPOLL_CTL_DEL + free where needed (some places calling close do not)
1342 epoll_ctl(epoll_fd
, EPOLL_CTL_DEL
,
1343 nr
->data
.forward
.reversedir
->fd
, 0);
1344 close(nr
->data
.forward
.reversedir
->fd
);
1345 epoll_ctl(epoll_fd
, EPOLL_CTL_DEL
, nr
->fd
, 0);
1348 #warning todo free after all events are processed
1349 /* free(nr->data.forward.reversedir);
1355 static void forward(struct nonblock_resumeinfo
*nr
, __u32 eventflags
)
1357 ASSERT(nr
->type
== EPOLLDATA_FORWARD
);
1358 ASSERT(nr
->data
.forward
.reversedir
->type
== EPOLLDATA_FORWARD
);
1360 if ((eventflags
& EPOLLOUT
) != 0)
1361 nr
->data
.forward
.is_connected
= 1;
1363 if (nr
->data
.forward
.is_connected
== 0 ||
1364 nr
->data
.forward
.reversedir
->data
.forward
.is_connected
1369 _forward(nr
->data
.forward
.reversedir
);
1372 static void nonblock_resume(struct nonblock_resumeinfo
*nr
, __u32 eventflags
)
1374 if (nr
->type
== EPOLLDATA_DISCOVERNETWORK
) {
1375 int rc
= resume_send_ifneeded(nr
->fd
,
1376 &(nr
->data
.discover_network
.lnr
));
1378 //printf("load_neigh_list state = %d rc = %d\n", nr->data.discover_network.state, rc);
1383 discover_network(nr
->fd
, nr
);
1384 } else if (nr
->type
== EPOLLDATA_RDSCONNECT
) {
1385 int rc
= resume_send_ifneeded(nr
->fd
,
1386 &(nr
->data
.discover_network
.lnr
));
1391 _rdscmd_connect(nr
);
1392 } else if (nr
->type
== EPOLLDATA_RDSOCKCMD
) {
1393 struct rdsock_cmd cmd
;
1395 int rc
= resume_send_ifneeded(nr
->fd
,
1396 &(nr
->data
.rdsock_cmd
.lnr
));
1401 rc
= read_rdsock_cmd_nonblock(rdsock_fd
,
1402 &(nr
->data
.rdsock_cmd
.lnr
), &cmd
);
1403 ASSERT(rc
!= RC_CONNBROKEN
);
1404 if (rc
== RC_WOULDBLOCK
)
1407 rc
= proc_rdsock_cmd(rdsock_fd
, &cmd
);
1408 free_rdsockcmd_data(&cmd
);
1410 } else if (nr
->type
== EPOLLDATA_FWD_TO_R
) {
1411 fwd_to_r_accept(nr
->fd
, nr
->data
.fwd_to_r
.fwd_to_host
,
1412 nr
->data
.fwd_to_r
.addr
,
1413 nr
->data
.fwd_to_r
.addrlen
,
1414 nr
->data
.fwd_to_r
.targetport
);
1415 } else if (nr
->type
== EPOLLDATA_FWD_TO_LSERVICE
) {
1416 fwd_to_lservice_accept(nr
->fd
, nr
->data
.fwd_to_lservice
.af
,
1417 nr
->data
.fwd_to_lservice
.saddr
,
1418 nr
->data
.fwd_to_lservice
.saddrlen
);
1419 } else if (nr
->type
== EPOLLDATA_FORWARD
) {
1420 forward(nr
, eventflags
);
1426 static int rdsock_negotiate_version(void)
1428 struct rdsock_cmd cmd
;
1429 __u32 versionmin
= 1000;
1430 __u32 versionmax
= 0;
1433 rc
= read_rdsock_cmd(rdsock_fd
, &cmd
);
1435 printf("read_rdsock_cmd rc = %d\n", rc
);
1439 if (cmd
.cmd
!= CRD_KTU_SUPPORTEDVERSIONS
) {
1440 printf("rhsock supportedversions not sent\n", rc
);
1444 rc
= parse_rdsock_supported_versions(&cmd
, &versionmin
, &versionmax
);
1446 printf("parse_rdsock_supported_versions rc = %d\n", rc
);
1450 /* printf("rdsock_negotiate_version versionmin %u versionmax %u\n",
1451 versionmin, versionmax); */
1453 if (versionmin
!= 0) {
1454 printf("rdsock_negotiate_version versionmin of kernel is %u, "
1455 "but needs to be 0\n"
1456 "You probably need to upgrade corutils or "
1457 "downgrade the kernel\n", versionmin
);
1461 rc
= send_rdsock_version(rdsock_fd
, 0);
1462 ASSERT(rc
== RC_OK
);
1467 static void epoll_add_fwd_to_r(struct list_head
*r_fwds
)
1469 while (list_empty(r_fwds
) == 0) {
1470 struct fwd_to_r_item
*item
= container_of(r_fwds
->next
,
1471 struct fwd_to_r_item
, allfwds
);
1473 struct nonblock_resumeinfo
*nr
;
1475 struct epoll_event epe
;
1477 set_nonblock(item
->bindfd
, 1);
1479 nr
= malloc(sizeof(struct nonblock_resumeinfo
));
1480 bzero(nr
, sizeof(struct nonblock_resumeinfo
));
1481 nr
->fd
= item
->bindfd
;
1482 nr
->type
= EPOLLDATA_FWD_TO_R
;
1483 nr
->data
.fwd_to_r
.fwd_to_host
= item
->fwd_to_host
;
1484 nr
->data
.fwd_to_r
.addr
= item
->addr
;
1485 nr
->data
.fwd_to_r
.addrlen
= item
->addrlen
;
1486 nr
->data
.fwd_to_r
.targetport
= item
->targetport
;
1487 bzero(&epe
, sizeof(struct epoll_event
));
1488 epe
.events
= (EPOLLIN
| EPOLLERR
);
1491 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, item
->bindfd
, &epe
);
1493 list_del(&(item
->allfwds
));
1498 static void epoll_add_fwd_to_lservice(struct list_head
*lservice_fwds
)
1500 while (list_empty(lservice_fwds
) == 0) {
1501 struct fwd_to_lservice_item
*item
= container_of(
1502 lservice_fwds
->next
,
1503 struct fwd_to_lservice_item
,
1506 struct nonblock_resumeinfo
*nr
;
1508 struct epoll_event epe
;
1510 set_nonblock(item
->bindfd
, 1);
1512 nr
= malloc(sizeof(struct nonblock_resumeinfo
));
1513 bzero(nr
, sizeof(struct nonblock_resumeinfo
));
1514 nr
->fd
= item
->bindfd
;
1515 nr
->type
= EPOLLDATA_FWD_TO_LSERVICE
;
1516 nr
->data
.fwd_to_lservice
.af
= item
->af
;
1517 nr
->data
.fwd_to_lservice
.saddr
= item
->saddr
;
1518 nr
->data
.fwd_to_lservice
.saddrlen
= item
->saddrlen
;
1519 bzero(&epe
, sizeof(struct epoll_event
));
1520 epe
.events
= (EPOLLIN
| EPOLLERR
);
1523 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, item
->bindfd
, &epe
);
1525 list_del(&(item
->allfwds
));
1531 static int parse_hexchar(char c
)
1553 else if (c
== 'A' || c
== 'a')
1555 else if (c
== 'B' || c
== 'b')
1557 else if (c
== 'C' || c
== 'c')
1559 else if (c
== 'D' || c
== 'd')
1561 else if (c
== 'E' || c
== 'e')
1563 else if (c
== 'F' || c
== 'f')
1569 static int parse_hex(char *target
, char *src
, int srclen
)
1574 ASSERT(target
!= 0);
1576 ASSERT((srclen
%2) == 0);
1578 for(u
=0;u
<(srclen
/2);u
++) {
1579 int high
= parse_hexchar(src
[u
*2]);
1580 int low
= parse_hexchar(src
[u
*2+1]);
1582 if (high
== -1 || low
== -1)
1585 target
[u
] = (char) ((high
<< 4) + low
);
1591 static int _parse_addr(char *arg
, size_t arg_len
, char **addr
, __u32
*addrlen
,
1594 char *noaddr
= "noaddr";
1596 if (arg_len
> 1048576)
1599 if (noaddr_allowed
!= 0 && arg_len
== 6 && memcmp(arg
, noaddr
, 6) == 0){
1605 if ((arg_len
< 2) || (arg_len
%2) != 0)
1608 *addr
= malloc(arg_len
/2);
1609 *addrlen
= arg_len
/2;
1611 if (parse_hex(*addr
, arg
, arg_len
) != 0)
1617 fprintf(stderr
, "error: argv_addr is not a valid address (contains "
1618 "non-hex characters or number of hex characters is not "
1619 "a multiple of 2)\n");
1623 static size_t _parse_addr_lastarglen(char *arg
, size_t len
)
1625 size_t lastarglen
= 0;
1627 while (lastarglen
< len
) {
1628 if (arg
[len
-lastarglen
-1] == ':')
1635 static int parse_addr(char *arg
, size_t arg_len
, size_t *arg_addrlen
,
1636 char **addr
, __u32
*addrlen
)
1638 size_t lastarglen
= _parse_addr_lastarglen(arg
, arg_len
);
1640 if (lastarglen
== 0 || lastarglen
>= arg_len
)
1643 *arg_addrlen
= lastarglen
+ 1; // +1 ... ':'
1645 return _parse_addr(arg
+ arg_len
- lastarglen
, lastarglen
,
1649 static int _parse_port(char *arg
, size_t len
, __u16
*port
)
1654 long int tmpport
= 0;
1656 tmpbuf
= malloc(len
+1);
1657 memcpy(tmpbuf
, arg
, len
);
1660 tmpport
= strtol(tmpbuf
, &endptr
, 10);
1661 if (tmpbuf
[0] == 0 || endptr
== 0 || endptr
!= tmpbuf
+ len
) {
1669 if (tmpport
<= 0 || tmpport
>= 65536)
1672 *port
= (__u16
) tmpport
;
1677 static int parse_port_firstarg(char *arg
, size_t len
, size_t *p_portlen
,
1682 while (portlen
< len
) {
1683 if (arg
[portlen
] == ':')
1688 if (portlen
== 0 || portlen
>= len
)
1691 if (_parse_port(arg
, portlen
, port
) != 0)
1694 *p_portlen
= portlen
+ 1;// +1 ... ':'
1698 static int parse_port_lastarg(char *arg
, size_t len
, size_t *p_portlen
,
1703 portlen
= _parse_addr_lastarglen(arg
, len
);
1705 if (portlen
== 0 || portlen
>= len
)
1708 if (_parse_port(arg
+ len
- portlen
, portlen
, port
) != 0)
1711 *p_portlen
= portlen
+ 1;// +1 ... ':'
1715 static int parse_inetaddr(char *addr
, size_t len
, int *af
,
1716 struct sockaddr
**saddr
, socklen_t
*saddrlen
)
1724 struct in_addr inaddr
;
1725 struct in6_addr in6addr
;
1727 if (parse_port_lastarg(addr
, len
, &portlen
, &port
) != 0)
1733 host
= malloc(len
- portlen
+ 1);
1734 memcpy(host
, addr
, len
- portlen
);
1735 host
[len
- portlen
] = 0;
1737 if (inet_pton(AF_INET
, host
, &inaddr
) == 1) {
1738 struct sockaddr_in
*ret
;
1743 ret
= malloc(sizeof(struct sockaddr_in
));
1744 bzero(ret
, sizeof(struct sockaddr_in
));
1746 ret
->sin_family
= AF_INET
;
1747 ret
->sin_port
= htons(port
);
1748 memcpy(&(ret
->sin_addr
), &inaddr
, sizeof(inaddr
));
1751 *saddr
= (struct sockaddr
*) ret
;
1752 *saddrlen
= sizeof(struct sockaddr_in
);
1755 } else if (inet_pton(AF_INET6
, host
, &in6addr
) == 1) {
1759 printf("sorry IPv6 support is not implemented yet\n");
1769 static int parse_fwd_to_r(char *argv_fwd
,
1770 struct list_head
*r_fwds
, __u8 fwd_to_host
)
1772 struct fwd_to_r_item
*item
;
1774 struct sockaddr
*saddr
;
1783 size_t len
= strlen(argv_fwd
);
1787 if (parse_port_lastarg(argv_fwd
, len
, &portlen
, &serviceport
) != 0)
1792 if (fwd_to_host
!= 0) {
1793 size_t arg_addrlen
= 0;
1794 if (parse_addr(argv_fwd
, len
, &arg_addrlen
,
1795 &addr
, &addrlen
) != 0)
1800 if (parse_inetaddr(argv_fwd
, len
, &af
, &saddr
, &saddrlen
) != 0)
1803 item
= malloc(sizeof(struct fwd_to_r_item
));
1804 item
->bindfd
= socket(af
, SOCK_STREAM
, 0);
1805 if (item
->bindfd
< 0) {
1810 if (setsockopt(item
->bindfd
, SOL_SOCKET
, SO_REUSEADDR
, &optval
,
1811 sizeof(optval
)) != 0) {
1812 perror("setsockopt");
1815 if (bind(item
->bindfd
, saddr
, saddrlen
) != 0) {
1819 if (listen(item
->bindfd
, 100) != 0) {
1823 item
->fwd_to_host
= fwd_to_host
;
1826 item
->addrlen
= addrlen
;
1828 item
->targetport
= htons(serviceport
);
1830 list_add_tail(&(item
->allfwds
), r_fwds
);
1837 close(item
->bindfd
);
1845 static int parse_fwd_to_lservice(char *argv_fwd
,
1846 struct list_head
*lservice_fwds
, __u8 publish
)
1852 struct cor_sockaddr bind_saddr
;
1856 struct fwd_to_lservice_item
*item
;
1859 struct sockaddr
*saddr
;
1862 size_t len
= strlen(argv_fwd
);
1864 if (parse_port_firstarg(argv_fwd
, len
, &portlen
, &serviceport
) != 0)
1867 argv_fwd
+= portlen
;
1870 if (parse_inetaddr(argv_fwd
, len
, &af
, &saddr
, &saddrlen
) != 0)
1873 memset(&bind_saddr
, 0, sizeof(struct cor_sockaddr
));
1874 bind_saddr
.sin_family
= AF_COR
;
1875 bind_saddr
.port
= htons(serviceport
);
1879 item
= malloc(sizeof(struct fwd_to_lservice_item
));
1880 item
->bindfd
= socket(PF_COR
, SOCK_STREAM
, 0);
1881 if (item
->bindfd
< 0) {
1885 optval
= publish
== 0 ? 0 : 1;
1886 if (setsockopt(item
->bindfd
, SOL_COR
, COR_PUBLISH_SERVICE
, &optval
,
1887 sizeof(optval
)) != 0) {
1888 perror("setsockopt");
1891 if (bind(item
->bindfd
, (struct sockaddr
*) &bind_saddr
,
1892 sizeof(bind_saddr
)) != 0) {
1896 if (listen(item
->bindfd
, 100) != 0) {
1902 item
->saddr
= saddr
;
1903 item
->saddrlen
= saddrlen
;
1905 list_add_tail(&(item
->allfwds
), lservice_fwds
);
1910 close(item
->bindfd
);
1918 static int parse_args(int argc
, char *argv
[], struct list_head
*r_fwds
,
1919 struct list_head
*lservice_fwds
)
1923 __u32 argsconsumed
= 0;
1929 if (argc
<= argsconsumed
+ 1)
1932 if (strcmp(argv
[argsconsumed
+ 1], "--addr") == 0) {
1933 if (argc
<= argsconsumed
+ 2)
1939 rc
= _parse_addr(argv
[argsconsumed
+ 2],
1940 strlen(argv
[argsconsumed
+ 2]),
1941 &localaddr
, &localaddrlen
, 1);
1948 } else if (strcmp(argv
[argsconsumed
+ 1],
1949 "--export-servicelist") == 0) {
1950 export_servicelist_enabled
= 1;
1953 } else if (strcmp(argv
[argsconsumed
+ 1],
1954 "--fwd-to-rservice") == 0) {
1955 if (argc
<= argsconsumed
+ 2)
1958 rc
= parse_fwd_to_r(argv
[argsconsumed
+ 2],
1964 } else if (strcmp(argv
[argsconsumed
+ 1],
1965 "--fwd-to-rhost") == 0) {
1966 if (argc
<= argsconsumed
+ 2)
1969 rc
= parse_fwd_to_r(argv
[argsconsumed
+ 2],
1975 } else if (strcmp(argv
[argsconsumed
+ 1],
1976 "--fwd-to-lservice") == 0) {
1977 if (argc
<= argsconsumed
+ 2)
1980 rc
= parse_fwd_to_lservice(argv
[argsconsumed
+ 2],
1985 } else if (strcmp(argv
[argsconsumed
+ 1],
1986 "--fwd-to-lservice-pub") == 0) {
1987 if (argc
<= argsconsumed
+ 2)
1990 rc
= parse_fwd_to_lservice(argv
[argsconsumed
+ 2],
2006 fprintf(stderr
, "usage: test_routed2"
2007 " [--export-servicelist]"
2008 " [--fwd-to-rservice bindaddr:bindport:remoteport]"
2009 " [--fwd-to-rhost bindaddr:bindport:remotaaddr:remoteport]"
2010 " [--fwd-to-lservice bindport:localaddr:localport]"
2011 " [--fwd-to-lservice-pub bindport:localaddr:localport]"
2012 " --addr addr (even number of hex digits or noaddr)\n");
2019 int main(int argc
, char *argv
[])
2022 struct list_head r_fwds
;
2023 struct list_head lservice_fwds
;
2025 struct nonblock_resumeinfo rds_nr
;
2027 int discover_finished_executed
= 0;
2029 discover_finished
= 0;
2032 init_list_head(&r_fwds
);
2033 init_list_head(&lservice_fwds
);
2037 rc
= parse_args(argc
, argv
, &r_fwds
, &lservice_fwds
);
2042 init_list_head(&node_list
);
2044 epoll_fd
= epoll_create(1);
2045 if (epoll_fd
<= 0) {
2046 perror("epoll_create");
2051 rdsock_fd
= socket(PF_COR
, SOCK_RAW
, PROTO_COR_RDEAMON
);
2052 if (rdsock_fd
< 0) {
2057 rc
= connect(rdsock_fd
, 0, 0);
2063 rc
= rdsock_negotiate_version();
2067 rc
= send_rdsock_up(rdsock_fd
, localaddr
, localaddrlen
);
2068 ASSERT(rc
== RC_OK
);
2070 set_nonblock(rdsock_fd
, 1);
2072 epoll_add_fwd_to_lservice(&lservice_fwds
);
2076 discover_network(0, 0);
2080 struct epoll_event events
[EPOLL_EVENTS
];
2083 if (discover_finished_executed
== 0 && discover_finished
!= 0) {
2084 struct epoll_event rds_epe
;
2086 bzero(&rds_nr
, sizeof(struct nonblock_resumeinfo
));
2087 rds_nr
.fd
= rdsock_fd
;
2088 rds_nr
.type
= EPOLLDATA_RDSOCKCMD
;
2089 bzero(&rds_epe
, sizeof(struct epoll_event
));
2090 rds_epe
.events
= (EPOLLIN
| EPOLLRDHUP
| EPOLLERR
);
2091 rds_epe
.data
.ptr
= &rds_nr
;
2093 epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, rdsock_fd
, &rds_epe
);
2095 epoll_add_fwd_to_r(&r_fwds
);
2097 discover_finished_executed
= 1;
2098 printf("discover finished\n");
2101 rdycnt
= epoll_wait(epoll_fd
, events
, EPOLL_EVENTS
, -1);
2103 for (u
=0;u
<rdycnt
;u
++) {
2104 struct nonblock_resumeinfo
*nr
= events
[u
].data
.ptr
;
2105 __u32 eventflags
= events
[u
].events
;
2106 nonblock_resume(nr
, eventflags
);