|
version 1.10, 2013/05/30 09:22:01
|
version 1.22, 2024/03/20 17:32:30
|
|
Line 12 terms:
|
Line 12 terms:
|
| All of the documentation and software included in the ELWIX and AITNET |
All of the documentation and software included in the ELWIX and AITNET |
| Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
| |
|
| Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 | Copyright 2004 - 2024 |
| by Michael Pounov <misho@elwix.org>. All rights reserved. |
by Michael Pounov <misho@elwix.org>. All rights reserved. |
| |
|
| Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
|
Line 51 SUCH DAMAGE.
|
Line 51 SUCH DAMAGE.
|
| int rpc_Errno; |
int rpc_Errno; |
| char rpc_Error[STRSIZ]; |
char rpc_Error[STRSIZ]; |
| |
|
| inline int |
|
| rpc_funcs_cmp(struct tagRPCFunc *a, struct tagRPCFunc *b) |
|
| { |
|
| int ret; |
|
| |
|
| assert(a && b); |
|
| |
|
| ret = AIT_KEY(&a->func_name) - AIT_KEY(&b->func_name); |
|
| |
|
| if (ret < 0) |
|
| return -1; |
|
| else if (ret > 0) |
|
| return 1; |
|
| |
|
| return ret; |
|
| } |
|
| |
|
| AVL_GENERATE(tagRPCFuncs, tagRPCFunc, func_node, rpc_funcs_cmp); |
|
| |
|
| #pragma GCC visibility pop |
#pragma GCC visibility pop |
| |
|
| // rpc_GetErrno() Get error code of last operation |
// rpc_GetErrno() Get error code of last operation |
|
Line 138 rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s)
|
Line 119 rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s)
|
| p->sess_instance = s->sess_instance; |
p->sess_instance = s->sess_instance; |
| |
|
| return 0; |
return 0; |
| |
} |
| |
|
| |
/* |
| |
* rpc_Read() - RPC read operation |
| |
* |
| |
* @sock = socket |
| |
* @type = type of socket |
| |
* @flags = receive flags |
| |
* @sa = check client address, if you use udp protocol |
| |
* @pkt = RPC packet |
| |
* return: -1 error, 0 EOF or or >0 readed bytes into buffer |
| |
*/ |
| |
ssize_t |
| |
rpc_Read(int sock, int type, int flags, sockaddr_t * __restrict sa, ait_val_t * __restrict pkt) |
| |
{ |
| |
struct pollfd pfd; |
| |
sockaddr_t sa2; |
| |
socklen_t salen; |
| |
int ret = 0, hlen, cx = 0; |
| |
u_char *buf = AIT_GET_BUF(pkt); |
| |
size_t blen = AIT_LEN(pkt); |
| |
struct tagRPCCall *rpc = (struct tagRPCCall *) buf; |
| |
#ifndef __linux__ |
| |
struct ether_header *eh; |
| |
struct bpf_hdr *h; |
| |
ait_val_t v = AIT_VAL_INIT; |
| |
#endif |
| |
|
| |
try2read: |
| |
pfd.fd = sock; |
| |
pfd.events = POLLIN | POLLPRI; |
| |
memset(buf, 0, blen); |
| |
memset(&sa2, 0, sizeof sa2); |
| |
salen = E_SOCKADDR_MAX; |
| |
#ifndef __linux__ |
| |
sa2.ss.ss_len = salen; |
| |
ether_addr_t bcst = {{ [0 ... sizeof bcst - 1] = 0xff }}; |
| |
#endif |
| |
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; |
| |
} |
| |
|
| |
switch (type) { |
| |
case SOCK_STREAM: |
| |
ret = recv(sock, buf, blen, flags); |
| |
break; |
| |
case SOCK_EXT: |
| |
ret = read(sock, buf, blen); |
| |
break; |
| |
#ifndef __linux__ |
| |
case SOCK_BPF: |
| |
if (!sa) { |
| |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| |
return -1; |
| |
} |
| |
|
| |
AIT_SET_BUF(&v, NULL, blen); |
| |
h = (struct bpf_hdr*) AIT_GET_BUF(&v); |
| |
|
| |
ret = read(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
| |
if (ret > 0) { |
| |
ret -= h->bh_hdrlen; |
| |
if (ret < h->bh_caplen || h->bh_caplen != h->bh_datalen || |
| |
ret < ETHER_HDR_LEN + sizeof(struct tagRPCCall)) { |
| |
AIT_FREE_VAL(&v); |
| |
if (cx < 3) { |
| |
cx++; |
| |
ret ^= ret; |
| |
goto try2read; /* wait for known address */ |
| |
} else |
| |
return -1; |
| |
} |
| |
ret = h->bh_caplen; |
| |
eh = (struct ether_header*) (AIT_GET_BUF(&v) + h->bh_hdrlen); |
| |
ret -= ETHER_HDR_LEN; |
| |
if (eh->ether_type != ntohs(RPC_DEFPORT)) { |
| |
AIT_FREE_VAL(&v); |
| |
if (cx < 3) { |
| |
cx++; |
| |
ret ^= ret; |
| |
goto try2read; /* wait for known address */ |
| |
} else |
| |
return -1; |
| |
} |
| |
|
| |
if (!memcmp(bcst.octet, eh->ether_dhost, sizeof bcst) || |
| |
!memcmp(bcst.octet, eh->ether_shost, sizeof bcst)) { |
| |
AIT_FREE_VAL(&v); |
| |
if (cx < 3) { |
| |
cx++; |
| |
ret ^= ret; |
| |
goto try2read; /* wait for known address */ |
| |
} else |
| |
return -1; |
| |
} |
| |
memcpy(buf, (u_char*) (eh + 1), MIN(ret, blen)); |
| |
AIT_FREE_VAL(&v); |
| |
} |
| |
break; |
| |
#endif |
| |
case SOCK_RAW: |
| |
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) { |
| |
cx++; |
| |
ret ^= ret; |
| |
goto try2read; /* wait for known address */ |
| |
} else |
| |
return -1; |
| |
} |
| |
break; |
| |
default: |
| |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| |
return -1; |
| |
} |
| |
if (ret < 0) { |
| |
LOGERR; |
| |
return -1; |
| |
} |
| |
if (!ret) /* EOF */ |
| |
return 0; |
| |
|
| |
/* check RPC packet header */ |
| |
if (type == SOCK_RAW) { |
| |
#ifdef IPV6_REMOVE_HEADER |
| |
hlen = sa->sa.sa_family == AF_INET ? |
| |
sizeof(struct ip) : sizeof(struct ip6_hdr); |
| |
#else |
| |
hlen = sa->sa.sa_family == AF_INET ? |
| |
sizeof(struct ip) : 0; |
| |
#endif |
| |
ret -= hlen; |
| |
if (ret > 0) |
| |
memmove(buf, buf + hlen, blen - hlen); |
| |
} |
| |
|
| |
/* 1st read for RPC header */ |
| |
if (ret < sizeof(struct tagRPCCall) || ret < ntohl(rpc->call_len)) { |
| |
rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret); |
| |
return -1; |
| |
} |
| |
/* check for loop request */ |
| |
if (!(rpc->call_io & RPC_ACK)) { |
| |
if (cx < 3) { |
| |
cx++; |
| |
ret ^= ret; |
| |
goto try2read; /* wait for known address */ |
| |
} else { |
| |
rpc_SetErr(ERPCMISMATCH, "Loop in RPC communication"); |
| |
return -1; |
| |
} |
| |
} |
| |
|
| |
return ret; |
| |
} |
| |
|
| |
/* |
| |
* rpc_Write() - RPC write operation |
| |
* |
| |
* @sock = socket |
| |
* @type = type of socket |
| |
* @flags = send flags |
| |
* @sa = send to client address, if you use udp protocol |
| |
* @pkt = RPC packet |
| |
* @blen = buffer length |
| |
* return: -1 error, 0 EOF or >0 written bytes into buffer |
| |
*/ |
| |
ssize_t |
| |
rpc_Write(int sock, int type, int flags, sockaddr_t * __restrict sa, |
| |
ait_val_t * __restrict pkt, size_t blen) |
| |
{ |
| |
struct pollfd pfd; |
| |
int ret = 0; |
| |
u_char *buf = AIT_GET_BUF(pkt); |
| |
#ifndef __linux__ |
| |
ait_val_t v = AIT_VAL_INIT; |
| |
struct ether_header *eh; |
| |
#endif |
| |
|
| |
|
| |
pfd.fd = sock; |
| |
pfd.events = POLLOUT; |
| |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || |
| |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { |
| |
if (ret > 0) |
| |
rpc_SetErr(EPIPE, "Disconnected RPC session\n"); |
| |
else |
| |
LOGERR; |
| |
return -1; |
| |
} |
| |
|
| |
switch (type) { |
| |
case SOCK_STREAM: |
| |
ret = send(sock, buf, blen, flags); |
| |
break; |
| |
case SOCK_EXT: |
| |
ret = write(sock, buf, blen); |
| |
break; |
| |
#ifndef __linux__ |
| |
case SOCK_BPF: |
| |
if (!sa) { |
| |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| |
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)); |
| |
|
| |
AIT_FREE_VAL(&v); |
| |
break; |
| |
#endif |
| |
case SOCK_RAW: |
| |
case SOCK_DGRAM: |
| |
if (!sa) { |
| |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| |
return -1; |
| |
} |
| |
|
| |
ret = sendto(sock, buf, blen, flags, &sa->sa, e_addrlen(sa)); |
| |
break; |
| |
default: |
| |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
| |
return -1; |
| |
} |
| |
if (ret < 0) { |
| |
LOGERR; |
| |
return -1; |
| |
} |
| |
if (!ret) /* EOF */ |
| |
return 0; |
| |
|
| |
if (ret != blen) { |
| |
rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, " |
| |
"really sended %d bytes", blen, ret); |
| |
return -1; |
| |
} |
| |
|
| |
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))); |
| } |
} |