2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2019
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>
28 #include <arpa/inet.h>
35 #define likely(x) __builtin_expect((x), 1)
36 #define unlikely(x) __builtin_expect((x), 0)
38 #define CD_CONTINUE_ON_ERROR_FLAG 32768
40 #define CD_CONNECT_NB 1
41 #define CD_CONNECT_PORT 2
42 #define CD_LIST_NEIGH 3
43 #define CD_LIST_SERVICES 4
47 #define CDR_EXECOK_BINDATA 2
48 #define CDR_EXECOK_BINDATA_NORESP 3
50 #define CDR_EXECFAILED 4
51 #define CDR_EXECFAILED_INVALID_COMMAND 1
52 #define CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESOURCES 2
53 #define CDR_EXECFAILED_NB_DOESNTEXIST 3
54 #define CDR_EXECFAILED_UNKNOWN_L4PROTOCOL 4
55 #define CDR_EXECFAILED_PORTCLOSED 5
59 #define LIST_NEIGH_FIELD_ADDR 1
60 #define LIST_NEIGH_FIELD_LATENCY 2
62 #define L4PROTO_STREAM 42399
65 static int bzero_nr_iffinished(struct libcor_nonblock_resumeinfo
*nr
, int rc
)
67 /*if (rc == RC_WOULDBLOCK) {
68 printf("wouldblock\n");
71 if (rc
!= RC_WOULDBLOCK
) {
72 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
77 #define LIBCOR_ASSERT_ERR() \
86 #warning todo commands are sent via multiple packets
87 int resume_send(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
89 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!=fd
))
92 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
||
93 unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
96 while (nr
->data
.write
.totalsent
< nr
->data
.write
.len
) {
97 char *buf
= &(nr
->data
.write
.buf
[0]);
98 #warning todo use ssize_t (other places too?)
99 int sent
= send(fd
, buf
+ nr
->data
.write
.totalsent
,
100 nr
->data
.write
.len
- nr
->data
.write
.totalsent
,
103 if (sent
< 0 && (errno
== EAGAIN
||
104 errno
== EWOULDBLOCK
))
105 return bzero_nr_iffinished(nr
, RC_WOULDBLOCK
);
112 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
115 nr
->data
.write
.totalsent
+= sent
;
118 return bzero_nr_iffinished(nr
, RC_OK
);
121 static int read_fully(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
122 char *buf
, __u32 len
, __u32
*maxread
)
126 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
129 if (unlikely(nr
->data
.read
.read_fully
.state
!= 0 && (
130 nr
->data
.read
.read_fully
.fd
!= fd
||
131 nr
->data
.read
.read_fully
.buf
!= buf
||
132 nr
->data
.read
.read_fully
.len
!= len
||
133 nr
->data
.read
.read_fully
.maxread
!= maxread
)))
136 if (nr
->data
.read
.read_fully
.state
== 1) {
138 } else if (unlikely(nr
->data
.read
.read_fully
.state
!= 0)) {
142 nr
->data
.read
.read_fully
.fd
= fd
;
143 nr
->data
.read
.read_fully
.buf
= buf
;
144 nr
->data
.read
.read_fully
.len
= len
;
145 nr
->data
.read
.read_fully
.maxread
= maxread
;
146 nr
->data
.read
.read_fully
.totalread
= 0;
148 nr
->data
.read
.read_fully
.state
= 1;
152 if (len
> (*maxread
)) {
153 printf("error in read_fully: maxread reached\n");
160 while (len
> nr
->data
.read
.read_fully
.totalread
) {
161 int rcvd
= recv(fd
, buf
+ nr
->data
.read
.read_fully
.totalread
,
162 len
- nr
->data
.read
.read_fully
.totalread
, 0);
165 if (rcvd
< 0 && (errno
== EAGAIN
||
166 errno
== EWOULDBLOCK
)) {
167 /* printf("wouldblock\n"); */
181 /*printf("rcvd: %d:", rcvd);
182 for(u=0;u<rcvd;u++) {
183 printf(" %d, ", (__s32) ((__u8) buf[totalread+u]));
187 nr
->data
.read
.read_fully
.totalread
+= (__u32
) rcvd
;
191 if (rc
!= RC_WOULDBLOCK
) {
192 bzero(&(nr
->data
.read
.read_fully
),
193 sizeof(nr
->data
.read
.read_fully
));
199 static int read_discard(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
205 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
208 if (unlikely(nr
->data
.read
.read_discard
.state
!= 0 && (
209 nr
->data
.read
.read_discard
.fd
!= fd
||
210 nr
->data
.read
.read_discard
.len
!= len
)))
213 if (nr
->data
.read
.read_discard
.state
== 1) {
215 } else if (unlikely(nr
->data
.read
.read_discard
.state
!= 0)) {
219 nr
->data
.read
.read_discard
.fd
= fd
;
220 nr
->data
.read
.read_discard
.len
= len
;
221 nr
->data
.read
.read_discard
.discarded
= 0;
224 nr
->data
.read
.read_discard
.state
= 1;
230 __u32 rcvlen
= len
- nr
->data
.read
.read_discard
.discarded
;
234 rcvd
= recv(fd
, buf
, rcvlen
, 0);
236 if (rcvd
< 0 && (errno
== EAGAIN
||
237 errno
== EWOULDBLOCK
)) {
251 nr
->data
.read
.read_discard
.discarded
-= rcvd
;
255 if (rc
!= RC_WOULDBLOCK
) {
256 bzero(&(nr
->data
.read
.read_discard
),
257 sizeof(nr
->data
.read
.read_discard
));
263 int encode_len(char *buf
, int buflen
, __u32 len
)
265 if (unlikely(buf
== 0))
267 if (unlikely(buflen
< 4))
273 } else if (len
< 16512) {
274 __u16 len_be
= htons(len
- 128);
275 char *len_p
= (char *) &len_be
;
277 buf
[0] = len_p
[0] + 128;
280 } else if (len
< 1073758336) {
281 __u32 len_be
= htonl(len
- 16512);
282 char *len_p
= (char *) &len_be
;
284 buf
[0] = len_p
[0] + 192;
294 int decode_len(char *buf
, int buflen
, __u32
*len
)
296 __u8 b0
= (__u8
) buf
[0];
300 if (buflen
>= 1 && b0
< 128) {
301 *len
= (__u8
) buf
[0];
303 } else if (buflen
>= 2 && b0
>= 128 && b0
< 192) {
304 ((char *) len
)[0] = buf
[0] - 128;
305 ((char *) len
)[1] = buf
[1];
307 *len
= ntohs(*len
) + 128;
309 } else if (buflen
>= 4 && b0
>= 192) {
310 ((char *) len
)[0] = buf
[0] - 192;
311 ((char *) len
)[1] = buf
[1];
312 ((char *) len
)[2] = buf
[2];
313 ((char *) len
)[3] = buf
[3];
315 *len
= ntohl(*len
) + 16512;
322 static int read_len(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
323 __u32
*len
, __u32
*maxread
)
325 int rc
= RC_CONNBROKEN
;
327 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
330 if (unlikely(nr
->data
.read
.read_len
.state
!= 0 && (
331 nr
->data
.read
.read_len
.fd
!= fd
||
332 nr
->data
.read
.read_len
.len
!= len
||
333 nr
->data
.read
.read_len
.maxread
!= maxread
)))
336 if (sizeof(nr
->data
.read
.read_len
.buf
) != 4)
339 if (nr
->data
.read
.read_len
.state
== 1) {
341 } else if (unlikely(nr
->data
.read
.read_len
.state
!= 0)) {
345 nr
->data
.read
.read_len
.fd
= fd
;
346 nr
->data
.read
.read_len
.len
= len
;
347 nr
->data
.read
.read_len
.maxread
= maxread
;
348 bzero(&(nr
->data
.read
.read_len
.buf
[0]), 4);
349 nr
->data
.read
.read_len
.read
= 0;
353 nr
->data
.read
.read_len
.state
= 1;
355 if (nr
->data
.read
.read_len
.read
>= 4) {
356 printf("error in readlen: read to high\n");
361 rc
= read_fully(fd
, nr
, &(nr
->data
.read
.read_len
.buf
[0]) +
362 nr
->data
.read
.read_len
.read
, 1, maxread
);
366 nr
->data
.read
.read_len
.read
++;
368 rc
= decode_len(&(nr
->data
.read
.read_len
.buf
[0]),
369 nr
->data
.read
.read_len
.read
, len
);
371 if (unlikely(rc
< nr
->data
.read
.read_len
.read
)) {
372 printf("error in readlen: decode_len has not "
373 "consumed the whole buffer\n");
383 if (rc
!= RC_WOULDBLOCK
) {
384 bzero(&(nr
->data
.read
.read_len
),
385 sizeof(nr
->data
.read
.read_len
));
391 static int _send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
, __u16 cmd
)
398 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!= fd
))
402 buf
[0] = ((char *) &cmd
)[0];
403 buf
[1] = ((char *) &cmd
)[1];
405 rc
= encode_len(&(buf
[2]), 4, nr
->data
.write
.len
);
406 if (rc
<= 0 || rc
> 4)
409 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
412 hdrlen
= 2 + ((__u32
) rc
);
414 if (unlikely(nr
->data
.write
.len
+ hdrlen
< nr
->data
.write
.len
||
415 nr
->data
.write
.len
+ hdrlen
> WRITE_BUF_SIZE
))
418 memmove(&(nr
->data
.write
.buf
[hdrlen
]), &(nr
->data
.write
.buf
[0]),
420 memcpy(&(nr
->data
.write
.buf
[0]), &(buf
[0]), hdrlen
);
421 nr
->data
.write
.len
+= hdrlen
;
423 return resume_send(fd
, nr
);
426 static int send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
427 __u16 cmd
, char *buf
, __u32 len
)
429 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
432 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
433 nr
->type
= RESUME_TYPE_WRITE
;
434 nr
->data
.write
.fd
= fd
;
436 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
439 if (unlikely(WRITE_BUF_SIZE
< len
))
443 memcpy(&(nr
->data
.write
.buf
[0]), buf
, len
);
444 nr
->data
.write
.len
= len
;
447 return _send_cmd(fd
, nr
, cmd
);
450 int read_resp_nonblock(int fd
, int expect_bindata
,
451 struct libcor_nonblock_resumeinfo
*nr
)
455 struct libcor_nonblock_resumeinfo_resp
*nr_resp
=
456 &(nr
->data
.read
.funcdata
.resp
);
458 if (nr
->type
== RESUME_TYPE_NONE
) {
459 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
460 nr
->type
= RESUME_TYPE_READ
;
461 nr
->data
.read
.functype
= RESUME_READ_FUNC_RESP
;
463 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
464 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RESP
)) {
466 } else if (unlikely(nr_resp
->fd
!= fd
)) {
469 __u8 state
= nr_resp
->state
;
473 } else if (unlikely(state
!= 0)) {
478 nr_resp
->respcode
= 0;
479 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->respcode
), 1, 0);
482 return bzero_nr_iffinished(nr
, rc
);
484 //printf("read_resp: respcode = %d\n", nr_resp->respcode);
486 if (nr_resp
->respcode
== CDR_EXECFAILED
) {
487 /* printf("crd_execfailed\n"); */
489 nr_resp
->reasoncode
= 0;
493 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->reasoncode
), 2, 0);
495 return bzero_nr_iffinished(nr
, rc
);
497 nr_resp
->reasoncode
= ntohs(nr_resp
->reasoncode
);
499 printf("execfailed: reasoncode = %d\n", (__s32
)
500 nr_resp
->reasoncode
);
503 if (expect_bindata
) {
504 if (nr_resp
->respcode
== CDR_EXECOK
)
505 printf("execfailed: received execok, expected execok_bindata\n");
506 else if (nr_resp
->respcode
== CDR_EXECOK_BINDATA
)
507 return bzero_nr_iffinished(nr
, RC_OK
);
509 eue CDR_EXECOK_BINDATA
510 if (nr_resp
->respcode
== CDR_EXECOK
)
511 return bzero_nr_iffinished(nr
, RC_OK
);
512 else if (nr_resp
->respcode
== CDR_EXECOK_BINDATA
)
513 printf("execfailed: received execok_bindata, expected execok\n");
516 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
519 int read_resp(int fd
, int expect_bindata
)
521 int rc
= RC_WOULDBLOCK
;
522 struct libcor_nonblock_resumeinfo nr
;
523 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
525 rc
= read_resp_nonblock(fd
, expect_bindata
, &nr
);
526 if (unlikely(rc
== RC_WOULDBLOCK
)) {
528 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
533 #warning todo replace LIBCOR_ASSERT_ERR
534 int send_connect_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
540 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
543 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
544 nr
->type
= RESUME_TYPE_WRITE
;
545 nr
->data
.write
.fd
= fd
;
547 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
550 if (unlikely(WRITE_BUF_SIZE
< 8))
553 memcpy(&(nr
->data
.write
.buf
[0]), (char *) &addr
, 8);
554 nr
->data
.write
.len
= 8;
556 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
559 return _send_cmd(fd
, nr
, CD_CONNECT_NB
);
562 int send_connect_neigh(int fd
, __be64 addr
)
564 int rc
= RC_WOULDBLOCK
;
565 struct libcor_nonblock_resumeinfo nr
;
566 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
568 rc
= send_connect_neigh_nonblock(fd
, &nr
, addr
);
569 if (unlikely(rc
== RC_WOULDBLOCK
)) {
571 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
576 int send_connect_port_nonblock(int fd
,
577 struct libcor_nonblock_resumeinfo
*nr
, __be32 port
)
579 char *p_port
= (char *) &port
;
581 cmd
[0] = L4PROTO_STREAM
/ 256;
582 cmd
[1] = L4PROTO_STREAM
% 256;
587 return send_cmd(fd
, nr
, CD_CONNECT_PORT
, &(cmd
[0]), 6);
590 int send_connect_port(int fd
, __be32 port
)
592 int rc
= RC_WOULDBLOCK
;
593 struct libcor_nonblock_resumeinfo nr
;
594 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
596 rc
= send_connect_port_nonblock(fd
, &nr
, port
);
597 if (unlikely(rc
== RC_WOULDBLOCK
)) {
599 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
604 int send_list_services_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
606 return send_cmd(fd
, nr
, CD_LIST_SERVICES
| CD_CONTINUE_ON_ERROR_FLAG
,
610 int send_list_services(int fd
)
612 int rc
= RC_WOULDBLOCK
;
613 struct libcor_nonblock_resumeinfo nr
;
614 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
616 rc
= send_list_services_nonblock(fd
, &nr
);
617 if (unlikely(rc
== RC_WOULDBLOCK
)) {
619 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
624 int read_service_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
626 void (*init
)(void *ptr
, __u32 numservices
),
627 void (*next_service
)(void *ptr
, __be32 port
))
631 struct libcor_nonblock_resumeinfo_servicelist
*nr_sl
=
632 &(nr
->data
.read
.funcdata
.servicelist
);
634 if (nr
->type
== RESUME_TYPE_NONE
) {
635 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
636 nr
->type
= RESUME_TYPE_READ
;
637 nr
->data
.read
.functype
= RESUME_READ_FUNC_SERVICELIST
;
641 nr_sl
->next_service
= next_service
;
642 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
643 nr
->data
.read
.functype
!=
644 RESUME_READ_FUNC_SERVICELIST
)) {
646 } else if (unlikely(nr_sl
->fd
!= fd
||
648 nr_sl
->init
!= init
||
649 nr_sl
->next_service
!= next_service
)) {
652 __u8 state
= nr_sl
->state
;
655 } else if (state
== 2) {
657 } else if (unlikely(state
!= 0)) {
662 rc
= read_len(fd
, nr
, &(nr_sl
->len
), 0);
664 return bzero_nr_iffinished(nr
, rc
);
668 rc
= read_len(fd
, nr
, &(nr_sl
->numservices
), &(nr_sl
->len
));
670 return bzero_nr_iffinished(nr
, rc
);
672 init(ptr
, nr_sl
->numservices
);
674 for(nr_sl
->q
=0; nr_sl
->q
< nr_sl
->numservices
; nr_sl
->q
++) {
679 rc
= read_fully(fd
, nr
, (char *) &(nr_sl
->port
), 4,
682 return bzero_nr_iffinished(nr
, rc
);
684 next_service(ptr
, nr_sl
->port
);
688 return bzero_nr_iffinished(nr
, rc
);
691 int read_service_list(int fd
, void *ptr
,
692 void (*init
)(void *ptr
, __u32 numservices
),
693 void (*next_service
)(void *ptr
, __be32 port
))
695 int rc
= RC_WOULDBLOCK
;
696 struct libcor_nonblock_resumeinfo nr
;
697 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
699 rc
= read_service_list_nonblock(fd
, &nr
, ptr
, init
, next_service
);
700 if (unlikely(rc
== RC_WOULDBLOCK
)) {
702 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
708 int send_list_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
710 return send_cmd(fd
, nr
, CD_LIST_NEIGH
| CD_CONTINUE_ON_ERROR_FLAG
,
714 int send_list_neigh(int fd
)
716 int rc
= RC_WOULDBLOCK
;
717 struct libcor_nonblock_resumeinfo nr
;
718 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
720 rc
= send_list_neigh_nonblock(fd
, &nr
);
721 if (unlikely(rc
== RC_WOULDBLOCK
)) {
723 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
728 static int field_present(struct listneigh_field
*fields
, __u32 numfields
,
732 for(u
=0;u
<numfields
;u
++) {
733 if (fields
[u
].field
== field
)
739 int read_neigh_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
741 void (*init
)(void *ptr
, __u32 numneigh
),
742 void (*next_neigh
)(void *ptr
, __be64 addr
))
746 struct libcor_nonblock_resumeinfo_neighlist
*nr_nl
=
747 &(nr
->data
.read
.funcdata
.neighlist
);
749 if (nr
->type
== RESUME_TYPE_NONE
) {
750 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
751 nr
->type
= RESUME_TYPE_READ
;
752 nr
->data
.read
.functype
= RESUME_READ_FUNC_NEIGHLIST
;
756 nr_nl
->next_neigh
= next_neigh
;
757 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
758 nr
->data
.read
.functype
!= RESUME_READ_FUNC_NEIGHLIST
)) {
760 } else if (unlikely(nr_nl
->fd
!= fd
||
762 nr_nl
->init
!= init
||
763 nr_nl
->next_neigh
!= next_neigh
)) {
766 __u8 state
= nr_nl
->state
;
769 } else if (state
== 2) {
771 } else if (state
== 3) {
773 } else if (state
== 4) {
775 } else if (state
== 5) {
777 } else if (state
== 6) {
779 } else if (state
== 7) {
781 } else if (state
== 8) {
783 } else if (unlikely(state
!= 0)) {
788 rc
= read_len(fd
, nr
, &(nr_nl
->len
), 0);
790 return bzero_nr_iffinished(nr
, rc
);
794 rc
= read_len(fd
, nr
, &(nr_nl
->numneighs
), &(nr_nl
->len
));
796 return bzero_nr_iffinished(nr
, rc
);
800 rc
= read_len(fd
, nr
, &(nr_nl
->numfields
), &(nr_nl
->len
));
802 return bzero_nr_iffinished(nr
, rc
);
804 if (unlikely(nr_nl
->numfields
> NEIGHLIST_MAX_FIELDS
))
805 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
807 for(nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numfields
; nr_nl
->u
++) {
808 nr_nl
->fields
[nr_nl
->u
].field
= 0;
812 rc
= read_fully(fd
, nr
,
813 (char *) &(nr_nl
->fields
[nr_nl
->u
].field
),
816 return bzero_nr_iffinished(nr
, rc
);
817 nr_nl
->fields
[nr_nl
->u
].field
=
818 ntohs(nr_nl
->fields
[nr_nl
->u
].field
);
823 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
), &(nr_nl
->len
));
825 return bzero_nr_iffinished(nr
, rc
);
827 if (unlikely(nr_nl
->fieldlen
> 65535))
828 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
830 nr_nl
->fields
[nr_nl
->u
].len
= (__u16
) nr_nl
->fieldlen
;
834 if (unlikely(field_present(nr_nl
->fields
, nr_nl
->numfields
,
835 LIST_NEIGH_FIELD_ADDR
) == 0))
836 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
838 init(ptr
, nr_nl
->numneighs
);
840 for (nr_nl
->u
=0; nr_nl
->u
< nr_nl
->numneighs
; nr_nl
->u
++) {
844 for(nr_nl
->v
=0; nr_nl
->v
< nr_nl
->numfields
; nr_nl
->v
++) {
845 nr_nl
->fieldlen
= nr_nl
->fields
[nr_nl
->v
].len
;
846 if (nr_nl
->fieldlen
== 0) {
849 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
),
852 return bzero_nr_iffinished(nr
, rc
);
855 if (nr_nl
->fieldlen
> nr_nl
->len
)
856 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
858 nr_nl
->len
-= nr_nl
->fieldlen
;
860 if (field_present(nr_nl
->fields
, nr_nl
->v
,
861 nr_nl
->fields
[nr_nl
->v
].field
)) {
863 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
864 LIST_NEIGH_FIELD_ADDR
) {
865 if (unlikely(nr_nl
->fieldlen
!= 8))
868 ASSERT(sizeof(nr_nl
->addr
) == 8);
872 rc
= read_fully(fd
, nr
, (char *) &(nr_nl
->addr
),
873 8, &(nr_nl
->fieldlen
));
875 return bzero_nr_iffinished(nr
, rc
);
877 if (unlikely(ntohll(nr_nl
->addr
) == 0))
878 return RC_CONNBROKEN
;
879 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
880 LIST_NEIGH_FIELD_LATENCY
) {
885 rc
= read_fully(fd
, nr
, &nr_nl
->latency
, 1,
888 return bzero_nr_iffinished(nr
, rc
);
890 printf("latency %d\n", (int) nr_nl
->latency
);
894 if (nr_nl
->fieldlen
> 0) {
897 rc
= read_discard(fd
, nr
, nr_nl
->fieldlen
);
899 return bzero_nr_iffinished(nr
, rc
);
905 next_neigh(ptr
, nr_nl
->addr
);
910 return bzero_nr_iffinished(nr
, rc
);
913 int read_neigh_list(int fd
, void *ptr
,
914 void (*init
)(void *ptr
, __u32 numneighs
),
915 void (*next_neigh
)(void *ptr
, __be64 addr
))
917 int rc
= RC_WOULDBLOCK
;
918 struct libcor_nonblock_resumeinfo nr
;
919 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
921 rc
= read_neigh_list_nonblock(fd
, &nr
, ptr
, init
, next_neigh
);
922 if (unlikely(rc
== RC_WOULDBLOCK
)) {
924 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
929 int pass_socket(int fd
, __u64 cookie
)
933 rc
= setsockopt(fd
, SOL_COR
, COR_PASS_ON_CLOSE
, &cookie
, 8);
935 perror("pass_socket");
936 return RC_CONNBROKEN
;
944 static int send_rdsock_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
945 __u32 cmd
, char *data
, __u32 datalen
)
947 __u32 be_cmd
= htonl(cmd
);
948 __u32 be_datalen
= htonl(datalen
);
950 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
953 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
954 nr
->type
= RESUME_TYPE_WRITE
;
955 nr
->data
.write
.fd
= fd
;
957 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
960 if (unlikely(datalen
+ 8 < datalen
|| WRITE_BUF_SIZE
< (datalen
+ 8)))
963 memcpy(&(nr
->data
.write
.buf
[0]), (char *) &be_cmd
, 4);
964 memcpy(&(nr
->data
.write
.buf
[4]), (char *) &be_datalen
, 4);
965 memcpy(&(nr
->data
.write
.buf
[8]), data
, datalen
);
966 nr
->data
.write
.len
= datalen
+ 8;
968 return resume_send(fd
, nr
);
971 int send_rdsock_version_nonblock(int fd
,
972 struct libcor_nonblock_resumeinfo
*nr
,
977 version
= htonl(version
);
979 memcpy(&(data
[0]), (char *) &version
, 4);
981 return send_rdsock_cmd(fd
, nr
, CRD_UTK_VERSION
, &(data
[0]), 4);
984 int send_rdsock_version(int fd
, __u32 version
)
986 int rc
= RC_WOULDBLOCK
;
987 struct libcor_nonblock_resumeinfo nr
;
988 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
990 rc
= send_rdsock_version_nonblock(fd
, &nr
, version
);
991 if (unlikely(rc
== RC_WOULDBLOCK
)) {
993 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
998 int send_rdsock_up_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
999 int has_addr
, __be64 addr
)
1007 if (has_addr
== 0 && addr
!= 0)
1008 return RC_CONNBROKEN
;
1011 flags
|= CRD_UTK_UP_FLAGS_ADDR
;
1013 flags
= htonll(flags
);
1015 memcpy(&(data
[0]), (char *) &flags
, 8);
1016 memcpy(&(data
[8]), (char *) &addr
, 8);
1018 return send_rdsock_cmd(fd
, nr
, CRD_UTK_UP
, &(data
[0]), 16);
1020 flags
= htonll(flags
);
1022 memcpy(&(data
[0]), (char *) &flags
, 8);
1024 return send_rdsock_cmd(fd
, nr
, CRD_UTK_UP
, &(data
[0]), 8);
1028 int send_rdsock_up(int fd
, int has_addr
, __be64 addr
)
1030 int rc
= RC_WOULDBLOCK
;
1031 struct libcor_nonblock_resumeinfo nr
;
1032 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1034 rc
= send_rdsock_up_nonblock(fd
, &nr
, has_addr
, addr
);
1035 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1036 LIBCOR_ASSERT_ERR();
1037 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1042 int send_rdsock_connecterror_nonblock(int fd
,
1043 struct libcor_nonblock_resumeinfo
*nr
,
1044 __u64 cookie
, __u32 error
)
1048 error
= htonl(error
);
1050 memcpy(&(data
[0]), (char *) &cookie
, 8);
1051 memcpy(&(data
[8]), (char *) &error
, 4);
1053 return send_rdsock_cmd(fd
, nr
, CRD_UTK_CONNECTERROR
, &(data
[0]), 12);
1056 int send_rdsock_connecterror(int fd
, __u64 cookie
, __u32 error
)
1058 int rc
= RC_WOULDBLOCK
;
1059 struct libcor_nonblock_resumeinfo nr
;
1060 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1062 rc
= send_rdsock_connecterror_nonblock(fd
, &nr
, cookie
, error
);
1063 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1064 LIBCOR_ASSERT_ERR();
1065 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1070 int parse_rdsock_supported_versions(struct rdsock_cmd
*cmd
,
1071 __u32
*versionmin
, __u32
*versionmax
)
1073 if (cmd
->cmddatalen
!= 8)
1076 memcpy((char *) versionmin
, cmd
->cmddata
, 4);
1077 *versionmin
= htonl(*versionmin
);
1078 memcpy((char *) versionmax
, cmd
->cmddata
+ 4, 4);
1079 *versionmax
= htonl(*versionmax
);
1084 int parse_rdsock_connect(void *ptr
, struct rdsock_cmd
*cmd
,
1085 int (*proc_connect
)(void *ptr
, __u64 cookie
,
1086 struct cor_sockaddr
*addr
, __u32 tos
))
1089 struct cor_sockaddr addr
;
1092 if ((sizeof(struct cor_sockaddr
) + 12) != cmd
->cmddatalen
)
1095 memcpy((char *) &cookie
, cmd
->cmddata
, 8);
1097 memcpy((char *) &addr
, cmd
->cmddata
+ 8, sizeof(struct cor_sockaddr
));
1099 memcpy((char *) &tos
, cmd
->cmddata
+ 8 + sizeof(struct cor_sockaddr
),
1103 return proc_connect(ptr
, cookie
, &addr
, tos
);
1106 int read_rdsock_cmd_nonblock(int fd
,
1107 struct libcor_nonblock_resumeinfo
*nr
,
1108 struct rdsock_cmd
*cmd
)
1112 struct libcor_nonblock_resumeinfo_rdsockcmd
*nr_rd
=
1113 &(nr
->data
.read
.funcdata
.rdsock_cmd
);
1115 bzero(cmd
, sizeof(struct rdsock_cmd
));
1117 if (nr
->type
== RESUME_TYPE_NONE
) {
1118 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1119 nr
->type
= RESUME_TYPE_READ
;
1120 nr
->data
.read
.functype
= RESUME_READ_FUNC_RDSOCK_CMD
;
1122 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
1123 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RDSOCK_CMD
)){
1124 LIBCOR_ASSERT_ERR();
1125 } else if (unlikely(nr_rd
->fd
!= fd
)) {
1126 LIBCOR_ASSERT_ERR();
1128 __u8 state
= nr_rd
->state
;
1132 } else if (state
== 2) {
1134 } else if (unlikely(state
!= 0)) {
1135 LIBCOR_ASSERT_ERR();
1139 if (sizeof(nr_rd
->buf
) != 8)
1140 LIBCOR_ASSERT_ERR();
1142 rc
= read_fully(fd
, nr
, (char *) &(nr_rd
->buf
[0]), 8, 0);
1144 return bzero_nr_iffinished(nr
, rc
);
1146 ((char *) &(nr_rd
->cmd
))[0] = nr_rd
->buf
[0];
1147 ((char *) &(nr_rd
->cmd
))[1] = nr_rd
->buf
[1];
1148 ((char *) &(nr_rd
->cmd
))[2] = nr_rd
->buf
[2];
1149 ((char *) &(nr_rd
->cmd
))[3] = nr_rd
->buf
[3];
1150 ((char *) &(nr_rd
->cmddatalen
))[0] = nr_rd
->buf
[4];
1151 ((char *) &(nr_rd
->cmddatalen
))[1] = nr_rd
->buf
[5];
1152 ((char *) &(nr_rd
->cmddatalen
))[2] = nr_rd
->buf
[6];
1153 ((char *) &(nr_rd
->cmddatalen
))[3] = nr_rd
->buf
[7];
1155 nr_rd
->cmd
= ntohl(nr_rd
->cmd
);
1156 nr_rd
->cmddatalen
= ntohl(nr_rd
->cmddatalen
);
1158 if (nr_rd
->cmddatalen
> 65536)
1161 nr_rd
->cmddata
= malloc(nr_rd
->cmddatalen
);
1162 if (nr_rd
->cmddata
== 0)
1167 rc
= read_fully(fd
, nr
, nr_rd
->cmddata
, nr_rd
->cmddatalen
, 0);
1169 if (rc
!= RC_WOULDBLOCK
) {
1170 free(nr_rd
->cmddata
);
1173 return bzero_nr_iffinished(nr
, rc
);
1176 cmd
->cmd
= nr_rd
->cmd
;
1177 cmd
->cmddata
= nr_rd
->cmddata
;
1178 cmd
->cmddatalen
= nr_rd
->cmddatalen
;
1184 rc
= read_discard(fd
, nr
, nr_rd
->cmddatalen
);
1186 return bzero_nr_iffinished(nr
, rc
);
1188 return bzero_nr_iffinished(nr
, rc
);
1191 int read_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
1193 int rc
= RC_WOULDBLOCK
;
1194 struct libcor_nonblock_resumeinfo nr
;
1195 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1197 rc
= read_rdsock_cmd_nonblock(fd
, &nr
, cmd
);
1198 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1199 LIBCOR_ASSERT_ERR();
1200 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);