version 1.18, 2015/05/18 15:09:59
|
version 1.18.2.2, 2015/06/29 22:29:25
|
Line 156 rpc_Read(int sock, int type, int flags, sockaddr_t * _
|
Line 156 rpc_Read(int sock, int type, int flags, sockaddr_t * _
|
struct pollfd pfd; |
struct pollfd pfd; |
sockaddr_t sa2; |
sockaddr_t sa2; |
socklen_t salen; |
socklen_t salen; |
int ret = 0, len, hlen, cx = 0; | int ret = 0, hlen, cx = 0; |
ait_val_t v = AIT_VAL_INIT; | |
struct ether_header *eh; |
struct ether_header *eh; |
struct bpf_hdr *h; |
struct bpf_hdr *h; |
ether_addr_t bcst = {{ [0 ... sizeof bcst - 1] = 0xff }}; |
ether_addr_t bcst = {{ [0 ... sizeof bcst - 1] = 0xff }}; |
u_char *buf = AIT_GET_BUF(pkt); |
u_char *buf = AIT_GET_BUF(pkt); |
size_t blen = AIT_LEN(pkt); |
size_t blen = AIT_LEN(pkt); |
struct tagRPCCall *rpc = (struct tagRPCCall *) buf; |
struct tagRPCCall *rpc = (struct tagRPCCall *) buf; |
|
ait_val_t v = AIT_VAL_INIT; |
|
|
if (type == SOCK_BPF && sa) { | try2read: |
AIT_SET_BUF(&v, NULL, blen); | |
h = (struct bpf_hdr*) AIT_GET_BUF(&v); | |
} | |
| |
pfd.fd = sock; |
pfd.fd = sock; |
pfd.events = POLLIN | POLLPRI; |
pfd.events = POLLIN | POLLPRI; |
memset(buf, 0, blen); |
memset(buf, 0, blen); |
memset(&sa2, 0, sizeof sa2); |
memset(&sa2, 0, sizeof sa2); |
salen = sa2.ss.ss_len = sizeof(sockaddr_t); |
salen = sa2.ss.ss_len = sizeof(sockaddr_t); |
|
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || |
|
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { |
|
if (ret) |
|
LOGERR; |
|
else |
|
rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond"); |
|
return -1; |
|
} |
|
|
for (len = blen; len > 0; len -= ret, buf += ret) { | switch (type) { |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | case SOCK_STREAM: |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | ret = recv(sock, buf, blen, flags); |
if (ret) | break; |
LOGERR; | case SOCK_EXT: |
else | ret = read(sock, buf, blen); |
rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond"); | break; |
if (type == SOCK_BPF) | case SOCK_BPF: |
AIT_FREE_VAL(&v); | if (!sa) { |
return -1; | rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
} | return -1; |
if (type == SOCK_STREAM) | } |
ret = recv(sock, buf, len, flags); | |
else if (type == SOCK_EXT) | AIT_SET_BUF(&v, NULL, blen); |
ret = read(sock, buf, len); | h = (struct bpf_hdr*) AIT_GET_BUF(&v); |
else if (type == SOCK_BPF && sa) { | |
ret = read(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
ret = read(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
if (ret > 0) { |
if (ret > 0) { |
ret -= h->bh_hdrlen; |
ret -= h->bh_hdrlen; |
if (ret < h->bh_caplen || h->bh_caplen != h->bh_datalen || |
if (ret < h->bh_caplen || h->bh_caplen != h->bh_datalen || |
ret < ETHER_HDR_LEN + sizeof(struct tagRPCCall)) { |
ret < ETHER_HDR_LEN + sizeof(struct tagRPCCall)) { |
|
AIT_FREE_VAL(&v); |
if (cx < 3) { |
if (cx < 3) { |
cx++; |
cx++; |
ret ^= ret; |
ret ^= ret; |
continue; /* wait for known address */ | goto try2read; /* wait for known address */ |
} else { | } else |
AIT_FREE_VAL(&v); | |
return -1; |
return -1; |
} |
|
} |
} |
ret = h->bh_caplen; |
ret = h->bh_caplen; |
eh = (struct ether_header*) (AIT_GET_BUF(&v) + h->bh_hdrlen); |
eh = (struct ether_header*) (AIT_GET_BUF(&v) + h->bh_hdrlen); |
ret -= ETHER_HDR_LEN; |
ret -= ETHER_HDR_LEN; |
if (eh->ether_type != ntohs(RPC_DEFPORT)) { |
if (eh->ether_type != ntohs(RPC_DEFPORT)) { |
|
AIT_FREE_VAL(&v); |
if (cx < 3) { |
if (cx < 3) { |
cx++; |
cx++; |
ret ^= ret; |
ret ^= ret; |
continue; /* wait for known address */ | goto try2read; /* wait for known address */ |
} else { | } else |
AIT_FREE_VAL(&v); | |
return -1; |
return -1; |
} |
|
} |
} |
|
|
if (!memcmp(bcst.octet, eh->ether_dhost, sizeof bcst) || |
if (!memcmp(bcst.octet, eh->ether_dhost, sizeof bcst) || |
!memcmp(bcst.octet, eh->ether_shost, sizeof bcst)) { |
!memcmp(bcst.octet, eh->ether_shost, sizeof bcst)) { |
|
AIT_FREE_VAL(&v); |
if (cx < 3) { |
if (cx < 3) { |
cx++; |
cx++; |
ret ^= ret; |
ret ^= ret; |
continue; /* wait for known address */ | goto try2read; /* wait for known address */ |
} else { | } else |
AIT_FREE_VAL(&v); | |
return -1; |
return -1; |
} |
|
} |
} |
memcpy(buf, (u_char*) (eh + 1), MIN(ret, len)); | memcpy(buf, (u_char*) (eh + 1), MIN(ret, blen)); |
AIT_FREE_VAL(&v); |
AIT_FREE_VAL(&v); |
return ret; |
|
} |
} |
} else { | break; |
ret = recvfrom(sock, buf, len, flags, &sa2.sa, &salen); | case SOCK_RAW: |
if (ret > -1 && sa && e_addrcmp(sa, &sa2, 42)) { | case SOCK_DGRAM: |
| if (!sa) { |
| rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| return -1; |
| } |
| |
| ret = recvfrom(sock, buf, blen, flags, &sa2.sa, &salen); |
| if (ret > -1 && e_addrcmp(sa, &sa2, 42)) { |
if (cx < 3) { |
if (cx < 3) { |
cx++; |
cx++; |
ret ^= ret; |
ret ^= ret; |
continue; /* wait for known address */ | goto try2read; /* wait for known address */ |
} else |
} else |
return -1; |
return -1; |
} |
} |
} | break; |
if (ret < 0) { | default: |
LOGERR; | rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
if (type == SOCK_BPF) | |
AIT_FREE_VAL(&v); | |
return -1; |
return -1; |
} | } |
if (!ret) { /* EOF */ | if (ret < 0) { |
if (type == SOCK_BPF) | LOGERR; |
AIT_FREE_VAL(&v); | return -1; |
return 0; | } |
} | if (!ret) /* EOF */ |
| return 0; |
|
|
/* check RPC packet header */ | /* check RPC packet header */ |
if ((u_char*) rpc == buf) { | if (type == SOCK_RAW) { |
if (type == SOCK_RAW) { | hlen = sa->sa.sa_family == AF_INET ? |
hlen = sa->sa.sa_family == AF_INET ? sizeof(struct ip) : sizeof(struct ip6_hdr); | sizeof(struct ip) : sizeof(struct ip6_hdr); |
ret -= hlen; | ret -= hlen; |
if (ret > 0) | if (ret > 0) |
memmove(buf, buf + hlen, blen - hlen); | memmove(buf, buf + hlen, blen - hlen); |
} | } |
|
|
/* 1st read for RPC header */ | /* 1st read for RPC header */ |
if (ret < sizeof(struct tagRPCCall)) { | if (ret < sizeof(struct tagRPCCall) || ret < ntohl(rpc->call_len)) { |
rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret); | rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret); |
if (type == SOCK_BPF) | return -1; |
AIT_FREE_VAL(&v); | } |
return -1; | /* check for loop request */ |
} | if (!(rpc->call_io & RPC_ACK)) { |
/* check for loop request */ | if (cx < 3) { |
if (!(rpc->call_io & RPC_ACK)) { | cx++; |
ret ^= ret; | ret ^= ret; |
continue; | goto try2read; /* wait for known address */ |
} | } else { |
/* calc estimated length */ | rpc_SetErr(ERPCMISMATCH, "Loop in RPC communication"); |
blen = len = ntohl(rpc->call_len); | return -1; |
if (blen > AIT_LEN(pkt)) { | |
AIT_RE_BUF(pkt, blen); | |
buf = AIT_GET_BUF(pkt); | |
rpc = (struct tagRPCCall*) buf; | |
} | |
} |
} |
} |
} |
ret = blen - len; |
|
|
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return ret; |
return ret; |
} |
} |
|
|
Line 311 rpc_Write(int sock, int type, int flags, sockaddr_t *
|
Line 309 rpc_Write(int sock, int type, int flags, sockaddr_t *
|
ait_val_t * __restrict pkt, size_t blen) |
ait_val_t * __restrict pkt, size_t blen) |
{ |
{ |
struct pollfd pfd; |
struct pollfd pfd; |
int ret = 0, len = 0; | int ret = 0; |
| u_char *buf = AIT_GET_BUF(pkt); |
ait_val_t v = AIT_VAL_INIT; |
ait_val_t v = AIT_VAL_INIT; |
struct ether_header *eh; |
struct ether_header *eh; |
u_char *buf = AIT_GET_BUF(pkt); |
|
|
|
if (type == SOCK_BPF && sa) { |
|
AIT_SET_BUF(&v, NULL, blen + sizeof(struct ether_header)); |
|
eh = (struct ether_header*) AIT_GET_BUF(&v); |
|
memcpy(eh->ether_dhost, LLADDR(&sa->sdl), ETHER_ADDR_LEN); |
|
eh->ether_type = htons(RPC_DEFPORT); |
|
memcpy(eh + 1, buf, blen); |
|
blen += sizeof(struct ether_header); |
|
} |
|
|
|
pfd.fd = sock; |
pfd.fd = sock; |
pfd.events = POLLOUT; |
pfd.events = POLLOUT; |
for (len = blen; len > 0; len -= ret, buf += ret) { | if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | if (ret > 0) |
#if 0 | rpc_SetErr(EPIPE, "Disconnected RPC session\n"); |
if (!ret) | else |
continue; | LOGERR; |
#endif | return -1; |
if (ret > 0) | } |
rpc_SetErr(EPIPE, "Disconnected RPC session\n"); | |
else | switch (type) { |
LOGERR; | case SOCK_STREAM: |
if (type == SOCK_BPF) | ret = send(sock, buf, blen, flags); |
AIT_FREE_VAL(&v); | break; |
return -1; | case SOCK_EXT: |
} | ret = write(sock, buf, blen); |
if (type == SOCK_STREAM) | break; |
ret = send(sock, buf, len, flags); | case SOCK_BPF: |
else if (type == SOCK_EXT) | if (!sa) { |
ret = write(sock, buf, len); | rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
else if (type == SOCK_BPF && sa) { | return -1; |
| } |
| |
| AIT_SET_BUF(&v, NULL, blen + sizeof(struct ether_header)); |
| eh = (struct ether_header*) AIT_GET_BUF(&v); |
| memcpy(eh->ether_dhost, LLADDR(&sa->sdl), ETHER_ADDR_LEN); |
| eh->ether_type = htons(RPC_DEFPORT); |
| memcpy(eh + 1, buf, blen); |
| blen += sizeof(struct ether_header); |
| |
ret = write(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
ret = write(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
} else if (sa) | |
ret = sendto(sock, buf, len, flags, &sa->sa, sa->sa.sa_len); | AIT_FREE_VAL(&v); |
else { | break; |
| case SOCK_RAW: |
| case SOCK_DGRAM: |
| if (!sa) { |
| rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| return -1; |
| } |
| |
| ret = sendto(sock, buf, blen, flags, &sa->sa, sa->sa.sa_len); |
| break; |
| default: |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return -1; |
return -1; |
} |
|
if (ret < 0) { |
|
LOGERR; |
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return -1; |
|
} |
|
if (!ret) { /* EOF */ |
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return 0; |
|
} |
|
} |
} |
ret = blen - len; | if (ret < 0) { |
| LOGERR; |
| return -1; |
| } |
| if (!ret) /* EOF */ |
| return 0; |
| |
if (ret != blen) { |
if (ret != blen) { |
rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, " |
rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, " |
"really sended %d bytes", blen, ret); |
"really sended %d bytes", blen, ret); |
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return -1; |
return -1; |
} |
} |
|
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
|
return ret; |
return ret; |
|
} |
|
|
|
/* |
|
* rpc_pktFreeSpace() - Get free space for payload into RPC packet |
|
* |
|
* @c = RPC client |
|
* return: remains free bytes from packet |
|
*/ |
|
size_t |
|
rpc_pktFreeSpace(rpc_cli_t * __restrict c) |
|
{ |
|
return (sizeof(struct tagRPCCall) + ait_resideVars(RPC_RETVARS(c))); |
} |
} |