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
23 #include <linux/types.h>
31 #define likely(x) __builtin_expect((x), 1)
32 #define unlikely(x) __builtin_expect((x), 0)
35 #define CD_CONNECT_NB 1
36 #define CD_CONNECT_PORT 2
37 #define CD_LIST_NEIGH 3
38 #define CD_LIST_SERVICES 4
42 #define CDR_EXECFAILED 2
43 #define CDR_EXECFAILED_INVALID_COMMAND 1
44 #define CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES 2
45 #define CDR_EXECFAILED_NB_DOESNTEXIST 3
46 #define CDR_EXECFAILED_PORTCLOSED 4
50 #define LIST_NEIGH_FIELD_ADDR 1
51 #define LIST_NEIGH_FIELD_LATENCY 2
54 static int bzero_nr_iffinished(struct libcor_nonblock_resumeinfo
*nr
, int rc
)
56 /*if (rc == RC_WOULDBLOCK) {
57 printf("wouldblock\n");
60 if (rc
!= RC_WOULDBLOCK
) {
61 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
66 #define LIBCOR_ASSERT_ERR() \
75 static __u64 htonll(__u64 in)
78 char *p_out
= (char *) &out
;
99 static __u64
ntohll(__u64 in
)
102 char *p_in
= (char *) &in
;
123 #warning todo commands are sent via multiple packets
124 int resume_send(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
126 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!=fd
))
129 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
||
130 unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
133 while (nr
->data
.write
.totalsent
< nr
->data
.write
.len
) {
134 char *buf
= &(nr
->data
.write
.buf
[0]);
135 int sent
= send(fd
, buf
+ nr
->data
.write
.totalsent
,
136 nr
->data
.write
.len
- nr
->data
.write
.totalsent
,
139 if (sent
< 0 && (errno
== EAGAIN
||
140 errno
== EWOULDBLOCK
))
141 return bzero_nr_iffinished(nr
, RC_WOULDBLOCK
);
148 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
151 nr
->data
.write
.totalsent
+= sent
;
154 return bzero_nr_iffinished(nr
, RC_OK
);
157 static int read_fully(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
158 char *buf
, __u32 len
, __u32
*maxread
)
162 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
165 if (unlikely(nr
->data
.read
.read_fully
.state
!= 0 && (
166 nr
->data
.read
.read_fully
.fd
!= fd
||
167 nr
->data
.read
.read_fully
.buf
!= buf
||
168 nr
->data
.read
.read_fully
.len
!= len
||
169 nr
->data
.read
.read_fully
.maxread
!= maxread
)))
172 if (nr
->data
.read
.read_fully
.state
== 1) {
174 } else if (unlikely(nr
->data
.read
.read_fully
.state
!= 0)) {
178 nr
->data
.read
.read_fully
.fd
= fd
;
179 nr
->data
.read
.read_fully
.buf
= buf
;
180 nr
->data
.read
.read_fully
.len
= len
;
181 nr
->data
.read
.read_fully
.maxread
= maxread
;
182 nr
->data
.read
.read_fully
.totalread
= 0;
184 nr
->data
.read
.read_fully
.state
= 1;
188 if (len
> (*maxread
)) {
189 printf("error in read_fully: maxread reached\n");
196 while (len
> nr
->data
.read
.read_fully
.totalread
) {
197 int rcvd
= recv(fd
, buf
+ nr
->data
.read
.read_fully
.totalread
,
198 len
- nr
->data
.read
.read_fully
.totalread
, 0);
201 if (rcvd
< 0 && (errno
== EAGAIN
||
202 errno
== EWOULDBLOCK
)) {
204 /* printf("wouldblock\n"); */
217 /*printf("rcvd: %d:", rcvd);
218 for(u=0;u<rcvd;u++) {
219 printf(" %d, ", (__s32) ((__u8) buf[totalread+u]));
223 nr
->data
.read
.read_fully
.totalread
+= (__u32
) rcvd
;
227 if (rc
!= RC_WOULDBLOCK
) {
228 bzero(&(nr
->data
.read
.read_fully
),
229 sizeof(nr
->data
.read
.read_fully
));
235 static int read_discard(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
241 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
244 if (unlikely(nr
->data
.read
.read_discard
.state
!= 0 && (
245 nr
->data
.read
.read_discard
.fd
!= fd
||
246 nr
->data
.read
.read_discard
.len
!= len
)))
249 if (nr
->data
.read
.read_discard
.state
== 1) {
251 } else if (unlikely(nr
->data
.read
.read_discard
.state
!= 0)) {
255 nr
->data
.read
.read_discard
.fd
= fd
;
256 nr
->data
.read
.read_discard
.len
= len
;
257 nr
->data
.read
.read_discard
.discarded
= 0;
260 nr
->data
.read
.read_discard
.state
= 1;
266 __u32 rcvlen
= len
- nr
->data
.read
.read_discard
.discarded
;
270 rcvd
= recv(fd
, buf
, rcvlen
, 0);
272 if (rcvd
< 0 && (errno
== EAGAIN
||
273 errno
== EWOULDBLOCK
)) {
287 nr
->data
.read
.read_discard
.discarded
-= rcvd
;
291 if (rc
!= RC_WOULDBLOCK
) {
292 bzero(&(nr
->data
.read
.read_discard
),
293 sizeof(nr
->data
.read
.read_discard
));
299 static int encode_len(char *buf
, int buflen
, __u32 len
)
301 if (unlikely(buf
== 0))
304 if (unlikely(buflen
< 4))
313 buf
[0] = (__u8
) ((len
- 128) /256 + 128);
314 buf
[1] = (__u8
) ((len
- 128) & 255);
318 if (len
< 1073741951) {
319 __u32 len_be
= htonl(len
- 16511);
320 char *len_p
= (char *) &len_be
;
322 buf
[0] = len_p
[0] + 192;
332 static int decode_len(char *buf
, int buflen
, __u32
*len
)
334 if (unlikely(buflen
< 1))
337 if ((__u8
) buf
[0] <= 127) {
338 *len
= (__u8
) buf
[0];
345 if ((__u8
) buf
[0] <= 191) {
346 *len
= 128 + ((__u32
) ((__u8
) buf
[0]) - 128) * 256 +
354 ((char *) len
)[0] = buf
[0] - 192;
355 ((char *) len
)[1] = buf
[1];
356 ((char *) len
)[2] = buf
[2];
357 ((char *) len
)[3] = buf
[3];
359 *len
= ntohl(*len
) + 16511;
364 static int read_len(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
365 __u32
*len
, __u32
*maxread
)
367 int rc
= RC_CONNBROKEN
;
369 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
372 if (unlikely(nr
->data
.read
.read_len
.state
!= 0 && (
373 nr
->data
.read
.read_len
.fd
!= fd
||
374 nr
->data
.read
.read_len
.len
!= len
||
375 nr
->data
.read
.read_len
.maxread
!= maxread
)))
378 if (sizeof(nr
->data
.read
.read_len
.buf
) != 4)
381 if (nr
->data
.read
.read_len
.state
== 1) {
383 } else if (unlikely(nr
->data
.read
.read_len
.state
!= 0)) {
387 nr
->data
.read
.read_len
.fd
= fd
;
388 nr
->data
.read
.read_len
.len
= len
;
389 nr
->data
.read
.read_len
.maxread
= maxread
;
390 bzero(&(nr
->data
.read
.read_len
.buf
[0]), 4);
391 nr
->data
.read
.read_len
.read
= 0;
395 nr
->data
.read
.read_len
.state
= 1;
397 if (nr
->data
.read
.read_len
.read
>= 4) {
398 printf("error in readlen: read to high\n");
403 rc
= read_fully(fd
, nr
, &(nr
->data
.read
.read_len
.buf
[0]) +
404 nr
->data
.read
.read_len
.read
, 1, maxread
);
408 nr
->data
.read
.read_len
.read
++;
410 rc
= decode_len(&(nr
->data
.read
.read_len
.buf
[0]),
411 nr
->data
.read
.read_len
.read
, len
);
413 if (unlikely(rc
< nr
->data
.read
.read_len
.read
)) {
414 printf("error in readlen: decode_len has not "
415 "consumed the whole buffer\n");
425 if (rc
!= RC_WOULDBLOCK
) {
426 bzero(&(nr
->data
.read
.read_len
),
427 sizeof(nr
->data
.read
.read_len
));
433 static int _send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
, __u16 cmd
)
440 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!= fd
))
444 buf
[0] = ((char *) &cmd
)[0];
445 buf
[1] = ((char *) &cmd
)[1];
447 rc
= encode_len(&(buf
[2]), 4, nr
->data
.write
.len
);
448 if (rc
<= 0 || rc
> 4)
451 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
454 hdrlen
= 2 + ((__u32
) rc
);
456 if (unlikely(nr
->data
.write
.len
+ hdrlen
< nr
->data
.write
.len
||
457 nr
->data
.write
.len
+ hdrlen
> WRITE_BUF_SIZE
))
460 memmove(&(nr
->data
.write
.buf
[hdrlen
]), &(nr
->data
.write
.buf
[0]),
462 memcpy(&(nr
->data
.write
.buf
[0]), &(buf
[0]), hdrlen
);
463 nr
->data
.write
.len
+= hdrlen
;
465 return resume_send(fd
, nr
);
468 static int send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
469 __u16 cmd
, char *buf
, __u32 len
)
471 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
474 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
475 nr
->type
= RESUME_TYPE_WRITE
;
476 nr
->data
.write
.fd
= fd
;
478 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
481 if (unlikely(WRITE_BUF_SIZE
< len
))
485 memcpy(&(nr
->data
.write
.buf
[0]), buf
, len
);
486 nr
->data
.write
.len
= len
;
489 return _send_cmd(fd
, nr
, cmd
);
492 int read_resp_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
496 struct libcor_nonblock_resumeinfo_resp
*nr_resp
=
497 &(nr
->data
.read
.funcdata
.resp
);
499 if (nr
->type
== RESUME_TYPE_NONE
) {
500 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
501 nr
->type
= RESUME_TYPE_READ
;
502 nr
->data
.read
.functype
= RESUME_READ_FUNC_RESP
;
504 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
505 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RESP
)) {
507 } else if (unlikely(nr_resp
->fd
!= fd
)) {
510 __u8 state
= nr_resp
->state
;
514 } else if (unlikely(state
!= 0)) {
519 nr_resp
->respcode
= 0;
520 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->respcode
), 1, 0);
523 return bzero_nr_iffinished(nr
, rc
);
525 if (nr_resp
->respcode
== CDR_EXECFAILED
) {
526 /* printf("crd_execfailed\n"); */
528 nr_resp
->reasoncode
= 0;
532 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->reasoncode
), 2, 0);
534 return bzero_nr_iffinished(nr
, rc
);
536 nr_resp
->reasoncode
= ntohs(nr_resp
->reasoncode
);
538 printf("execfailed: reasoncode = %d\n", (__s32
)
539 nr_resp
->reasoncode
);
542 //printf("read_resp: respcode = %d\n", nr_resp->respcode);
544 if (nr_resp
->respcode
== CDR_EXECOK
)
545 return bzero_nr_iffinished(nr
, RC_OK
);
547 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
550 int read_resp(int fd
)
552 int rc
= RC_WOULDBLOCK
;
553 struct libcor_nonblock_resumeinfo nr
;
554 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
556 rc
= read_resp_nonblock(fd
, &nr
);
557 if (unlikely(rc
== RC_WOULDBLOCK
)) {
559 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
565 int send_connect_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
566 __u32 addrlen
, char *addr
)
571 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
574 if (unlikely(addrlen
> (1024 * 1024 * 1024) ||
575 addrlen
+ 4 > WRITE_BUF_SIZE
))
578 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
579 nr
->type
= RESUME_TYPE_WRITE
;
580 nr
->data
.write
.fd
= fd
;
582 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
585 if (unlikely(WRITE_BUF_SIZE
< 4))
588 rc
= encode_len(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), 4, addrlen
);
589 if (unlikely(rc
<= 0 || rc
> 4))
592 nr
->data
.write
.len
+= (__u32
) rc
;
594 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
||
595 WRITE_BUF_SIZE
- nr
->data
.write
.len
< addrlen
))
598 memcpy(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), addr
, addrlen
);
599 nr
->data
.write
.len
+= addrlen
;
601 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
604 return _send_cmd(fd
, nr
, CD_CONNECT_NB
);
607 int send_connect_neigh(int fd
, __u32 addrlen
, char *addr
)
609 int rc
= RC_WOULDBLOCK
;
610 struct libcor_nonblock_resumeinfo nr
;
611 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
613 rc
= send_connect_neigh_nonblock(fd
, &nr
, addrlen
, addr
);
614 if (unlikely(rc
== RC_WOULDBLOCK
)) {
616 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
621 int send_connect_port_nonblock(int fd
,
622 struct libcor_nonblock_resumeinfo
*nr
, __be16 port
)
624 return send_cmd(fd
, nr
, CD_CONNECT_PORT
, (char *) &port
, 2);
627 int send_connect_port(int fd
, __be16 port
)
629 int rc
= RC_WOULDBLOCK
;
630 struct libcor_nonblock_resumeinfo nr
;
631 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
633 rc
= send_connect_port_nonblock(fd
, &nr
, port
);
634 if (unlikely(rc
== RC_WOULDBLOCK
)) {
636 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
641 int send_list_services_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
643 return send_cmd(fd
, nr
, CD_LIST_SERVICES
, 0, 0);
646 int send_list_services(int fd
)
648 int rc
= RC_WOULDBLOCK
;
649 struct libcor_nonblock_resumeinfo nr
;
650 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
652 rc
= send_list_services_nonblock(fd
, &nr
);
653 if (unlikely(rc
== RC_WOULDBLOCK
)) {
655 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
660 int read_service_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
662 void (*init
)(void *ptr
, __u32 numservices
),
663 void (*next_service
)(void *ptr
, __be16 port
))
667 struct libcor_nonblock_resumeinfo_servicelist
*nr_sl
=
668 &(nr
->data
.read
.funcdata
.servicelist
);
670 if (nr
->type
== RESUME_TYPE_NONE
) {
671 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
672 nr
->type
= RESUME_TYPE_READ
;
673 nr
->data
.read
.functype
= RESUME_READ_FUNC_SERVICELIST
;
677 nr_sl
->next_service
= next_service
;
678 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
679 nr
->data
.read
.functype
!=
680 RESUME_READ_FUNC_SERVICELIST
)) {
682 } else if (unlikely(nr_sl
->fd
!= fd
||
684 nr_sl
->init
!= init
||
685 nr_sl
->next_service
!= next_service
)) {
688 __u8 state
= nr_sl
->state
;
691 } else if (state
== 2) {
693 } else if (state
== 3) {
695 } else if (unlikely(state
!= 0)) {
702 rc
= read_fully(fd
, nr
, (char *) &(nr_sl
->respcode
), 1, 0);
704 return bzero_nr_iffinished(nr
, rc
);
706 if (unlikely(nr_sl
->respcode
!= CDR_BINDATA
))
707 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
711 rc
= read_len(fd
, nr
, &(nr_sl
->len
), 0);
713 return bzero_nr_iffinished(nr
, rc
);
717 rc
= read_len(fd
, nr
, &(nr_sl
->numservices
), &(nr_sl
->len
));
719 return bzero_nr_iffinished(nr
, rc
);
721 init(ptr
, nr_sl
->numservices
);
723 for(nr_sl
->q
=0; nr_sl
->q
< nr_sl
->numservices
; nr_sl
->q
++) {
728 rc
= read_fully(fd
, nr
, (char *) &(nr_sl
->port
), 2,
731 return bzero_nr_iffinished(nr
, rc
);
733 next_service(ptr
, nr_sl
->port
);
737 return bzero_nr_iffinished(nr
, rc
);
740 int read_service_list(int fd
, void *ptr
,
741 void (*init
)(void *ptr
, __u32 numservices
),
742 void (*next_service
)(void *ptr
, __be16 port
))
744 int rc
= RC_WOULDBLOCK
;
745 struct libcor_nonblock_resumeinfo nr
;
746 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
748 rc
= read_service_list_nonblock(fd
, &nr
, ptr
, init
, next_service
);
749 if (unlikely(rc
== RC_WOULDBLOCK
)) {
751 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
757 int send_list_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
759 return send_cmd(fd
, nr
, CD_LIST_NEIGH
, 0, 0);
762 int send_list_neigh(int fd
)
764 int rc
= RC_WOULDBLOCK
;
765 struct libcor_nonblock_resumeinfo nr
;
766 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
768 rc
= send_list_neigh_nonblock(fd
, &nr
);
769 if (unlikely(rc
== RC_WOULDBLOCK
)) {
771 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
776 static int field_present(struct listneigh_field
*fields
, __u32 numfields
,
780 for(u
=0;u
<numfields
;u
++) {
781 if (fields
[u
].field
== field
)
787 int read_neigh_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
789 void (*init
)(void *ptr
, __u32 numneigh
),
790 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
794 struct libcor_nonblock_resumeinfo_neighlist
*nr_nl
=
795 &(nr
->data
.read
.funcdata
.neighlist
);
797 if (nr
->type
== RESUME_TYPE_NONE
) {
798 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
799 nr
->type
= RESUME_TYPE_READ
;
800 nr
->data
.read
.functype
= RESUME_READ_FUNC_NEIGHLIST
;
804 nr_nl
->next_neigh
= next_neigh
;
805 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
806 nr
->data
.read
.functype
!= RESUME_READ_FUNC_NEIGHLIST
)) {
808 } else if (unlikely(nr_nl
->fd
!= fd
||
810 nr_nl
->init
!= init
||
811 nr_nl
->next_neigh
!= next_neigh
)) {
814 __u8 state
= nr_nl
->state
;
817 } else if (state
== 2) {
819 } else if (state
== 3) {
821 } else if (state
== 4) {
823 } else if (state
== 5) {
825 } else if (state
== 6) {
827 } else if (state
== 7) {
829 } else if (state
== 8) {
831 } else if (state
== 9) {
833 } else if (unlikely(state
!= 0)) {
840 rc
= read_fully(fd
, nr
, (char *) &(nr_nl
->respcode
), 1, 0);
842 return bzero_nr_iffinished(nr
, rc
);
844 if (unlikely(nr_nl
->respcode
!= CDR_BINDATA
))
845 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
849 rc
= read_len(fd
, nr
, &(nr_nl
->len
), 0);
851 return bzero_nr_iffinished(nr
, rc
);
855 rc
= read_len(fd
, nr
, &(nr_nl
->numneighs
), &(nr_nl
->len
));
857 return bzero_nr_iffinished(nr
, rc
);
861 rc
= read_len(fd
, nr
, &(nr_nl
->numfields
), &(nr_nl
->len
));
863 return bzero_nr_iffinished(nr
, rc
);
865 if (unlikely(nr_nl
->numfields
> NEIGHLIST_MAX_FIELDS
))
866 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
868 for(nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numfields
; nr_nl
->u
++) {
869 nr_nl
->fields
[nr_nl
->u
].field
= 0;
873 rc
= read_fully(fd
, nr
,
874 (char *) &(nr_nl
->fields
[nr_nl
->u
].field
),
877 return bzero_nr_iffinished(nr
, rc
);
878 nr_nl
->fields
[nr_nl
->u
].field
=
879 ntohs(nr_nl
->fields
[nr_nl
->u
].field
);
884 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
), &(nr_nl
->len
));
886 return bzero_nr_iffinished(nr
, rc
);
888 if (unlikely(nr_nl
->fieldlen
> 65535))
889 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
891 nr_nl
->fields
[nr_nl
->u
].len
= (__u16
) nr_nl
->fieldlen
;
895 if (unlikely(field_present(nr_nl
->fields
, nr_nl
->numfields
,
896 LIST_NEIGH_FIELD_ADDR
) == 0))
897 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
899 init(ptr
, nr_nl
->numneighs
);
901 for (nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numneighs
; nr_nl
->u
++) {
902 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
906 for(nr_nl
->v
=0; nr_nl
->v
< nr_nl
->numfields
; nr_nl
->v
++) {
907 nr_nl
->fieldlen
= nr_nl
->fields
[nr_nl
->v
].len
;
908 if (nr_nl
->fieldlen
== 0) {
911 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
),
914 return bzero_nr_iffinished(nr
, rc
);
917 if (nr_nl
->fieldlen
> nr_nl
->len
)
918 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
920 nr_nl
->len
-= nr_nl
->fieldlen
;
922 if (field_present(nr_nl
->fields
, nr_nl
->v
,
923 nr_nl
->fields
[nr_nl
->v
].field
)) {
925 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
926 LIST_NEIGH_FIELD_ADDR
) {
928 nr_nl
->addrlen
= nr_nl
->fieldlen
;
930 if (unlikely(nr_nl
->addrlen
> ADDR_MAX_LEN
))
933 if (sizeof(nr_nl
->addr
) != ADDR_MAX_LEN
)
936 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
940 rc
= read_fully(fd
, nr
, &(nr_nl
->addr
[0]),
944 return bzero_nr_iffinished(nr
, rc
);
945 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
946 LIST_NEIGH_FIELD_LATENCY
) {
951 rc
= read_fully(fd
, nr
, &nr_nl
->latency
, 1,
954 return bzero_nr_iffinished(nr
, rc
);
956 printf("latency %d\n", (int) nr_nl
->latency
);
960 if (nr_nl
->fieldlen
> 0) {
963 rc
= read_discard(fd
, nr
, nr_nl
->fieldlen
);
965 return bzero_nr_iffinished(nr
, rc
);
971 if (nr_nl
->addrlen
> ADDR_MAX_LEN
)
974 next_neigh(ptr
, nr_nl
->addrlen
, &(nr_nl
->addr
[0]));
975 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
980 return bzero_nr_iffinished(nr
, rc
);
983 int read_neigh_list(int fd
, void *ptr
,
984 void (*init
)(void *ptr
, __u32 numneighs
),
985 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
987 int rc
= RC_WOULDBLOCK
;
988 struct libcor_nonblock_resumeinfo nr
;
989 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
991 rc
= read_neigh_list_nonblock(fd
, &nr
, ptr
, init
, next_neigh
);
992 if (unlikely(rc
== RC_WOULDBLOCK
)) {
994 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
999 int pass_socket(int fd
, __u64 cookie
)
1003 rc
= setsockopt(fd
, SOL_COR
, COR_PASS_ON_CLOSE
, &cookie
, 8);
1005 perror("pass_socket");
1006 return RC_CONNBROKEN
;
1014 static int send_rdsock_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
1015 __u32 cmd
, char *data
, __u32 datalen
)
1017 __u32 be_cmd
= htonl(cmd
);
1018 __u32 be_datalen
= htonl(datalen
);
1020 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
1021 LIBCOR_ASSERT_ERR();
1023 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1024 nr
->type
= RESUME_TYPE_WRITE
;
1025 nr
->data
.write
.fd
= fd
;
1027 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
1028 LIBCOR_ASSERT_ERR();
1030 if (unlikely(datalen
+ 8 < datalen
|| WRITE_BUF_SIZE
< (datalen
+ 8)))
1031 LIBCOR_ASSERT_ERR();
1033 memcpy(&(nr
->data
.write
.buf
[0]), (char *) &be_cmd
, 4);
1034 memcpy(&(nr
->data
.write
.buf
[4]), (char *) &be_datalen
, 4);
1035 memcpy(&(nr
->data
.write
.buf
[8]), data
, datalen
);
1036 nr
->data
.write
.len
= datalen
+ 8;
1038 return resume_send(fd
, nr
);
1041 int send_rdsock_version_nonblock(int fd
,
1042 struct libcor_nonblock_resumeinfo
*nr
,
1047 version
= htonl(version
);
1049 memcpy(&(data
[0]), (char *) &version
, 4);
1051 return send_rdsock_cmd(fd
, nr
, CRD_UTK_VERSION
, &(data
[0]), 4);
1054 int send_rdsock_version(int fd
, __u32 version
)
1056 int rc
= RC_WOULDBLOCK
;
1057 struct libcor_nonblock_resumeinfo nr
;
1058 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1060 rc
= send_rdsock_version_nonblock(fd
, &nr
, version
);
1061 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1062 LIBCOR_ASSERT_ERR();
1063 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1068 int send_rdsock_up_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
1069 char *addr
, __u32 addrlen
)
1077 if (addr
== 0 && addrlen
!= 0)
1078 return RC_CONNBROKEN
;
1081 return RC_CONNBROKEN
;
1083 flags
= htonll(flags
);
1084 addrlenbe
= htonl(addrlen
);
1086 memcpy(&(data
[0]), (char *) &flags
, 8);
1087 memcpy(&(data
[8]), (char *) &addrlenbe
, 4);
1089 memcpy(&(data
[12]), addr
, addrlen
);
1091 return send_rdsock_cmd(fd
, nr
, CRD_UTK_UP
, &(data
[0]), 12 + addrlen
);
1094 int send_rdsock_up(int fd
, char *addr
, __u32 addrlen
)
1096 int rc
= RC_WOULDBLOCK
;
1097 struct libcor_nonblock_resumeinfo nr
;
1098 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1100 rc
= send_rdsock_up_nonblock(fd
, &nr
, addr
, addrlen
);
1101 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1102 LIBCOR_ASSERT_ERR();
1103 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1108 int send_rdsock_connecterror_nonblock(int fd
,
1109 struct libcor_nonblock_resumeinfo
*nr
,
1110 __u64 cookie
, __u32 error
)
1114 error
= htonl(error
);
1116 memcpy(&(data
[0]), (char *) &cookie
, 8);
1117 memcpy(&(data
[8]), (char *) &error
, 4);
1119 return send_rdsock_cmd(fd
, nr
, CRD_UTK_CONNECTERROR
, &(data
[0]), 12);
1122 int send_rdsock_connecterror(int fd
, __u64 cookie
, __u32 error
)
1124 int rc
= RC_WOULDBLOCK
;
1125 struct libcor_nonblock_resumeinfo nr
;
1126 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1128 rc
= send_rdsock_connecterror_nonblock(fd
, &nr
, cookie
, error
);
1129 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1130 LIBCOR_ASSERT_ERR();
1131 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1136 int parse_rdsock_supported_versions(struct rdsock_cmd
*cmd
,
1137 __u32
*versionmin
, __u32
*versionmax
)
1139 if (cmd
->cmddatalen
!= 8)
1142 memcpy((char *) versionmin
, cmd
->cmddata
, 4);
1143 *versionmin
= htonl(*versionmin
);
1144 memcpy((char *) versionmax
, cmd
->cmddata
+ 4, 4);
1145 *versionmax
= htonl(*versionmax
);
1150 int parse_rdsock_connect(void *ptr
, struct rdsock_cmd
*cmd
,
1151 int (*proc_connect
)(void *ptr
, __u64 cookie
,
1152 struct cor_sockaddr
*addr
))
1155 struct cor_sockaddr addr
;
1157 memcpy((char *) &cookie
, cmd
->cmddata
, 8);
1159 if ((sizeof(struct cor_sockaddr
) + 8) != cmd
->cmddatalen
)
1162 memcpy((char *) &addr
, cmd
->cmddata
+ 8, sizeof(struct cor_sockaddr
));
1164 return proc_connect(ptr
, cookie
, &addr
);
1167 int read_rdsock_cmd_nonblock(int fd
,
1168 struct libcor_nonblock_resumeinfo
*nr
,
1169 struct rdsock_cmd
*cmd
)
1173 struct libcor_nonblock_resumeinfo_rdsockcmd
*nr_rd
=
1174 &(nr
->data
.read
.funcdata
.rdsock_cmd
);
1176 bzero(cmd
, sizeof(struct rdsock_cmd
));
1178 if (nr
->type
== RESUME_TYPE_NONE
) {
1179 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1180 nr
->type
= RESUME_TYPE_READ
;
1181 nr
->data
.read
.functype
= RESUME_READ_FUNC_RDSOCK_CMD
;
1183 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
1184 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RDSOCK_CMD
)){
1185 LIBCOR_ASSERT_ERR();
1186 } else if (unlikely(nr_rd
->fd
!= fd
)) {
1187 LIBCOR_ASSERT_ERR();
1189 __u8 state
= nr_rd
->state
;
1193 } else if (state
== 2) {
1195 } else if (unlikely(state
!= 0)) {
1196 LIBCOR_ASSERT_ERR();
1200 if (sizeof(nr_rd
->buf
) != 8)
1201 LIBCOR_ASSERT_ERR();
1203 rc
= read_fully(fd
, nr
, (char *) &(nr_rd
->buf
[0]), 8, 0);
1205 return bzero_nr_iffinished(nr
, rc
);
1207 ((char *) &(nr_rd
->cmd
))[0] = nr_rd
->buf
[0];
1208 ((char *) &(nr_rd
->cmd
))[1] = nr_rd
->buf
[1];
1209 ((char *) &(nr_rd
->cmd
))[2] = nr_rd
->buf
[2];
1210 ((char *) &(nr_rd
->cmd
))[3] = nr_rd
->buf
[3];
1211 ((char *) &(nr_rd
->cmddatalen
))[0] = nr_rd
->buf
[4];
1212 ((char *) &(nr_rd
->cmddatalen
))[1] = nr_rd
->buf
[5];
1213 ((char *) &(nr_rd
->cmddatalen
))[2] = nr_rd
->buf
[6];
1214 ((char *) &(nr_rd
->cmddatalen
))[3] = nr_rd
->buf
[7];
1216 nr_rd
->cmd
= ntohl(nr_rd
->cmd
);
1217 nr_rd
->cmddatalen
= ntohl(nr_rd
->cmddatalen
);
1219 if (nr_rd
->cmddatalen
> 65536)
1222 nr_rd
->cmddata
= malloc(nr_rd
->cmddatalen
);
1223 if (nr_rd
->cmddata
== 0)
1228 rc
= read_fully(fd
, nr
, nr_rd
->cmddata
, nr_rd
->cmddatalen
, 0);
1230 if (rc
!= RC_WOULDBLOCK
) {
1231 free(nr_rd
->cmddata
);
1234 return bzero_nr_iffinished(nr
, rc
);
1237 cmd
->cmd
= nr_rd
->cmd
;
1238 cmd
->cmddata
= nr_rd
->cmddata
;
1239 cmd
->cmddatalen
= nr_rd
->cmddatalen
;
1245 rc
= read_discard(fd
, nr
, nr_rd
->cmddatalen
);
1247 return bzero_nr_iffinished(nr
, rc
);
1249 return bzero_nr_iffinished(nr
, rc
);
1252 int read_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
1254 int rc
= RC_WOULDBLOCK
;
1255 struct libcor_nonblock_resumeinfo nr
;
1256 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1258 rc
= read_rdsock_cmd_nonblock(fd
, &nr
, cmd
);
1259 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1260 LIBCOR_ASSERT_ERR();
1261 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);