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_SET_FORWARD_TIMEOUT 4
39 #define CD_SET_BACKWARD_TIMEOUT 5
43 #define CDR_EXECFAILED 2
44 #define CDR_EXECFAILED_UNKNOWN_COMMAND 1
45 #define CDR_EXECFAILED_PERMISSION_DENIED 2
46 #define CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES 3
47 #define CDR_EXECFAILED_CMD_TOO_SHORT 4
48 #define CDR_EXECFAILED_CMD_TOO_LONG 5
49 #define CDR_EXECFAILED_TARGETADDR_DOESNTEXIST 6
50 #define CDR_EXECFAILED_PORTCLOSED 7
51 #define CDR_EXECFAILED_LISTENERQUEUE_FULL 8
52 #define CDR_EXECFAILED_ILLEGAL_COMMAND 9
56 #define LIST_NEIGH_FIELD_ADDR 1
57 #define LIST_NEIGH_FIELD_LATENCY 2
60 static int bzero_nr_iffinished(struct libcor_nonblock_resumeinfo
*nr
, int rc
)
62 if (rc
!= RC_WOULDBLOCK
) {
63 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
68 #define LIBCOR_ASSERT_ERR() \
76 #warning todo commands are sent via multiple packets
77 int resume_send(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
79 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!=fd
))
82 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
||
83 unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
86 while (nr
->data
.write
.totalsent
< nr
->data
.write
.len
) {
87 char *buf
= &(nr
->data
.write
.buf
[0]);
88 int sent
= send(fd
, buf
+ nr
->data
.write
.totalsent
,
89 nr
->data
.write
.len
- nr
->data
.write
.totalsent
,
93 printf("non-blocking write not supported");
102 return RC_CONNBROKEN
;
105 nr
->data
.write
.totalsent
+= sent
;
111 static int read_fully(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
112 char *buf
, __u32 len
, __u32
*maxread
)
116 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
119 if (unlikely(nr
->data
.read
.read_fully
.state
!= 0 && (
120 nr
->data
.read
.read_fully
.fd
!= fd
||
121 nr
->data
.read
.read_fully
.buf
!= buf
||
122 nr
->data
.read
.read_fully
.len
!= len
||
123 nr
->data
.read
.read_fully
.maxread
!= maxread
)))
126 if (nr
->data
.read
.read_fully
.state
== 1) {
128 } else if (unlikely(nr
->data
.read
.read_fully
.state
!= 0)) {
132 nr
->data
.read
.read_fully
.fd
= fd
;
133 nr
->data
.read
.read_fully
.buf
= buf
;
134 nr
->data
.read
.read_fully
.len
= len
;
135 nr
->data
.read
.read_fully
.maxread
= maxread
;
136 nr
->data
.read
.read_fully
.totalread
= 0;
138 nr
->data
.read
.read_fully
.state
= 1;
142 if (len
> (*maxread
)) {
143 printf("error in read_fully: maxread reached/n");
150 while (len
> nr
->data
.read
.read_fully
.totalread
) {
151 int rcvd
= recv(fd
, buf
+ nr
->data
.read
.read_fully
.totalread
,
152 len
- nr
->data
.read
.read_fully
.totalread
, 0);
156 printf("non-blocking read not supported");
170 /*printf("rcvd: %d:", rcvd);
171 for(u=0;u<rcvd;u++) {
172 printf(" %d, ", (__s32) ((__u8) buf[totalread+u]));
176 nr
->data
.read
.read_fully
.totalread
+= (__u32
) rcvd
;
180 if (rc
!= RC_WOULDBLOCK
) {
181 bzero(&(nr
->data
.read
.read_fully
),
182 sizeof(nr
->data
.read
.read_fully
));
188 static int read_discard(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
194 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
197 if (unlikely(nr
->data
.read
.read_discard
.state
!= 0 && (
198 nr
->data
.read
.read_discard
.fd
!= fd
||
199 nr
->data
.read
.read_discard
.len
!= len
)))
202 if (nr
->data
.read
.read_discard
.state
== 1) {
204 } else if (unlikely(nr
->data
.read
.read_discard
.state
!= 0)) {
208 nr
->data
.read
.read_discard
.fd
= fd
;
209 nr
->data
.read
.read_discard
.len
= len
;
210 nr
->data
.read
.read_discard
.discarded
= 0;
213 nr
->data
.read
.read_discard
.state
= 1;
219 __u32 rcvlen
= len
- nr
->data
.read
.read_discard
.discarded
;
223 rcvd
= recv(fd
, buf
, rcvlen
, 0);
239 nr
->data
.read
.read_discard
.discarded
-= rcvd
;
243 if (rc
!= RC_WOULDBLOCK
) {
244 bzero(&(nr
->data
.read
.read_discard
),
245 sizeof(nr
->data
.read
.read_discard
));
251 static int encode_len(char *buf
, int buflen
, __u32 len
)
253 if (unlikely(buf
== 0))
256 if (unlikely(buflen
< 4))
265 buf
[0] = (__u8
) ((len
- 128) /256 + 128);
266 buf
[1] = (__u8
) ((len
- 128) & 255);
270 if (len
< 1073741951) {
271 __u32 len_be
= htonl(len
- 16511);
272 char *len_p
= (char *) &len_be
;
274 buf
[0] = len_p
[0] + 192;
284 static int decode_len(char *buf
, int buflen
, __u32
*len
)
286 if (unlikely(buflen
< 1))
289 if ((__u8
) buf
[0] <= 127) {
290 *len
= (__u8
) buf
[0];
297 if ((__u8
) buf
[0] <= 191) {
298 *len
= 128 + ((__u32
) ((__u8
) buf
[0]) - 128) * 256 +
306 ((char *) len
)[0] = buf
[0] - 192;
307 ((char *) len
)[1] = buf
[1];
308 ((char *) len
)[2] = buf
[2];
309 ((char *) len
)[3] = buf
[3];
311 *len
= ntohl(*len
) + 16511;
316 static int read_len(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
317 __u32
*len
, __u32
*maxread
)
319 int rc
= RC_CONNBROKEN
;
321 if (unlikely(nr
->type
!= RESUME_TYPE_READ
))
324 if (unlikely(nr
->data
.read
.read_len
.state
!= 0 && (
325 nr
->data
.read
.read_len
.fd
!= fd
||
326 nr
->data
.read
.read_len
.len
!= len
||
327 nr
->data
.read
.read_len
.maxread
!= maxread
)))
330 if (sizeof(nr
->data
.read
.read_len
.buf
) != 4)
333 if (nr
->data
.read
.read_len
.state
== 1) {
335 } else if (unlikely(nr
->data
.read
.read_len
.state
!= 0)) {
339 nr
->data
.read
.read_len
.fd
= fd
;
340 nr
->data
.read
.read_len
.len
= len
;
341 nr
->data
.read
.read_len
.maxread
= maxread
;
342 bzero(&(nr
->data
.read
.read_len
.buf
[0]), 4);
343 nr
->data
.read
.read_len
.read
= 0;
347 nr
->data
.read
.read_len
.state
= 1;
349 if (nr
->data
.read
.read_len
.read
>= 4) {
350 printf("error in readlen: read to high\n");
354 rc
= read_fully(fd
, nr
, &(nr
->data
.read
.read_len
.buf
[0]) +
355 nr
->data
.read
.read_len
.read
, 1, maxread
);
359 nr
->data
.read
.read_len
.read
++;
361 rc
= decode_len(&(nr
->data
.read
.read_len
.buf
[0]),
362 nr
->data
.read
.read_len
.read
, len
);
364 if (unlikely(rc
< nr
->data
.read
.read_len
.read
)) {
365 printf("error in readlen: decode_len has not "
366 "consumed the whole buffer\n");
380 if (rc
!= RC_WOULDBLOCK
) {
381 bzero(&(nr
->data
.read
.read_len
),
382 sizeof(nr
->data
.read
.read_len
));
388 static int _send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
, __u16 cmd
)
395 if (unlikely(nr
->type
!= RESUME_TYPE_WRITE
|| nr
->data
.write
.fd
!= fd
))
399 buf
[0] = ((char *) &cmd
)[0];
400 buf
[1] = ((char *) &cmd
)[1];
402 rc
= encode_len(&(buf
[2]), 4, nr
->data
.write
.len
);
403 if (rc
<= 0 || rc
> 4)
406 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
409 hdrlen
= 2 + ((__u32
) rc
);
411 if (unlikely(nr
->data
.write
.len
+ hdrlen
< nr
->data
.write
.len
||
412 nr
->data
.write
.len
+ hdrlen
> WRITE_BUF_SIZE
))
415 memmove(&(nr
->data
.write
.buf
[hdrlen
]), &(nr
->data
.write
.buf
[0]),
417 memcpy(&(nr
->data
.write
.buf
[0]), &(buf
[0]), hdrlen
);
418 nr
->data
.write
.len
+= hdrlen
;
420 return resume_send(fd
, nr
);
423 static int send_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
424 __u16 cmd
, char *buf
, __u32 len
)
426 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
429 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
430 nr
->type
= RESUME_TYPE_WRITE
;
431 nr
->data
.write
.fd
= fd
;
433 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
436 if (unlikely(WRITE_BUF_SIZE
< len
))
439 memcpy(&(nr
->data
.write
.buf
[0]), buf
, len
);
440 nr
->data
.write
.len
= len
;
442 return _send_cmd(fd
, nr
, cmd
);
445 int read_resp_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
)
449 struct libcor_nonblock_resumeinfo_resp
*nr_resp
=
450 &(nr
->data
.read
.funcdata
.resp
);
452 if (nr
->type
== RESUME_TYPE_NONE
) {
453 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
454 nr
->type
= RESUME_TYPE_READ
;
455 nr
->data
.read
.functype
= RESUME_READ_FUNC_RESP
;
457 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
458 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RESP
)) {
460 } else if (unlikely(nr_resp
->fd
!= fd
)) {
463 __u8 state
= nr_resp
->state
;
467 } else if (state
== 2) {
469 } else if (state
== 3) {
471 } else if (unlikely(state
!= 0)) {
476 nr_resp
->respcode
= 0;
477 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->respcode
), 1, 0);
480 return bzero_nr_iffinished(nr
, rc
);
482 if (nr_resp
->respcode
== CDR_EXECFAILED
) {
483 nr_resp
->reasoncode
= 0;
487 rc
= read_fully(fd
, nr
, (char *) &(nr_resp
->reasoncode
), 2, 0);
489 return bzero_nr_iffinished(nr
, rc
);
491 nr_resp
->reasoncode
= ntohs(nr_resp
->reasoncode
);
493 printf("execfailed: reasoncode = %d\n", (__s32
)
494 nr_resp
->reasoncode
);
498 rc
= read_len(fd
, nr
, &(nr_resp
->reasonlen
),
501 return bzero_nr_iffinished(nr
, rc
);
505 rc
= read_discard(fd
, nr
, nr_resp
->reasonlen
);
507 return bzero_nr_iffinished(nr
, rc
);
510 while (reasonlen > 0) {
511 __u32 nextread = reasonlen;
513 if (reasonlen > 4093)
515 reasonlen -= nextread;
516 int rc = read_fully(fd, buf, nextread, 0);
527 if (nr_resp
->respcode
== CDR_EXECOK
)
528 return bzero_nr_iffinished(nr
, RC_OK
);
530 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
533 int read_resp(int fd
)
535 int rc
= RC_WOULDBLOCK
;
536 struct libcor_nonblock_resumeinfo nr
;
537 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
539 rc
= read_resp_nonblock(fd
, &nr
);
540 if (unlikely(rc
== RC_WOULDBLOCK
)) {
542 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
548 int send_connect_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
549 __u32 addrlen
, char *addr
)
554 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
557 if (unlikely(addrlen
> (1024 * 1024 * 1024) ||
558 addrlen
+ 4 > WRITE_BUF_SIZE
))
561 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
562 nr
->type
= RESUME_TYPE_WRITE
;
563 nr
->data
.write
.fd
= fd
;
565 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
568 if (unlikely(WRITE_BUF_SIZE
< 4))
571 rc
= encode_len(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), 4, addrlen
);
572 if (unlikely(rc
<= 0 || rc
> 4))
575 nr
->data
.write
.len
+= (__u32
) rc
;
577 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
||
578 WRITE_BUF_SIZE
- nr
->data
.write
.len
< addrlen
))
581 memcpy(&(nr
->data
.write
.buf
[nr
->data
.write
.len
]), addr
, addrlen
);
582 nr
->data
.write
.len
+= addrlen
;
584 if (unlikely(nr
->data
.write
.len
> WRITE_BUF_SIZE
))
587 return _send_cmd(fd
, nr
, CD_CONNECT_NB
);
590 int send_connect_neigh(int fd
, __u32 addrlen
, char *addr
)
592 int rc
= RC_WOULDBLOCK
;
593 struct libcor_nonblock_resumeinfo nr
;
594 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
596 rc
= send_connect_neigh_nonblock(fd
, &nr
, addrlen
, addr
);
597 if (unlikely(rc
== RC_WOULDBLOCK
)) {
599 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
604 int send_connect_port_nonblock(int fd
,
605 struct libcor_nonblock_resumeinfo
*nr
, __u64 port
)
607 __u64 p
= htonll(port
);
608 return send_cmd(fd
, nr
, CD_CONNECT_PORT
, (char *) &p
, 8);
611 int send_connect_port(int fd
, __u64 port
)
613 int rc
= RC_WOULDBLOCK
;
614 struct libcor_nonblock_resumeinfo nr
;
615 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
617 rc
= send_connect_port_nonblock(fd
, &nr
, port
);
618 if (unlikely(rc
== RC_WOULDBLOCK
)) {
620 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
625 int send_list_neigh_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
626 __u32 limit
, __u32 offset
)
632 rc
= encode_len(buf
, 4, limit
);
633 if (unlikely(rc
<= 0))
634 return RC_CONNBROKEN
;
638 rc
= encode_len(buf
+ len
, 4, offset
);
639 if (unlikely(rc
<= 0))
640 return RC_CONNBROKEN
;
644 return send_cmd(fd
, nr
, CD_LIST_NEIGH
, buf
, len
);
647 int send_list_neigh(int fd
, __u32 limit
, __u32 offset
)
649 int rc
= RC_WOULDBLOCK
;
650 struct libcor_nonblock_resumeinfo nr
;
651 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
653 rc
= send_list_neigh_nonblock(fd
, &nr
, limit
, offset
);
654 if (unlikely(rc
== RC_WOULDBLOCK
)) {
656 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
661 static int field_present(struct listneigh_field
*fields
, __u32 numfields
,
665 for(u
=0;u
<numfields
;u
++) {
666 if (fields
[u
].field
== field
)
672 int read_neigh_list_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
674 void (*init
)(void *ptr
, __u32 totalneighs
, __u32 responserows
),
675 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
679 struct libcor_nonblock_resumeinfo_neighlist
*nr_nl
=
680 &(nr
->data
.read
.funcdata
.neighlist
);
682 if (nr
->type
== RESUME_TYPE_NONE
) {
683 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
684 nr
->type
= RESUME_TYPE_READ
;
685 nr
->data
.read
.functype
= RESUME_READ_FUNC_NEIGHLIST
;
689 nr_nl
->next_neigh
= next_neigh
;
690 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
691 nr
->data
.read
.functype
!= RESUME_READ_FUNC_NEIGHLIST
)) {
693 } else if (unlikely(nr_nl
->fd
!= fd
||
695 nr_nl
->init
!= init
||
696 nr_nl
->next_neigh
!= next_neigh
)) {
699 __u8 state
= nr_nl
->state
;
702 } else if (state
== 2) {
704 } else if (state
== 3) {
706 } else if (state
== 4) {
708 } else if (state
== 5) {
710 } else if (state
== 6) {
712 } else if (state
== 7) {
714 } else if (state
== 8) {
716 } else if (state
== 9) {
718 } else if (state
==10) {
720 } else if (state
== 11) {
722 } else if (unlikely(state
!= 0)) {
729 rc
= read_fully(fd
, nr
, (char *) &(nr_nl
->respcode
), 1, 0);
731 return bzero_nr_iffinished(nr
, rc
);
733 if (unlikely(nr_nl
->respcode
!= CDR_BINDATA
))
734 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
738 rc
= read_len(fd
, nr
, &(nr_nl
->len
), 0);
740 return bzero_nr_iffinished(nr
, rc
);
744 rc
= read_len(fd
, nr
, &(nr_nl
->totalneighs
), &(nr_nl
->len
));
746 return bzero_nr_iffinished(nr
, rc
);
750 rc
= read_len(fd
, nr
, &(nr_nl
->response_rows
), &(nr_nl
->len
));
752 return bzero_nr_iffinished(nr
, rc
);
756 rc
= read_len(fd
, nr
, &(nr_nl
->numfields
), &(nr_nl
->len
));
758 return bzero_nr_iffinished(nr
, rc
);
760 if (unlikely(nr_nl
->numfields
> NEIGHLIST_MAX_FIELDS
))
761 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
763 for(nr_nl
->u
=0;nr_nl
->u
<nr_nl
->numfields
;nr_nl
->u
++) {
764 nr_nl
->fields
[nr_nl
->u
].field
= 0;
768 rc
= read_fully(fd
, nr
,
769 (char *) &(nr_nl
->fields
[nr_nl
->u
].field
),
772 return bzero_nr_iffinished(nr
, rc
);
773 nr_nl
->fields
[nr_nl
->u
].field
=
774 ntohs(nr_nl
->fields
[nr_nl
->u
].field
);
779 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
), &(nr_nl
->len
));
781 return bzero_nr_iffinished(nr
, rc
);
783 if (unlikely(nr_nl
->fieldlen
> 65535))
784 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
786 nr_nl
->fields
[nr_nl
->u
].len
= (__u16
) nr_nl
->fieldlen
;
790 if (unlikely(field_present(nr_nl
->fields
, nr_nl
->numfields
,
791 LIST_NEIGH_FIELD_ADDR
) == 0))
792 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
794 init(ptr
, nr_nl
->totalneighs
, nr_nl
->response_rows
);
796 for (nr_nl
->u
=0;nr_nl
->u
<nr_nl
->response_rows
;nr_nl
->u
++) {
797 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
801 for(nr_nl
->v
=0;nr_nl
->v
<nr_nl
->numfields
;nr_nl
->v
++) {
802 nr_nl
->fieldlen
= nr_nl
->fields
[nr_nl
->v
].len
;
803 if (nr_nl
->fieldlen
== 0) {
806 rc
= read_len(fd
, nr
, &(nr_nl
->fieldlen
),
809 return bzero_nr_iffinished(nr
, rc
);
812 if (nr_nl
->fieldlen
> nr_nl
->len
)
813 return bzero_nr_iffinished(nr
, RC_CONNBROKEN
);
815 nr_nl
->len
-= nr_nl
->fieldlen
;
817 if (field_present(nr_nl
->fields
, nr_nl
->v
,
818 nr_nl
->fields
[nr_nl
->v
].field
)) {
820 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
821 LIST_NEIGH_FIELD_ADDR
) {
824 rc
= read_len(fd
, nr
, &(nr_nl
->addrlen
),
827 return bzero_nr_iffinished(nr
, rc
);
829 if (unlikely(nr_nl
->addrlen
> ADDR_MAX_LEN
))
832 if (sizeof(nr_nl
->addr
) != ADDR_MAX_LEN
)
835 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
839 rc
= read_fully(fd
, nr
, &(nr_nl
->addr
[0]),
843 return bzero_nr_iffinished(nr
, rc
);
844 } else if (nr_nl
->fields
[nr_nl
->v
].field
==
845 LIST_NEIGH_FIELD_LATENCY
) {
850 rc
= read_fully(fd
, nr
, &nr_nl
->latency
, 1,
853 return bzero_nr_iffinished(nr
, rc
);
855 printf("latency %d\n", (int) nr_nl
->latency
);
859 if (nr_nl
->fieldlen
> 0) {
862 rc
= read_discard(fd
, nr
, nr_nl
->fieldlen
);
864 return bzero_nr_iffinished(nr
, rc
);
870 if (nr_nl
->addrlen
> ADDR_MAX_LEN
)
873 next_neigh(ptr
, nr_nl
->addrlen
, &(nr_nl
->addr
[0]));
874 bzero(&(nr_nl
->addr
[0]), ADDR_MAX_LEN
);
882 int read_neigh_list(int fd
, void *ptr
,
883 void (*init
)(void *ptr
, __u32 totalneighs
, __u32 responserows
),
884 void (*next_neigh
)(void *ptr
, __u32 addrlen
, char *addr
))
886 int rc
= RC_WOULDBLOCK
;
887 struct libcor_nonblock_resumeinfo nr
;
888 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
890 rc
= read_neigh_list_nonblock(fd
, &nr
, ptr
, init
, next_neigh
);
891 if (unlikely(rc
== RC_WOULDBLOCK
)) {
893 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
898 int pass_socket(int fd
, __u64 cookie
)
902 rc
= setsockopt(fd
, SOL_COR
, COR_PASS_ON_CLOSE
, &cookie
, 8);
904 perror("pass_socket");
905 return RC_CONNBROKEN
;
913 static int send_rdsock_cmd(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
914 __u32 cmd
, char *data
, __u32 datalen
)
916 __u32 be_cmd
= htonl(cmd
);
917 __u32 be_datalen
= htonl(datalen
);
919 if (unlikely(nr
->type
!= RESUME_TYPE_NONE
))
922 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
923 nr
->type
= RESUME_TYPE_WRITE
;
924 nr
->data
.write
.fd
= fd
;
926 if (sizeof(nr
->data
.write
.buf
) != WRITE_BUF_SIZE
)
929 if (unlikely(datalen
+ 8 < datalen
|| WRITE_BUF_SIZE
< (datalen
+ 8)))
932 memcpy(&(nr
->data
.write
.buf
[0]), (char *) &be_cmd
, 4);
933 memcpy(&(nr
->data
.write
.buf
[4]), (char *) &be_datalen
, 4);
934 memcpy(&(nr
->data
.write
.buf
[8]), data
, datalen
);
935 nr
->data
.write
.len
= datalen
+ 9;
937 return resume_send(fd
, nr
);
940 int send_rdsock_connecterror_nonblock(int fd
,
941 struct libcor_nonblock_resumeinfo
*nr
,
942 __u64 cookie
, __u32 error
)
946 error
= htonl(error
);
948 memcpy(&(data
[0]), (char *) &cookie
, 8);
949 memcpy(&(data
[8]), (char *) &error
, 4);
951 return send_rdsock_cmd(fd
, nr
, CRD_UTK_CONNECTERROR
, &(data
[0]), 12);
954 int send_rdsock_connecterror(int fd
, __u64 cookie
, __u32 error
)
956 int rc
= RC_WOULDBLOCK
;
957 struct libcor_nonblock_resumeinfo nr
;
958 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
960 rc
= send_rdsock_connecterror_nonblock(fd
, &nr
, cookie
, error
);
961 if (unlikely(rc
== RC_WOULDBLOCK
)) {
963 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
968 int send_rdsock_up_nonblock(int fd
, struct libcor_nonblock_resumeinfo
*nr
,
969 char *addr
, __u32 addrlen
)
977 if (addr
== 0 && addrlen
!= 0)
978 return RC_CONNBROKEN
;
981 return RC_CONNBROKEN
;
983 flags
= htonll(flags
);
984 addrlenbe
= htonl(addrlen
);
986 memcpy(&(data
[0]), (char *) &flags
, 8);
987 memcpy(&(data
[8]), (char *) &addrlenbe
, 4);
989 memcpy(&(data
[12]), addr
, addrlen
);
991 return send_rdsock_cmd(fd
, nr
, CRD_UTK_UP
, &(data
[0]), 12 + addrlen
);
994 int send_rdsock_up(int fd
, char *addr
, __u32 addrlen
)
996 int rc
= RC_WOULDBLOCK
;
997 struct libcor_nonblock_resumeinfo nr
;
998 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1000 rc
= send_rdsock_up_nonblock(fd
, &nr
, addr
, addrlen
);
1001 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1002 LIBCOR_ASSERT_ERR();
1003 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);
1008 int parse_rdsock_connect(void *ptr
, struct rdsock_cmd
*cmd
,
1009 int (*proc_connect
)(void *ptr
, __u64 cookie
,
1010 struct cor_sockaddr
*addr
))
1013 struct cor_sockaddr addr
;
1015 memcpy((char *) &cookie
, cmd
->cmddata
, 8);
1017 if ((sizeof(struct cor_sockaddr
) + 8) > cmd
->cmddatalen
)
1020 memcpy((char *) &addr
, cmd
->cmddata
+ 8, sizeof(struct cor_sockaddr
));
1022 return proc_connect(ptr
, cookie
, &addr
);
1025 int read_rdsock_cmd_nonblock(int fd
,
1026 struct libcor_nonblock_resumeinfo
*nr
,
1027 struct rdsock_cmd
*cmd
)
1031 struct libcor_nonblock_resumeinfo_rdsockcmd
*nr_rd
=
1032 &(nr
->data
.read
.funcdata
.rdsock_cmd
);
1034 bzero(cmd
, sizeof(struct rdsock_cmd
));
1036 if (nr
->type
== RESUME_TYPE_NONE
) {
1037 bzero(nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1038 nr
->type
= RESUME_TYPE_READ
;
1039 nr
->data
.read
.functype
= RESUME_READ_FUNC_RDSOCK_CMD
;
1041 } else if (unlikely(nr
->type
!= RESUME_TYPE_READ
||
1042 nr
->data
.read
.functype
!= RESUME_READ_FUNC_RDSOCK_CMD
)){
1043 LIBCOR_ASSERT_ERR();
1044 } else if (unlikely(nr_rd
->fd
!= fd
)) {
1045 LIBCOR_ASSERT_ERR();
1047 __u8 state
= nr_rd
->state
;
1051 } else if (state
== 2) {
1053 } else if (unlikely(state
!= 0)) {
1054 LIBCOR_ASSERT_ERR();
1058 if (sizeof(nr_rd
->buf
) != 8)
1059 LIBCOR_ASSERT_ERR();
1061 rc
= read_fully(fd
, nr
, (char *) &(nr_rd
->buf
[0]), 8, 0);
1063 return bzero_nr_iffinished(nr
, rc
);
1065 ((char *) &(nr_rd
->cmd
))[0] = nr_rd
->buf
[0];
1066 ((char *) &(nr_rd
->cmd
))[1] = nr_rd
->buf
[1];
1067 ((char *) &(nr_rd
->cmd
))[2] = nr_rd
->buf
[2];
1068 ((char *) &(nr_rd
->cmd
))[3] = nr_rd
->buf
[3];
1069 ((char *) &(nr_rd
->cmddatalen
))[0] = nr_rd
->buf
[4];
1070 ((char *) &(nr_rd
->cmddatalen
))[1] = nr_rd
->buf
[5];
1071 ((char *) &(nr_rd
->cmddatalen
))[2] = nr_rd
->buf
[6];
1072 ((char *) &(nr_rd
->cmddatalen
))[3] = nr_rd
->buf
[7];
1074 nr_rd
->cmd
= ntohl(nr_rd
->cmd
);
1075 nr_rd
->cmddatalen
= ntohl(nr_rd
->cmddatalen
);
1077 if (nr_rd
->cmddatalen
> 65536)
1080 nr_rd
->cmddata
= malloc(nr_rd
->cmddatalen
);
1081 if (nr_rd
->cmddata
== 0)
1086 rc
= read_fully(fd
, nr
, nr_rd
->cmddata
, nr_rd
->cmddatalen
, 0);
1088 if (rc
!= RC_WOULDBLOCK
) {
1089 free(nr_rd
->cmddata
);
1092 return bzero_nr_iffinished(nr
, rc
);
1095 cmd
->cmd
= nr_rd
->cmd
;
1096 cmd
->cmddata
= nr_rd
->cmddata
;
1097 cmd
->cmddatalen
= nr_rd
->cmddatalen
;
1103 rc
= read_discard(fd
, nr
, nr_rd
->cmddatalen
);
1105 return bzero_nr_iffinished(nr
, rc
);
1107 return bzero_nr_iffinished(nr
, rc
);
1110 int read_rdsock_cmd(int fd
, struct rdsock_cmd
*cmd
)
1112 int rc
= RC_WOULDBLOCK
;
1113 struct libcor_nonblock_resumeinfo nr
;
1114 bzero(&nr
, sizeof(struct libcor_nonblock_resumeinfo
));
1116 rc
= read_rdsock_cmd_nonblock(fd
, &nr
, cmd
);
1117 if (unlikely(rc
== RC_WOULDBLOCK
)) {
1118 LIBCOR_ASSERT_ERR();
1119 return bzero_nr_iffinished(&nr
, RC_CONNBROKEN
);