int decode_tcp_nfs_half(struct tuple4 *addr, struct half_stream *hs) { u_char *p, *buf; int i, len, discard; u_int32_t fraghdr; buf = hs->data; len = hs->count - hs->offset; discard = 0; for (p = buf; p + 4 < buf + len; ) { fraghdr = pntohl(p); p += 4 + FRAGLEN(fraghdr); if (p > buf + len) return (0); if (LASTFRAG(fraghdr)) { i = p - buf; decode_nfs(addr, buf, i); buf += i; len -= i; discard += i; } } return (discard); }
int rpc_decode(u_char *buf, int len, struct rpc_msg *msg) { XDR xdrs; u_int32_t fraghdr; u_char *p, *tmp; int stat, tmplen; if (len < 20) return (0); p = buf + 4; /* If not recognizably RPC, try TCP record defragmentation */ if (pntohl(p) != CALL && pntohl(p) != REPLY) { tmp = buf; tmplen = 0; for (;;) { fraghdr = pntohl(tmp); if (FRAGLEN(fraghdr) + 4 > len) return (0); len -= 4; memmove(tmp, tmp + 4, len); tmplen += FRAGLEN(fraghdr); if (LASTFRAG(fraghdr)) break; tmp += FRAGLEN(fraghdr); len -= FRAGLEN(fraghdr); if (len < 4) return (0); } len = tmplen; } /* Decode RPC message. */ memset(msg, 0, sizeof(*msg)); if (ntohl(((struct rpc_msg *)buf)->rm_direction) == CALL) { xdrmem_create(&xdrs, buf, len, XDR_DECODE); if (!xdr_callmsg(&xdrs, msg)) { xdr_destroy(&xdrs); return (0); } } else if (ntohl(((struct rpc_msg *)buf)->rm_direction) == REPLY) { msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; xdrmem_create(&xdrs, buf, len, XDR_DECODE); if (!xdr_replymsg(&xdrs, msg)) { xdr_destroy(&xdrs); return (0); } } stat = xdr_getpos(&xdrs); xdr_destroy(&xdrs); return (stat); }