Diff for /libaitrpc/src/aitrpc.c between versions 1.18 and 1.20

version 1.18, 2015/05/18 15:09:59 version 1.20, 2015/07/22 20:01:46
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 156  rpc_Read(int sock, int type, int flags, sockaddr_t * _ Line 137  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 = (u_char) MIN(sizeof(sockaddr_t), 0xff);
         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 290  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)));
 }  }

Removed from v.1.18  
changed lines
  Added in v.1.20


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>