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_UNKNOWN_COMMAND 1
44 #define CDR_EXECFAILED_PERMISSION_DENIED 2
45 #define CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES 3
46 #define CDR_EXECFAILED_CMD_TOO_SHORT 4
47 #define CDR_EXECFAILED_CMD_TOO_LONG 5
48 #define CDR_EXECFAILED_TARGETADDR_DOESNTEXIST 6
49 #define CDR_EXECFAILED_PORTCLOSED 7
50 #define CDR_EXECFAILED_LISTENERQUEUE_FULL 8
51 #define CDR_EXECFAILED_ILLEGAL_COMMAND 9
55 #define LIST_NEIGH_FIELD_ADDR 1
56 #define LIST_NEIGH_FIELD_LATENCY 2
59 static int bzero_nr_iffinished(struct libcor_nonblock_resumeinfo
*nr
, int rc
)
61 /*if (rc == RC_WOULDBLOCK) {
62 printf("wouldblock\n");
65 if (rc
!= RC_WOULDBLOCK
) {
66 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
71 #define LIBCOR_ASSERT_ERR() \
80 static __u64 htonll(__u64 in)
83 char *p_out
= (char *) &out
;
104 static __u64
ntohll(__u64 in
)
107 char *p_in
= (char *) &in
;
128 #warning todo commands are sent via multiple packets
129 int resume_send(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
131 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!=fd
))
134 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
||
135 unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
138 while (nr
->data
.write
.totalsent
< nr
->data
.write
.len
) {
139 char *buf
= &(nr
->data
.write
.buf
[0]);
140 int sent
= send(fd
, buf
+ nr
->data
.write
.totalsent
,
141 nr
->data
.write
.len
- nr
->data
.write
.totalsent
,
144 if (sent
< 0 && (errno
== EAGAIN
||
145 errno
== EWOULDBLOCK
))
146 return bzero_nr_iffinished(nr
, RC_WOULDBLOCK
);
153 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
156 nr
->data
.write
.totalsent
+= sent
;
159 return bzero_nr_iffinished(nr
, RC_OK
);
162 static int read_fully(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
163 char *buf
, __u32 len
, __u32
*maxread
)
167 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
170 if (unlikely(nr
->data
.read
.read_fully
.state
!= 0 && (
171 nr
->data
.read
.read_fully
.fd
!= fd
||
172 nr
->data
.read
.read_fully
.buf
!= buf
||
173 nr
->data
.read
.read_fully
.len
!= len
||
174 nr
->data
.read
.read_fully
.maxread
!= maxread
)))
177 if (nr
->data
.read
.read_fully
.state
== 1) {
179 } else if (unlikely(nr
->data
.read
.read_fully
.state
!= 0)) {
183 nr
->data
.read
.read_fully
.fd
= fd
;
184 nr
->data
.read
.read_fully
.buf
= buf
;
185 nr
->data
.read
.read_fully
.len
= len
;
186 nr
->data
.read
.read_fully
.maxread
= maxread
;
187 nr
->data
.read
.read_fully
.totalread
= 0;
189 nr
->data
.read
.read_fully
.state
= 1;
193 if (len
> (*maxread
)) {
194 printf("error in read_fully: maxread reached\n");
201 while (len
> nr
->data
.read
.read_fully
.totalread
) {
202 int rcvd
= recv(fd
, buf
+ nr
->data
.read
.read_fully
.totalread
,
203 len
- nr
->data
.read
.read_fully
.totalread
, 0);
206 if (rcvd
< 0 && (errno
== EAGAIN
||
207 errno
== EWOULDBLOCK
)) {
209 /* printf("wouldblock\n"); */
222 /*printf("rcvd: %d:", rcvd);
223 for(u=0;u<rcvd;u++) {
224 printf(" %d, ", (__s32) ((__u8) buf[totalread+u]));
228 nr
->data
.read
.read_fully
.totalread
+= (__u32
) rcvd
;
232 if (rc
!= RC_WOULDBLOCK
) {
233 bzero(&(nr
->data
.read
.read_fully
),
234 sizeof(nr
->data
.read
.read_fully
));
240 static int read_discard(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
246 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
249 if (unlikely(nr
->data
.read
.read_discard
.state
!= 0 && (
250 nr
->data
.read
.read_discard
.fd
!= fd
||
251 nr
->data
.read
.read_discard
.len
!= len
)))
254 if (nr
->data
.read
.read_discard
.state
== 1) {
256 } else if (unlikely(nr
->data
.read
.read_discard
.state
!= 0)) {
260 nr
->data
.read
.read_discard
.fd
= fd
;
261 nr
->data
.read
.read_discard
.len
= len
;
262 nr
->data
.read
.read_discard
.discarded
= 0;
265 nr
->data
.read
.read_discard
.state
= 1;
271 __u32 rcvlen
= len
- nr
->data
.read
.read_discard
.discarded
;
275 rcvd
= recv(fd
, buf
, rcvlen
, 0);
277 if (rcvd
< 0 && (errno
== EAGAIN
||
278 errno
== EWOULDBLOCK
)) {
292 nr
->data
.read
.read_discard
.discarded
-= rcvd
;
296 if (rc
!= RC_WOULDBLOCK
) {
297 bzero(&(nr
->data
.read
.read_discard
),
298 sizeof(nr
->data
.read
.read_discard
));
304 static int encode_len(char *buf
, int buflen
, __u32 len
)
306 if (unlikely(buf
== 0))
309 if (unlikely(buflen
< 4))
318 buf
[0] = (__u8
) ((len
- 128) /256 + 128);
319 buf
[1] = (__u8
) ((len
- 128) & 255);
323 if (len
< 1073741951) {
324 __u32 len_be
= htonl(len
- 16511);
325 char *len_p
= (char *) &len_be
;
327 buf
[0] = len_p
[0] + 192;
337 static int decode_len(char *buf
, int buflen
, __u32
*len
)
339 if (unlikely(buflen
< 1))
342 if ((__u8
) buf
[0] <= 127) {
343 *len
= (__u8
) buf
[0];
350 if ((__u8
) buf
[0] <= 191) {
351 *len
= 128 + ((__u32
) ((__u8
) buf
[0]) - 128) * 256 +
359 ((char *) len
)[0] = buf
[0] - 192;
360 ((char *) len
)[1] = buf
[1];
361 ((char *) len
)[2] = buf
[2];
362 ((char *) len
)[3] = buf
[3];
364 *len
= ntohl(*len
) + 16511;
369 static int read_len(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
370 __u32
*len
, __u32
*maxread
)
372 int rc
= RC_CONNBROKEN
;
374 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
377 if (unlikely(nr
->data
.read
.read_len
.state
!= 0 && (
378 nr
->data
.read
.read_len
.fd
!= fd
||
379 nr
->data
.read
.read_len
.len
!= len
||
380 nr
->data
.read
.read_len
.maxread
!= maxread
)))
383 if (sizeof(nr
->data
.read
.read_len
.buf
) != 4)
386 if (nr
->data
.read
.read_len
.state
== 1) {
388 } else if (unlikely(nr
->data
.read
.read_len
.state
!= 0)) {
392 nr
->data
.read
.read_len
.fd
= fd
;
393 nr
->data
.read
.read_len
.len
= len
;
394 nr
->data
.read
.read_len
.maxread
= maxread
;
395 bzero(&(nr
->data
.read
.read_len
.buf
[0]), 4);
396 nr
->data
.read
.read_len
.read
= 0;
400 nr
->data
.read
.read_len
.state
= 1;
402 if (nr
->data
.read
.read_len
.read
>= 4) {
403 printf("error in readlen: read to high\n");
408 rc
= read_fully(fd
, nr
, &(nr
->data
.read
.read_len
.buf
[0]) +
409 nr
->data
.read
.read_len
.read
, 1, maxread
);
413 nr
->data
.read
.read_len
.read
++;
415 rc
= decode_len(&(nr
->data
.read
.read_len
.buf
[0]),
416 nr
->data
.read
.read_len
.read
, len
);
418 if (unlikely(rc
< nr
->data
.read
.read_len
.read
)) {
419 printf("error in readlen: decode_len has not "
420 "consumed the whole buffer\n");
430 if (rc
!= RC_WOULDBLOCK
) {
431 bzero(&(nr
->data
.read
.read_len
),
432 sizeof(nr
->data
.read
.read_len
));
438 static int _send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
, __u16 cmd
)
445 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!= fd
))
449 buf
[0] = ((char *) &cmd
)[0];
450 buf
[1] = ((char *) &cmd
)[1];
452 rc
= encode_len(&(buf
[2]), 4, nr
->data
.write
.len
);
453 if (rc
<= 0 || rc
> 4)
456 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
459 hdrlen
= 2 + ((__u32
) rc
);
461 if (unlikely(nr
->data
.write
.len
+ hdrlen
< nr
->data
.write
.len
||
462 nr
->data
.write
.len
+ hdrlen
> WRITE_BUF_SIZE
))
465 memmove(&(nr
->data
.write
.buf
[hdrlen
]), &(nr
->data
.write
.buf
[0]),
467 memcpy(&(nr
->data
.write
.buf
[0]), &(buf
[0]), hdrlen
);
468 nr
->data
.write
.len
+= hdrlen
;
470 return resume_send(fd
, nr
);
473 static int send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
474 __u16 cmd
, char *buf
, __u32 len
)
476 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
479 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
480 nr
->type
= RESUME_TYPE_WRITE
;
481 nr
->data
.write
.fd
= fd
;
483 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
486 if (unlikely(WRITE_BUF_SIZE
< len
))
490 memcpy(&(nr
->data
.write
.buf
[0]), buf
, len
);
491 nr
->data
.write
.len
= len
;
494 return _send_cmd(fd
, nr
, cmd
);
497 int read_resp_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
501 struct libcor_nonblock_resumeinfo_resp
*nr_resp
=
502 &(nr
->data
.read
.funcdata
.resp
);
504 if (nr
->type
== RESUME_TYPE_NONE
) {
505 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
506 nr
->type
= RESUME_TYPE_READ
;
507 nr
->data
.read
.functype
= RESUME_READ_FUNC_RESP
;
509 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
510 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RESP
)) {
512 } else if (unlikely(nr_resp
->fd
!= fd
)) {
515 __u8 state
= nr_resp
->state
;
519 } else if (state
== 2) {
521 } else if (state
== 3) {
523 } else if (unlikely(state
!= 0)) {
528 nr_resp
->respcode
= 0;
529 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->respcode
), 1, 0);
532 return bzero_nr_iffinished(nr
, rc
);
534 if (nr_resp
->respcode
== CDR_EXECFAILED
) {
535 nr_resp
->reasoncode
= 0;
539 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->reasoncode
), 2, 0);
541 return bzero_nr_iffinished(nr
, rc
);
543 nr_resp
->reasoncode
= ntohs(nr_resp
->reasoncode
);
545 printf("execfailed: reasoncode = %d\n", (__s32
)
546 nr_resp
->reasoncode
);
550 rc
= read_len(fd
, nr
, &(nr_resp
->reasonlen
),
553 return bzero_nr_iffinished(nr
, rc
);
557 rc
= read_discard(fd
, nr
, nr_resp
->reasonlen
);
559 return bzero_nr_iffinished(nr
, rc
);
562 while (reasonlen > 0) {
563 __u32 nextread = reasonlen;
565 if (reasonlen > 4093)
567 reasonlen -= nextread;
568 int rc = read_fully(fd, buf, nextread, 0);
579 //printf("read_resp: respcode = %d\n", nr_resp->respcode);
581 if (nr_resp
->respcode
== CDR_EXECOK
)
582 return bzero_nr_iffinished(nr
, RC_OK
);
584 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
587 int read_resp(int fd
)
589 int rc
= RC_WOULDBLOCK
;
590 struct libcor_nonblock_resumeinfo nr
;
591 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
593 rc
= read_resp_nonblock(fd
, &nr
);
594 if (unlikely(rc
== RC_WOULDBLOCK
)) {
596 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
602 int send_connect_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
603 __u32 addrlen
, char *addr
)
608 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
611 if (unlikely(addrlen
> (1024 * 1024 * 1024) ||
612 addrlen
+ 4 > WRITE_BUF_SIZE
))
615 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
616 nr
->type
= RESUME_TYPE_WRITE
;
617 nr
->data
.write
.fd
= fd
;
619 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
622 if (unlikely(WRITE_BUF_SIZE
< 4))
625 rc
= encode_len(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), 4, addrlen
);
626 if (unlikely(rc
<= 0 || rc
> 4))
629 nr
->data
.write
.len
+= (__u32
) rc
;
631 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
||
632 WRITE_BUF_SIZE
- nr
->data
.write
.len
< addrlen
))
635 memcpy(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), addr
, addrlen
);
636 nr
->data
.write
.len
+= addrlen
;
638 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
641 return _send_cmd(fd
, nr
, CD_CONNECT_NB
);
644 int send_connect_neigh(int fd
, __u32 addrlen
, char *addr
)
646 int rc
= RC_WOULDBLOCK
;
647 struct libcor_nonblock_resumeinfo nr
;
648 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
650 rc
= send_connect_neigh_nonblock(fd
, &nr
, addrlen
, addr
);
651 if (unlikely(rc
== RC_WOULDBLOCK
)) {
653 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
658 int send_connect_port_nonblock(int fd
,
659 struct libcor_nonblock_resumeinfo
*nr
, __be16 port
)
661 return send_cmd(fd
, nr
, CD_CONNECT_PORT
, (char *) &port
, 2);
664 int send_connect_port(int fd
, __be16 port
)
666 int rc
= RC_WOULDBLOCK
;
667 struct libcor_nonblock_resumeinfo nr
;
668 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
670 rc
= send_connect_port_nonblock(fd
, &nr
, port
);
671 if (unlikely(rc
== RC_WOULDBLOCK
)) {
673 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
678 int send_list_services_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
680 return send_cmd(fd
, nr
, CD_LIST_SERVICES
, 0, 0);
683 int send_list_services(int fd
)
685 int rc
= RC_WOULDBLOCK
;
686 struct libcor_nonblock_resumeinfo nr
;
687 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
689 rc
= send_list_services_nonblock(fd
, &nr
);
690 if (unlikely(rc
== RC_WOULDBLOCK
)) {
692 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
697 int read_service_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
699 void (*init
)(void *ptr
, __u32 numservices
),
700 void (*next_service
)(void *ptr
, __be16 port
))
704 struct libcor_nonblock_resumeinfo_servicelist
*nr_sl
=
705 &(nr
->data
.read
.funcdata
.servicelist
);
707 if (nr
->type
== RESUME_TYPE_NONE
) {
708 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
709 nr
->type
= RESUME_TYPE_READ
;
710 nr
->data
.read
.functype
= RESUME_READ_FUNC_SERVICELIST
;
714 nr_sl
->next_service
= next_service
;
715 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
716 nr
->data
.read
.functype
!=
717 RESUME_READ_FUNC_SERVICELIST
)) {
719 } else if (unlikely(nr_sl
->fd
!= fd
||
721 nr_sl
->init
!= init
||
722 nr_sl
->next_service
!= next_service
)) {
725 __u8 state
= nr_sl
->state
;
728 } else if (state
== 2) {
730 } else if (state
== 3) {
732 } else if (unlikely(state
!= 0)) {
739 rc
= read_fully(fd
, nr
, (char *) &(nr_sl
->respcode
), 1, 0);
741 return bzero_nr_iffinished(nr
, rc
);
743 if (unlikely(nr_sl
->respcode
!= CDR_BINDATA
))
744 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
748 rc
= read_len(fd
, nr
, &(nr_sl
->len
), 0);
750 return bzero_nr_iffinished(nr
, rc
);
754 rc
= read_len(fd
, nr
, &(nr_sl
->numservices
), &(nr_sl
->len
));
756 return bzero_nr_iffinished(nr
, rc
);
758 init(ptr
, nr_sl
->numservices
);
760 for(nr_sl
->q
=0; nr_sl
->q
< nr_sl
->numservices
; nr_sl
->q
++) {
765 rc
= read_fully(fd
, nr
, (char *) &(nr_sl
->port
), 2,
768 return bzero_nr_iffinished(nr
, rc
);
770 next_service(ptr
, nr_sl
->port
);
774 return bzero_nr_iffinished(nr
, rc
);
777 int read_service_list(int fd
, void *ptr
,
778 void (*init
)(void *ptr
, __u32 numservices
),
779 void (*next_service
)(void *ptr
, __be16 port
))
781 int rc
= RC_WOULDBLOCK
;
782 struct libcor_nonblock_resumeinfo nr
;
783 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
785 rc
= read_service_list_nonblock(fd
, &nr
, ptr
, init
, next_service
);
786 if (unlikely(rc
== RC_WOULDBLOCK
)) {
788 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
794 int send_list_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
796 return send_cmd(fd
, nr
, CD_LIST_NEIGH
, 0, 0);
799 int send_list_neigh(int fd
)
801 int rc
= RC_WOULDBLOCK
;
802 struct libcor_nonblock_resumeinfo nr
;
803 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
805 rc
= send_list_neigh_nonblock(fd
, &nr
);
806 if (unlikely(rc
== RC_WOULDBLOCK
)) {
808 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
813 static int field_present(struct listneigh_field
*fields
, __u32 numfields
,
817 for(u
=0;u
<numfields
;u
++) {
818 if (fields
[u
].field
== field
)
824 int read_neigh_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
826 void (*init
)(void *ptr
, __u32 numneigh
),
827 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
831 struct libcor_nonblock_resumeinfo_neighlist
*nr_nl
=
832 &(nr
->data
.read
.funcdata
.neighlist
);
834 if (nr
->type
== RESUME_TYPE_NONE
) {
835 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
836 nr
->type
= RESUME_TYPE_READ
;
837 nr
->data
.read
.functype
= RESUME_READ_FUNC_NEIGHLIST
;
841 nr_nl
->next_neigh
= next_neigh
;
842 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
843 nr
->data
.read
.functype
!= RESUME_READ_FUNC_NEIGHLIST
)) {
845 } else if (unlikely(nr_nl
->fd
!= fd
||
847 nr_nl
->init
!= init
||
848 nr_nl
->next_neigh
!= next_neigh
)) {
851 __u8 state
= nr_nl
->state
;
854 } else if (state
== 2) {
856 } else if (state
== 3) {
858 } else if (state
== 4) {
860 } else if (state
== 5) {
862 } else if (state
== 6) {
864 } else if (state
== 7) {
866 } else if (state
== 8) {
868 } else if (state
== 9) {
870 } else if (unlikely(state
!= 0)) {
877 rc
= read_fully(fd
, nr
, (char *) &(nr_nl
->respcode
), 1, 0);
879 return bzero_nr_iffinished(nr
, rc
);
881 if (unlikely(nr_nl
->respcode
!= CDR_BINDATA
))
882 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
886 rc
= read_len(fd
, nr
, &(nr_nl
->len
), 0);
888 return bzero_nr_iffinished(nr
, rc
);
892 rc
= read_len(fd
, nr
, &(nr_nl
->numneighs
), &(nr_nl
->len
));
894 return bzero_nr_iffinished(nr
, rc
);
898 rc
= read_len(fd
, nr
, &(nr_nl
->numfields
), &(nr_nl
->len
));
900 return bzero_nr_iffinished(nr
, rc
);
902 if (unlikely(nr_nl
->numfields
> NEIGHLIST_MAX_FIELDS
))
903 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
905 for(nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numfields
; nr_nl
->u
++) {
906 nr_nl
->fields
[nr_nl
->u
].field
= 0;
910 rc
= read_fully(fd
, nr
,
911 (char *) &(nr_nl
->fields
[nr_nl
->u
].field
),
914 return bzero_nr_iffinished(nr
, rc
);
915 nr_nl
->fields
[nr_nl
->u
].field
=
916 ntohs(nr_nl
->fields
[nr_nl
->u
].field
);
921 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
), &(nr_nl
->len
));
923 return bzero_nr_iffinished(nr
, rc
);
925 if (unlikely(nr_nl
->fieldlen
> 65535))
926 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
928 nr_nl
->fields
[nr_nl
->u
].len
= (__u16
) nr_nl
->fieldlen
;
932 if (unlikely(field_present(nr_nl
->fields
, nr_nl
->numfields
,
933 LIST_NEIGH_FIELD_ADDR
) == 0))
934 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
936 init(ptr
, nr_nl
->numneighs
);
938 for (nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numneighs
; nr_nl
->u
++) {
939 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
943 for(nr_nl
->v
=0; nr_nl
->v
< nr_nl
->numfields
; nr_nl
->v
++) {
944 nr_nl
->fieldlen
= nr_nl
->fields
[nr_nl
->v
].len
;
945 if (nr_nl
->fieldlen
== 0) {
948 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
),
951 return bzero_nr_iffinished(nr
, rc
);
954 if (nr_nl
->fieldlen
> nr_nl
->len
)
955 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
957 nr_nl
->len
-= nr_nl
->fieldlen
;
959 if (field_present(nr_nl
->fields
, nr_nl
->v
,
960 nr_nl
->fields
[nr_nl
->v
].field
)) {
962 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
963 LIST_NEIGH_FIELD_ADDR
) {
965 nr_nl
->addrlen
= nr_nl
->fieldlen
;
967 if (unlikely(nr_nl
->addrlen
> ADDR_MAX_LEN
))
970 if (sizeof(nr_nl
->addr
) != ADDR_MAX_LEN
)
973 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
977 rc
= read_fully(fd
, nr
, &(nr_nl
->addr
[0]),
981 return bzero_nr_iffinished(nr
, rc
);
982 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
983 LIST_NEIGH_FIELD_LATENCY
) {
988 rc
= read_fully(fd
, nr
, &nr_nl
->latency
, 1,
991 return bzero_nr_iffinished(nr
, rc
);
993 printf("latency %d\n", (int) nr_nl
->latency
);
997 if (nr_nl
->fieldlen
> 0) {
1000 rc
= read_discard(fd
, nr
, nr_nl
->fieldlen
);
1002 return bzero_nr_iffinished(nr
, rc
);
1005 nr_nl
->fieldlen
= 0;
1008 if (nr_nl
->addrlen
> ADDR_MAX_LEN
)
1009 LIBCOR_ASSERT_ERR();
1011 next_neigh(ptr
, nr_nl
->addrlen
, &(nr_nl
->addr
[0]));
1012 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
1017 return bzero_nr_iffinished(nr
, rc
);
1020 int read_neigh_list(int fd
, void *ptr
,
1021 void (*init
)(void *ptr
, __u32 numneighs
),
1022 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
1024 int rc
= RC_WOULDBLOCK
;
1025 struct libcor_nonblock_resumeinfo nr
;
1026 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1028 rc
= read_neigh_list_nonblock(fd
, &nr
, ptr
, init
, next_neigh
);
1029 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1030 LIBCOR_ASSERT_ERR();
1031 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1036 int pass_socket(int fd
, __u64 cookie
)
1040 rc
= setsockopt(fd
, SOL_COR
, COR_PASS_ON_CLOSE
, &cookie
, 8);
1042 perror("pass_socket");
1043 return RC_CONNBROKEN
;
1051 static int send_rdsock_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
1052 __u32 cmd
, char *data
, __u32 datalen
)
1054 __u32 be_cmd
= htonl(cmd
);
1055 __u32 be_datalen
= htonl(datalen
);
1057 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
1058 LIBCOR_ASSERT_ERR();
1060 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1061 nr
->type
= RESUME_TYPE_WRITE
;
1062 nr
->data
.write
.fd
= fd
;
1064 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
1065 LIBCOR_ASSERT_ERR();
1067 if (unlikely(datalen
+ 8 < datalen
|| WRITE_BUF_SIZE
< (datalen
+ 8)))
1068 LIBCOR_ASSERT_ERR();
1070 memcpy(&(nr
->data
.write
.buf
[0]), (char *) &be_cmd
, 4);
1071 memcpy(&(nr
->data
.write
.buf
[4]), (char *) &be_datalen
, 4);
1072 memcpy(&(nr
->data
.write
.buf
[8]), data
, datalen
);
1073 nr
->data
.write
.len
= datalen
+ 8;
1075 return resume_send(fd
, nr
);
1078 int send_rdsock_version_nonblock(int fd
,
1079 struct libcor_nonblock_resumeinfo
*nr
,
1084 version
= htonl(version
);
1086 memcpy(&(data
[0]), (char *) &version
, 4);
1088 return send_rdsock_cmd(fd
, nr
, CRD_UTK_VERSION
, &(data
[0]), 4);
1091 int send_rdsock_version(int fd
, __u32 version
)
1093 int rc
= RC_WOULDBLOCK
;
1094 struct libcor_nonblock_resumeinfo nr
;
1095 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1097 rc
= send_rdsock_version_nonblock(fd
, &nr
, version
);
1098 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1099 LIBCOR_ASSERT_ERR();
1100 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1105 int send_rdsock_up_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
1106 char *addr
, __u32 addrlen
)
1114 if (addr
== 0 && addrlen
!= 0)
1115 return RC_CONNBROKEN
;
1118 return RC_CONNBROKEN
;
1120 flags
= htonll(flags
);
1121 addrlenbe
= htonl(addrlen
);
1123 memcpy(&(data
[0]), (char *) &flags
, 8);
1124 memcpy(&(data
[8]), (char *) &addrlenbe
, 4);
1126 memcpy(&(data
[12]), addr
, addrlen
);
1128 return send_rdsock_cmd(fd
, nr
, CRD_UTK_UP
, &(data
[0]), 12 + addrlen
);
1131 int send_rdsock_up(int fd
, char *addr
, __u32 addrlen
)
1133 int rc
= RC_WOULDBLOCK
;
1134 struct libcor_nonblock_resumeinfo nr
;
1135 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1137 rc
= send_rdsock_up_nonblock(fd
, &nr
, addr
, addrlen
);
1138 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1139 LIBCOR_ASSERT_ERR();
1140 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1145 int send_rdsock_connecterror_nonblock(int fd
,
1146 struct libcor_nonblock_resumeinfo
*nr
,
1147 __u64 cookie
, __u32 error
)
1151 error
= htonl(error
);
1153 memcpy(&(data
[0]), (char *) &cookie
, 8);
1154 memcpy(&(data
[8]), (char *) &error
, 4);
1156 return send_rdsock_cmd(fd
, nr
, CRD_UTK_CONNECTERROR
, &(data
[0]), 12);
1159 int send_rdsock_connecterror(int fd
, __u64 cookie
, __u32 error
)
1161 int rc
= RC_WOULDBLOCK
;
1162 struct libcor_nonblock_resumeinfo nr
;
1163 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1165 rc
= send_rdsock_connecterror_nonblock(fd
, &nr
, cookie
, error
);
1166 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1167 LIBCOR_ASSERT_ERR();
1168 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1173 int parse_rdsock_supported_versions(struct rdsock_cmd
*cmd
,
1174 __u32
*versionmin
, __u32
*versionmax
)
1176 if (cmd
->cmddatalen
!= 8)
1179 memcpy((char *) versionmin
, cmd
->cmddata
, 4);
1180 *versionmin
= htonl(*versionmin
);
1181 memcpy((char *) versionmax
, cmd
->cmddata
+ 4, 4);
1182 *versionmax
= htonl(*versionmax
);
1187 int parse_rdsock_connect(void *ptr
, struct rdsock_cmd
*cmd
,
1188 int (*proc_connect
)(void *ptr
, __u64 cookie
,
1189 struct cor_sockaddr
*addr
))
1192 struct cor_sockaddr addr
;
1194 memcpy((char *) &cookie
, cmd
->cmddata
, 8);
1196 if ((sizeof(struct cor_sockaddr
) + 8) != cmd
->cmddatalen
)
1199 memcpy((char *) &addr
, cmd
->cmddata
+ 8, sizeof(struct cor_sockaddr
));
1201 return proc_connect(ptr
, cookie
, &addr
);
1204 int read_rdsock_cmd_nonblock(int fd
,
1205 struct libcor_nonblock_resumeinfo
*nr
,
1206 struct rdsock_cmd
*cmd
)
1210 struct libcor_nonblock_resumeinfo_rdsockcmd
*nr_rd
=
1211 &(nr
->data
.read
.funcdata
.rdsock_cmd
);
1213 bzero(cmd
, sizeof(struct rdsock_cmd
));
1215 if (nr
->type
== RESUME_TYPE_NONE
) {
1216 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1217 nr
->type
= RESUME_TYPE_READ
;
1218 nr
->data
.read
.functype
= RESUME_READ_FUNC_RDSOCK_CMD
;
1220 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
1221 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RDSOCK_CMD
)){
1222 LIBCOR_ASSERT_ERR();
1223 } else if (unlikely(nr_rd
->fd
!= fd
)) {
1224 LIBCOR_ASSERT_ERR();
1226 __u8 state
= nr_rd
->state
;
1230 } else if (state
== 2) {
1232 } else if (unlikely(state
!= 0)) {
1233 LIBCOR_ASSERT_ERR();
1237 if (sizeof(nr_rd
->buf
) != 8)
1238 LIBCOR_ASSERT_ERR();
1240 rc
= read_fully(fd
, nr
, (char *) &(nr_rd
->buf
[0]), 8, 0);
1242 return bzero_nr_iffinished(nr
, rc
);
1244 ((char *) &(nr_rd
->cmd
))[0] = nr_rd
->buf
[0];
1245 ((char *) &(nr_rd
->cmd
))[1] = nr_rd
->buf
[1];
1246 ((char *) &(nr_rd
->cmd
))[2] = nr_rd
->buf
[2];
1247 ((char *) &(nr_rd
->cmd
))[3] = nr_rd
->buf
[3];
1248 ((char *) &(nr_rd
->cmddatalen
))[0] = nr_rd
->buf
[4];
1249 ((char *) &(nr_rd
->cmddatalen
))[1] = nr_rd
->buf
[5];
1250 ((char *) &(nr_rd
->cmddatalen
))[2] = nr_rd
->buf
[6];
1251 ((char *) &(nr_rd
->cmddatalen
))[3] = nr_rd
->buf
[7];
1253 nr_rd
->cmd
= ntohl(nr_rd
->cmd
);
1254 nr_rd
->cmddatalen
= ntohl(nr_rd
->cmddatalen
);
1256 if (nr_rd
->cmddatalen
> 65536)
1259 nr_rd
->cmddata
= malloc(nr_rd
->cmddatalen
);
1260 if (nr_rd
->cmddata
== 0)
1265 rc
= read_fully(fd
, nr
, nr_rd
->cmddata
, nr_rd
->cmddatalen
, 0);
1267 if (rc
!= RC_WOULDBLOCK
) {
1268 free(nr_rd
->cmddata
);
1271 return bzero_nr_iffinished(nr
, rc
);
1274 cmd
->cmd
= nr_rd
->cmd
;
1275 cmd
->cmddata
= nr_rd
->cmddata
;
1276 cmd
->cmddatalen
= nr_rd
->cmddatalen
;
1282 rc
= read_discard(fd
, nr
, nr_rd
->cmddatalen
);
1284 return bzero_nr_iffinished(nr
, rc
);
1286 return bzero_nr_iffinished(nr
, rc
);
1289 int read_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
1291 int rc
= RC_WOULDBLOCK
;
1292 struct libcor_nonblock_resumeinfo nr
;
1293 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1295 rc
= read_rdsock_cmd_nonblock(fd
, &nr
, cmd
);
1296 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1297 LIBCOR_ASSERT_ERR();
1298 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);