132115b10SPawel Jakub Dawidek /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 432115b10SPawel Jakub Dawidek * Copyright (c) 2009-2010 The FreeBSD Foundation 532115b10SPawel Jakub Dawidek * 632115b10SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 732115b10SPawel Jakub Dawidek * the FreeBSD Foundation. 832115b10SPawel Jakub Dawidek * 932115b10SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 1032115b10SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 1132115b10SPawel Jakub Dawidek * are met: 1232115b10SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 1332115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1432115b10SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1532115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1632115b10SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1732115b10SPawel Jakub Dawidek * 1832115b10SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1932115b10SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2032115b10SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2132115b10SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2232115b10SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2332115b10SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2432115b10SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2532115b10SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2632115b10SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2732115b10SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2832115b10SPawel Jakub Dawidek * SUCH DAMAGE. 2932115b10SPawel Jakub Dawidek */ 3032115b10SPawel Jakub Dawidek 315571414cSPawel Jakub Dawidek #include <sys/types.h> 3232115b10SPawel Jakub Dawidek #include <sys/queue.h> 335571414cSPawel Jakub Dawidek #include <sys/socket.h> 3432115b10SPawel Jakub Dawidek 3532115b10SPawel Jakub Dawidek #include <errno.h> 3632115b10SPawel Jakub Dawidek #include <stdint.h> 3701ab52c0SPawel Jakub Dawidek #include <string.h> 385ee17035SPawel Jakub Dawidek #include <strings.h> 3932115b10SPawel Jakub Dawidek 402ec483c5SPawel Jakub Dawidek #include "pjdlog.h" 4132115b10SPawel Jakub Dawidek #include "proto.h" 4232115b10SPawel Jakub Dawidek #include "proto_impl.h" 4332115b10SPawel Jakub Dawidek 4432115b10SPawel Jakub Dawidek #define PROTO_CONN_MAGIC 0x907041c 4532115b10SPawel Jakub Dawidek struct proto_conn { 4632115b10SPawel Jakub Dawidek int pc_magic; 47e2eabb44SPawel Jakub Dawidek struct proto *pc_proto; 4832115b10SPawel Jakub Dawidek void *pc_ctx; 4932115b10SPawel Jakub Dawidek int pc_side; 5032115b10SPawel Jakub Dawidek #define PROTO_SIDE_CLIENT 0 5132115b10SPawel Jakub Dawidek #define PROTO_SIDE_SERVER_LISTEN 1 5232115b10SPawel Jakub Dawidek #define PROTO_SIDE_SERVER_WORK 2 5332115b10SPawel Jakub Dawidek }; 5432115b10SPawel Jakub Dawidek 55e2eabb44SPawel Jakub Dawidek static TAILQ_HEAD(, proto) protos = TAILQ_HEAD_INITIALIZER(protos); 5632115b10SPawel Jakub Dawidek 5732115b10SPawel Jakub Dawidek void 58e2eabb44SPawel Jakub Dawidek proto_register(struct proto *proto, bool isdefault) 5932115b10SPawel Jakub Dawidek { 6050692f84SPawel Jakub Dawidek static bool seen_default = false; 6132115b10SPawel Jakub Dawidek 6250692f84SPawel Jakub Dawidek if (!isdefault) 63e2eabb44SPawel Jakub Dawidek TAILQ_INSERT_HEAD(&protos, proto, prt_next); 6450692f84SPawel Jakub Dawidek else { 652ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(!seen_default); 6650692f84SPawel Jakub Dawidek seen_default = true; 67e2eabb44SPawel Jakub Dawidek TAILQ_INSERT_TAIL(&protos, proto, prt_next); 6850692f84SPawel Jakub Dawidek } 6932115b10SPawel Jakub Dawidek } 7032115b10SPawel Jakub Dawidek 715ee17035SPawel Jakub Dawidek static struct proto_conn * 72e2eabb44SPawel Jakub Dawidek proto_alloc(struct proto *proto, int side) 735ee17035SPawel Jakub Dawidek { 745ee17035SPawel Jakub Dawidek struct proto_conn *conn; 755ee17035SPawel Jakub Dawidek 765ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(proto != NULL); 775ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || 785ee17035SPawel Jakub Dawidek side == PROTO_SIDE_SERVER_LISTEN || 795ee17035SPawel Jakub Dawidek side == PROTO_SIDE_SERVER_WORK); 805ee17035SPawel Jakub Dawidek 815ee17035SPawel Jakub Dawidek conn = malloc(sizeof(*conn)); 825ee17035SPawel Jakub Dawidek if (conn != NULL) { 835ee17035SPawel Jakub Dawidek conn->pc_proto = proto; 845ee17035SPawel Jakub Dawidek conn->pc_side = side; 855ee17035SPawel Jakub Dawidek conn->pc_magic = PROTO_CONN_MAGIC; 865ee17035SPawel Jakub Dawidek } 875ee17035SPawel Jakub Dawidek return (conn); 885ee17035SPawel Jakub Dawidek } 895ee17035SPawel Jakub Dawidek 905ee17035SPawel Jakub Dawidek static void 915ee17035SPawel Jakub Dawidek proto_free(struct proto_conn *conn) 925ee17035SPawel Jakub Dawidek { 935ee17035SPawel Jakub Dawidek 945ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 955ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 965ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT || 975ee17035SPawel Jakub Dawidek conn->pc_side == PROTO_SIDE_SERVER_LISTEN || 985ee17035SPawel Jakub Dawidek conn->pc_side == PROTO_SIDE_SERVER_WORK); 995ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 1005ee17035SPawel Jakub Dawidek 1015ee17035SPawel Jakub Dawidek bzero(conn, sizeof(*conn)); 1025ee17035SPawel Jakub Dawidek free(conn); 1035ee17035SPawel Jakub Dawidek } 1045ee17035SPawel Jakub Dawidek 10532115b10SPawel Jakub Dawidek static int 1060b626a28SPawel Jakub Dawidek proto_common_setup(const char *srcaddr, const char *dstaddr, 1070b626a28SPawel Jakub Dawidek struct proto_conn **connp, int side) 10832115b10SPawel Jakub Dawidek { 109e2eabb44SPawel Jakub Dawidek struct proto *proto; 11032115b10SPawel Jakub Dawidek struct proto_conn *conn; 11132115b10SPawel Jakub Dawidek void *ctx; 11232115b10SPawel Jakub Dawidek int ret; 11332115b10SPawel Jakub Dawidek 1145ee17035SPawel Jakub Dawidek PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || 1155ee17035SPawel Jakub Dawidek side == PROTO_SIDE_SERVER_LISTEN); 11632115b10SPawel Jakub Dawidek 117e2eabb44SPawel Jakub Dawidek TAILQ_FOREACH(proto, &protos, prt_next) { 1188dd94e23SPawel Jakub Dawidek if (side == PROTO_SIDE_CLIENT) { 119e2eabb44SPawel Jakub Dawidek if (proto->prt_client == NULL) 1208dd94e23SPawel Jakub Dawidek ret = -1; 1218dd94e23SPawel Jakub Dawidek else 122e2eabb44SPawel Jakub Dawidek ret = proto->prt_client(srcaddr, dstaddr, &ctx); 1238dd94e23SPawel Jakub Dawidek } else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ { 124e2eabb44SPawel Jakub Dawidek if (proto->prt_server == NULL) 1258dd94e23SPawel Jakub Dawidek ret = -1; 1268dd94e23SPawel Jakub Dawidek else 127e2eabb44SPawel Jakub Dawidek ret = proto->prt_server(dstaddr, &ctx); 1288dd94e23SPawel Jakub Dawidek } 12932115b10SPawel Jakub Dawidek /* 13032115b10SPawel Jakub Dawidek * ret == 0 - success 1310b626a28SPawel Jakub Dawidek * ret == -1 - dstaddr is not for this protocol 1324b85a12fSUlrich Spörlein * ret > 0 - right protocol, but an error occurred 13332115b10SPawel Jakub Dawidek */ 13432115b10SPawel Jakub Dawidek if (ret >= 0) 13532115b10SPawel Jakub Dawidek break; 13632115b10SPawel Jakub Dawidek } 13732115b10SPawel Jakub Dawidek if (proto == NULL) { 13832115b10SPawel Jakub Dawidek /* Unrecognized address. */ 13932115b10SPawel Jakub Dawidek errno = EINVAL; 14032115b10SPawel Jakub Dawidek return (-1); 14132115b10SPawel Jakub Dawidek } 14232115b10SPawel Jakub Dawidek if (ret > 0) { 1434b85a12fSUlrich Spörlein /* An error occurred. */ 14432115b10SPawel Jakub Dawidek errno = ret; 14532115b10SPawel Jakub Dawidek return (-1); 14632115b10SPawel Jakub Dawidek } 1475ee17035SPawel Jakub Dawidek conn = proto_alloc(proto, side); 1485ee17035SPawel Jakub Dawidek if (conn == NULL) { 149e2eabb44SPawel Jakub Dawidek if (proto->prt_close != NULL) 150e2eabb44SPawel Jakub Dawidek proto->prt_close(ctx); 1515ee17035SPawel Jakub Dawidek errno = ENOMEM; 1525ee17035SPawel Jakub Dawidek return (-1); 1535ee17035SPawel Jakub Dawidek } 15432115b10SPawel Jakub Dawidek conn->pc_ctx = ctx; 15532115b10SPawel Jakub Dawidek *connp = conn; 1565ee17035SPawel Jakub Dawidek 15732115b10SPawel Jakub Dawidek return (0); 15832115b10SPawel Jakub Dawidek } 15932115b10SPawel Jakub Dawidek 16032115b10SPawel Jakub Dawidek int 1610b626a28SPawel Jakub Dawidek proto_client(const char *srcaddr, const char *dstaddr, 1620b626a28SPawel Jakub Dawidek struct proto_conn **connp) 16332115b10SPawel Jakub Dawidek { 16432115b10SPawel Jakub Dawidek 1650b626a28SPawel Jakub Dawidek return (proto_common_setup(srcaddr, dstaddr, connp, PROTO_SIDE_CLIENT)); 16632115b10SPawel Jakub Dawidek } 16732115b10SPawel Jakub Dawidek 16832115b10SPawel Jakub Dawidek int 1699d70b24bSPawel Jakub Dawidek proto_connect(struct proto_conn *conn, int timeout) 17032115b10SPawel Jakub Dawidek { 17132115b10SPawel Jakub Dawidek int ret; 17232115b10SPawel Jakub Dawidek 1732ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 1742ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 1752ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT); 1762ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 177e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_connect != NULL); 1781c193322SPawel Jakub Dawidek PJDLOG_ASSERT(timeout >= -1); 17932115b10SPawel Jakub Dawidek 180e2eabb44SPawel Jakub Dawidek ret = conn->pc_proto->prt_connect(conn->pc_ctx, timeout); 18132115b10SPawel Jakub Dawidek if (ret != 0) { 18232115b10SPawel Jakub Dawidek errno = ret; 18332115b10SPawel Jakub Dawidek return (-1); 18432115b10SPawel Jakub Dawidek } 18532115b10SPawel Jakub Dawidek 18632115b10SPawel Jakub Dawidek return (0); 18732115b10SPawel Jakub Dawidek } 18832115b10SPawel Jakub Dawidek 18932115b10SPawel Jakub Dawidek int 1901c193322SPawel Jakub Dawidek proto_connect_wait(struct proto_conn *conn, int timeout) 1911c193322SPawel Jakub Dawidek { 1921c193322SPawel Jakub Dawidek int ret; 1931c193322SPawel Jakub Dawidek 1941c193322SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 1951c193322SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 1961c193322SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT); 1971c193322SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 198e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_connect_wait != NULL); 1991c193322SPawel Jakub Dawidek PJDLOG_ASSERT(timeout >= 0); 2001c193322SPawel Jakub Dawidek 201e2eabb44SPawel Jakub Dawidek ret = conn->pc_proto->prt_connect_wait(conn->pc_ctx, timeout); 2021c193322SPawel Jakub Dawidek if (ret != 0) { 2031c193322SPawel Jakub Dawidek errno = ret; 2041c193322SPawel Jakub Dawidek return (-1); 2051c193322SPawel Jakub Dawidek } 2061c193322SPawel Jakub Dawidek 2071c193322SPawel Jakub Dawidek return (0); 2081c193322SPawel Jakub Dawidek } 2091c193322SPawel Jakub Dawidek 2101c193322SPawel Jakub Dawidek int 21132115b10SPawel Jakub Dawidek proto_server(const char *addr, struct proto_conn **connp) 21232115b10SPawel Jakub Dawidek { 21332115b10SPawel Jakub Dawidek 2140b626a28SPawel Jakub Dawidek return (proto_common_setup(NULL, addr, connp, PROTO_SIDE_SERVER_LISTEN)); 21532115b10SPawel Jakub Dawidek } 21632115b10SPawel Jakub Dawidek 21732115b10SPawel Jakub Dawidek int 21832115b10SPawel Jakub Dawidek proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) 21932115b10SPawel Jakub Dawidek { 22032115b10SPawel Jakub Dawidek struct proto_conn *newconn; 22132115b10SPawel Jakub Dawidek int ret; 22232115b10SPawel Jakub Dawidek 2232ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 2242ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 2252ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); 2262ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 227e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_accept != NULL); 22832115b10SPawel Jakub Dawidek 2295ee17035SPawel Jakub Dawidek newconn = proto_alloc(conn->pc_proto, PROTO_SIDE_SERVER_WORK); 23032115b10SPawel Jakub Dawidek if (newconn == NULL) 23132115b10SPawel Jakub Dawidek return (-1); 23232115b10SPawel Jakub Dawidek 233e2eabb44SPawel Jakub Dawidek ret = conn->pc_proto->prt_accept(conn->pc_ctx, &newconn->pc_ctx); 23432115b10SPawel Jakub Dawidek if (ret != 0) { 2355ee17035SPawel Jakub Dawidek proto_free(newconn); 23632115b10SPawel Jakub Dawidek errno = ret; 23732115b10SPawel Jakub Dawidek return (-1); 23832115b10SPawel Jakub Dawidek } 23932115b10SPawel Jakub Dawidek 24032115b10SPawel Jakub Dawidek *newconnp = newconn; 24132115b10SPawel Jakub Dawidek 24232115b10SPawel Jakub Dawidek return (0); 24332115b10SPawel Jakub Dawidek } 24432115b10SPawel Jakub Dawidek 24532115b10SPawel Jakub Dawidek int 246b938cdccSPawel Jakub Dawidek proto_send(const struct proto_conn *conn, const void *data, size_t size) 24732115b10SPawel Jakub Dawidek { 24832115b10SPawel Jakub Dawidek int ret; 24932115b10SPawel Jakub Dawidek 2502ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 2512ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 2522ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 253e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); 25432115b10SPawel Jakub Dawidek 255e2eabb44SPawel Jakub Dawidek ret = conn->pc_proto->prt_send(conn->pc_ctx, data, size, -1); 25632115b10SPawel Jakub Dawidek if (ret != 0) { 25732115b10SPawel Jakub Dawidek errno = ret; 25832115b10SPawel Jakub Dawidek return (-1); 25932115b10SPawel Jakub Dawidek } 26032115b10SPawel Jakub Dawidek return (0); 26132115b10SPawel Jakub Dawidek } 26232115b10SPawel Jakub Dawidek 26332115b10SPawel Jakub Dawidek int 264b938cdccSPawel Jakub Dawidek proto_recv(const struct proto_conn *conn, void *data, size_t size) 26532115b10SPawel Jakub Dawidek { 26632115b10SPawel Jakub Dawidek int ret; 26732115b10SPawel Jakub Dawidek 2682ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 2692ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 2702ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 271e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); 27232115b10SPawel Jakub Dawidek 273e2eabb44SPawel Jakub Dawidek ret = conn->pc_proto->prt_recv(conn->pc_ctx, data, size, NULL); 27432115b10SPawel Jakub Dawidek if (ret != 0) { 27532115b10SPawel Jakub Dawidek errno = ret; 27632115b10SPawel Jakub Dawidek return (-1); 27732115b10SPawel Jakub Dawidek } 27832115b10SPawel Jakub Dawidek return (0); 27932115b10SPawel Jakub Dawidek } 28032115b10SPawel Jakub Dawidek 28132115b10SPawel Jakub Dawidek int 28201ab52c0SPawel Jakub Dawidek proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn) 2838046c499SPawel Jakub Dawidek { 28401ab52c0SPawel Jakub Dawidek const char *protoname; 28501ab52c0SPawel Jakub Dawidek int ret, fd; 2868046c499SPawel Jakub Dawidek 2878046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 2888046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 2898046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 290e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); 29101ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(mconn != NULL); 29201ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(mconn->pc_magic == PROTO_CONN_MAGIC); 29301ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(mconn->pc_proto != NULL); 29401ab52c0SPawel Jakub Dawidek fd = proto_descriptor(mconn); 29501ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 296e2eabb44SPawel Jakub Dawidek protoname = mconn->pc_proto->prt_name; 29701ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(protoname != NULL); 2988046c499SPawel Jakub Dawidek 2994d70e06fSMikolaj Golub ret = conn->pc_proto->prt_send(conn->pc_ctx, 3004d70e06fSMikolaj Golub (const unsigned char *)protoname, strlen(protoname) + 1, fd); 30101ab52c0SPawel Jakub Dawidek proto_close(mconn); 3028046c499SPawel Jakub Dawidek if (ret != 0) { 3038046c499SPawel Jakub Dawidek errno = ret; 3048046c499SPawel Jakub Dawidek return (-1); 3058046c499SPawel Jakub Dawidek } 3068046c499SPawel Jakub Dawidek return (0); 3078046c499SPawel Jakub Dawidek } 3088046c499SPawel Jakub Dawidek 3098046c499SPawel Jakub Dawidek int 31001ab52c0SPawel Jakub Dawidek proto_connection_recv(const struct proto_conn *conn, bool client, 31101ab52c0SPawel Jakub Dawidek struct proto_conn **newconnp) 3128046c499SPawel Jakub Dawidek { 31301ab52c0SPawel Jakub Dawidek char protoname[128]; 314e2eabb44SPawel Jakub Dawidek struct proto *proto; 31501ab52c0SPawel Jakub Dawidek struct proto_conn *newconn; 31601ab52c0SPawel Jakub Dawidek int ret, fd; 3178046c499SPawel Jakub Dawidek 3188046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 3198046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 3208046c499SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 321e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); 32201ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(newconnp != NULL); 3238046c499SPawel Jakub Dawidek 32401ab52c0SPawel Jakub Dawidek bzero(protoname, sizeof(protoname)); 32501ab52c0SPawel Jakub Dawidek 3264d70e06fSMikolaj Golub ret = conn->pc_proto->prt_recv(conn->pc_ctx, (unsigned char *)protoname, 32701ab52c0SPawel Jakub Dawidek sizeof(protoname) - 1, &fd); 3288046c499SPawel Jakub Dawidek if (ret != 0) { 3298046c499SPawel Jakub Dawidek errno = ret; 3308046c499SPawel Jakub Dawidek return (-1); 3318046c499SPawel Jakub Dawidek } 33201ab52c0SPawel Jakub Dawidek 33301ab52c0SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 33401ab52c0SPawel Jakub Dawidek 335e2eabb44SPawel Jakub Dawidek TAILQ_FOREACH(proto, &protos, prt_next) { 336e2eabb44SPawel Jakub Dawidek if (strcmp(proto->prt_name, protoname) == 0) 33701ab52c0SPawel Jakub Dawidek break; 33801ab52c0SPawel Jakub Dawidek } 33901ab52c0SPawel Jakub Dawidek if (proto == NULL) { 34001ab52c0SPawel Jakub Dawidek errno = EINVAL; 34101ab52c0SPawel Jakub Dawidek return (-1); 34201ab52c0SPawel Jakub Dawidek } 34301ab52c0SPawel Jakub Dawidek 34401ab52c0SPawel Jakub Dawidek newconn = proto_alloc(proto, 34501ab52c0SPawel Jakub Dawidek client ? PROTO_SIDE_CLIENT : PROTO_SIDE_SERVER_WORK); 34601ab52c0SPawel Jakub Dawidek if (newconn == NULL) 34701ab52c0SPawel Jakub Dawidek return (-1); 348e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(newconn->pc_proto->prt_wrap != NULL); 349e2eabb44SPawel Jakub Dawidek ret = newconn->pc_proto->prt_wrap(fd, client, &newconn->pc_ctx); 35001ab52c0SPawel Jakub Dawidek if (ret != 0) { 35101ab52c0SPawel Jakub Dawidek proto_free(newconn); 35201ab52c0SPawel Jakub Dawidek errno = ret; 35301ab52c0SPawel Jakub Dawidek return (-1); 35401ab52c0SPawel Jakub Dawidek } 35501ab52c0SPawel Jakub Dawidek 35601ab52c0SPawel Jakub Dawidek *newconnp = newconn; 35701ab52c0SPawel Jakub Dawidek 3588046c499SPawel Jakub Dawidek return (0); 3598046c499SPawel Jakub Dawidek } 3608046c499SPawel Jakub Dawidek 3618046c499SPawel Jakub Dawidek int 36232115b10SPawel Jakub Dawidek proto_descriptor(const struct proto_conn *conn) 36332115b10SPawel Jakub Dawidek { 36432115b10SPawel Jakub Dawidek 3652ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 3662ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 3672ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 368e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_descriptor != NULL); 36932115b10SPawel Jakub Dawidek 370e2eabb44SPawel Jakub Dawidek return (conn->pc_proto->prt_descriptor(conn->pc_ctx)); 37132115b10SPawel Jakub Dawidek } 37232115b10SPawel Jakub Dawidek 37332115b10SPawel Jakub Dawidek bool 37432115b10SPawel Jakub Dawidek proto_address_match(const struct proto_conn *conn, const char *addr) 37532115b10SPawel Jakub Dawidek { 37632115b10SPawel Jakub Dawidek 3772ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 3782ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 3792ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 380e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_address_match != NULL); 38132115b10SPawel Jakub Dawidek 382e2eabb44SPawel Jakub Dawidek return (conn->pc_proto->prt_address_match(conn->pc_ctx, addr)); 38332115b10SPawel Jakub Dawidek } 38432115b10SPawel Jakub Dawidek 38532115b10SPawel Jakub Dawidek void 38632115b10SPawel Jakub Dawidek proto_local_address(const struct proto_conn *conn, char *addr, size_t size) 38732115b10SPawel Jakub Dawidek { 38832115b10SPawel Jakub Dawidek 3892ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 3902ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 3912ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 392e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_local_address != NULL); 39332115b10SPawel Jakub Dawidek 394e2eabb44SPawel Jakub Dawidek conn->pc_proto->prt_local_address(conn->pc_ctx, addr, size); 39532115b10SPawel Jakub Dawidek } 39632115b10SPawel Jakub Dawidek 39732115b10SPawel Jakub Dawidek void 39832115b10SPawel Jakub Dawidek proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) 39932115b10SPawel Jakub Dawidek { 40032115b10SPawel Jakub Dawidek 4012ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 4022ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 4032ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 404e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_remote_address != NULL); 40532115b10SPawel Jakub Dawidek 406e2eabb44SPawel Jakub Dawidek conn->pc_proto->prt_remote_address(conn->pc_ctx, addr, size); 40732115b10SPawel Jakub Dawidek } 40832115b10SPawel Jakub Dawidek 4095571414cSPawel Jakub Dawidek int 4105571414cSPawel Jakub Dawidek proto_timeout(const struct proto_conn *conn, int timeout) 4115571414cSPawel Jakub Dawidek { 4125571414cSPawel Jakub Dawidek struct timeval tv; 4135571414cSPawel Jakub Dawidek int fd; 4145571414cSPawel Jakub Dawidek 4152ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 4162ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 4172ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 4185571414cSPawel Jakub Dawidek 4195571414cSPawel Jakub Dawidek fd = proto_descriptor(conn); 4202b1b224dSPawel Jakub Dawidek if (fd == -1) 4215571414cSPawel Jakub Dawidek return (-1); 4225571414cSPawel Jakub Dawidek 4235571414cSPawel Jakub Dawidek tv.tv_sec = timeout; 4245571414cSPawel Jakub Dawidek tv.tv_usec = 0; 4252b1b224dSPawel Jakub Dawidek if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) 4265571414cSPawel Jakub Dawidek return (-1); 4272b1b224dSPawel Jakub Dawidek if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) 4285571414cSPawel Jakub Dawidek return (-1); 4295571414cSPawel Jakub Dawidek 4305571414cSPawel Jakub Dawidek return (0); 4315571414cSPawel Jakub Dawidek } 4325571414cSPawel Jakub Dawidek 43332115b10SPawel Jakub Dawidek void 43432115b10SPawel Jakub Dawidek proto_close(struct proto_conn *conn) 43532115b10SPawel Jakub Dawidek { 43632115b10SPawel Jakub Dawidek 4372ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn != NULL); 4382ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 4392ec483c5SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto != NULL); 440e2eabb44SPawel Jakub Dawidek PJDLOG_ASSERT(conn->pc_proto->prt_close != NULL); 44132115b10SPawel Jakub Dawidek 442e2eabb44SPawel Jakub Dawidek conn->pc_proto->prt_close(conn->pc_ctx); 4435ee17035SPawel Jakub Dawidek proto_free(conn); 44432115b10SPawel Jakub Dawidek } 445