hast_proto.c revision 229509
12886Sphk/*- 22886Sphk * Copyright (c) 2009-2010 The FreeBSD Foundation 32926Sphk * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 42926Sphk * All rights reserved. 53833Sphk * 65014Sphk * This software was developed by Pawel Jakub Dawidek under sponsorship from 72926Sphk * the FreeBSD Foundation. 82886Sphk * 92886Sphk * Redistribution and use in source and binary forms, with or without 103833Sphk * modification, are permitted provided that the following conditions 113833Sphk * are met: 122886Sphk * 1. Redistributions of source code must retain the above copyright 132886Sphk * notice, this list of conditions and the following disclaimer. 142886Sphk * 2. Redistributions in binary form must reproduce the above copyright 152886Sphk * notice, this list of conditions and the following disclaimer in the 162886Sphk * documentation and/or other materials provided with the distribution. 172886Sphk * 182886Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 192886Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202886Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212886Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 222886Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 232886Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 242886Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 252886Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 262886Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 272886Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 282886Sphk * SUCH DAMAGE. 295014Sphk */ 305014Sphk 315014Sphk#include <sys/cdefs.h> 325014Sphk__FBSDID("$FreeBSD: stable/9/sbin/hastd/hast_proto.c 229509 2012-01-04 17:22:10Z trociny $"); 332886Sphk 342886Sphk#include <sys/endian.h> 355014Sphk 365014Sphk#include <errno.h> 375014Sphk#include <strings.h> 385014Sphk 395014Sphk#include <hast.h> 405014Sphk#include <ebuf.h> 415014Sphk#include <nv.h> 425014Sphk#include <pjdlog.h> 435014Sphk#include <proto.h> 445014Sphk 455014Sphk#ifdef HAVE_CRYPTO 465014Sphk#include "hast_checksum.h" 472886Sphk#endif 482886Sphk#include "hast_compression.h" 492886Sphk#include "hast_proto.h" 502886Sphk 512886Sphkstruct hast_main_header { 522886Sphk /* Protocol version. */ 532886Sphk uint8_t version; 542886Sphk /* Size of nv headers. */ 552886Sphk uint32_t size; 562886Sphk} __packed; 572886Sphk 582886Sphktypedef int hps_send_t(const struct hast_resource *, struct nv *nv, void **, 592886Sphk size_t *, bool *); 602886Sphktypedef int hps_recv_t(const struct hast_resource *, struct nv *nv, void **, 612886Sphk size_t *, bool *); 622886Sphk 632886Sphkstruct hast_pipe_stage { 642886Sphk const char *hps_name; 652886Sphk hps_send_t *hps_send; 662886Sphk hps_recv_t *hps_recv; 672886Sphk}; 682886Sphk 692886Sphkstatic struct hast_pipe_stage pipeline[] = { 702886Sphk { "compression", compression_send, compression_recv }, 712886Sphk#ifdef HAVE_CRYPTO 722886Sphk { "checksum", checksum_send, checksum_recv } 732886Sphk#endif 742886Sphk}; 752886Sphk 762886Sphk/* 772886Sphk * Send the given nv structure via conn. 782886Sphk * We keep headers in nv structure and pass data in separate argument. 792886Sphk * There can be no data at all (data is NULL then). 802886Sphk */ 812886Sphkint 822886Sphkhast_proto_send(const struct hast_resource *res, struct proto_conn *conn, 832886Sphk struct nv *nv, const void *data, size_t size) 842886Sphk{ 852886Sphk struct hast_main_header hdr; 862886Sphk struct ebuf *eb; 872886Sphk bool freedata; 882886Sphk void *dptr, *hptr; 892886Sphk size_t hsize; 902886Sphk int ret; 912886Sphk 922886Sphk dptr = (void *)(uintptr_t)data; 932886Sphk freedata = false; 942948Sphk ret = -1; 952971Sphk 962926Sphk if (data != NULL) { 972926Sphk unsigned int ii; 983112Sphk 992971Sphk for (ii = 0; ii < sizeof(pipeline) / sizeof(pipeline[0]); 1002926Sphk ii++) { 1012926Sphk (void)pipeline[ii].hps_send(res, nv, &dptr, &size, 1022926Sphk &freedata); 1032926Sphk } 1042926Sphk nv_add_uint32(nv, size, "size"); 1052926Sphk if (nv_error(nv) != 0) { 1062886Sphk errno = nv_error(nv); 1072926Sphk goto end; 1082926Sphk } 1092886Sphk } 1102926Sphk 1112886Sphk eb = nv_hton(nv); 1122886Sphk if (eb == NULL) 1132926Sphk goto end; 1142886Sphk 1152886Sphk hdr.version = HAST_PROTO_VERSION; 1162886Sphk hdr.size = htole32((uint32_t)ebuf_size(eb)); 1172886Sphk if (ebuf_add_head(eb, &hdr, sizeof(hdr)) < 0) 1182886Sphk goto end; 1192886Sphk 1202886Sphk hptr = ebuf_data(eb, &hsize); 1212886Sphk if (proto_send(conn, hptr, hsize) < 0) 1222886Sphk goto end; 1232886Sphk if (data != NULL && proto_send(conn, dptr, size) < 0) 1242886Sphk goto end; 1252886Sphk 1262886Sphk ret = 0; 1272886Sphkend: 1282886Sphk if (freedata) 1292886Sphk free(dptr); 1303833Sphk return (ret); 1313833Sphk} 1323833Sphk 1335014Sphkint 1342886Sphkhast_proto_recv_hdr(const struct proto_conn *conn, struct nv **nvp) 1352886Sphk{ 1362926Sphk struct hast_main_header hdr; 1372926Sphk struct nv *nv; 1382926Sphk struct ebuf *eb; 1392926Sphk void *hptr; 1402926Sphk 1412886Sphk eb = NULL; 1422886Sphk nv = NULL; 1432886Sphk 1442886Sphk if (proto_recv(conn, &hdr, sizeof(hdr)) < 0) 1455014Sphk goto fail; 1465014Sphk 1475014Sphk if (hdr.version != HAST_PROTO_VERSION) { 1485014Sphk errno = ERPCMISMATCH; 1495014Sphk goto fail; 1505014Sphk } 1515014Sphk 1525014Sphk hdr.size = le32toh(hdr.size); 1535014Sphk 1545014Sphk eb = ebuf_alloc(hdr.size); 1555014Sphk if (eb == NULL) 1565014Sphk goto fail; 1575014Sphk if (ebuf_add_tail(eb, NULL, hdr.size) < 0) 1585014Sphk goto fail; 1595014Sphk hptr = ebuf_data(eb, NULL); 1605014Sphk PJDLOG_ASSERT(hptr != NULL); 1615014Sphk if (proto_recv(conn, hptr, hdr.size) < 0) 1625014Sphk goto fail; 1635014Sphk nv = nv_ntoh(eb); 1645014Sphk if (nv == NULL) 1655014Sphk goto fail; 1665014Sphk 1675014Sphk *nvp = nv; 1685014Sphk return (0); 1695014Sphkfail: 1705014Sphk if (eb != NULL) 1715014Sphk ebuf_free(eb); 1725014Sphk return (-1); 1735014Sphk} 1742886Sphk 1752886Sphkint 1762886Sphkhast_proto_recv_data(const struct hast_resource *res, struct proto_conn *conn, 1772886Sphk struct nv *nv, void *data, size_t size) 1782886Sphk{ 1792886Sphk unsigned int ii; 1802886Sphk bool freedata; 1812886Sphk size_t dsize; 1822886Sphk void *dptr; 1832886Sphk int ret; 1842886Sphk 1852926Sphk PJDLOG_ASSERT(data != NULL); 1862886Sphk PJDLOG_ASSERT(size > 0); 1872886Sphk 1882886Sphk ret = -1; 1892886Sphk freedata = false; 1903112Sphk dptr = data; 1912886Sphk 1922886Sphk dsize = nv_get_uint32(nv, "size"); 1933112Sphk if (dsize > size) { 1943833Sphk errno = EINVAL; 1952886Sphk goto end; 1963112Sphk } else if (dsize == 0) { 1973833Sphk (void)nv_set_error(nv, 0); 1983112Sphk } else { 1993112Sphk if (proto_recv(conn, data, dsize) < 0) 2003112Sphk goto end; 2012926Sphk for (ii = sizeof(pipeline) / sizeof(pipeline[0]); ii > 0; 2023833Sphk ii--) { 2032926Sphk ret = pipeline[ii - 1].hps_recv(res, nv, &dptr, 2043833Sphk &dsize, &freedata); 2053833Sphk if (ret == -1) 2065014Sphk goto end; 2075014Sphk } 2085014Sphk ret = -1; 2095014Sphk if (dsize > size) { 210 errno = EINVAL; 211 goto end; 212 } 213 if (dptr != data) 214 bcopy(dptr, data, dsize); 215 } 216 217 ret = 0; 218end: 219 if (freedata) 220 free(dptr); 221 return (ret); 222} 223