1*aa772005SRobert Watson /*- 2*aa772005SRobert Watson * Copyright (c) 2009-2010 The FreeBSD Foundation 3*aa772005SRobert Watson * All rights reserved. 4*aa772005SRobert Watson * 5*aa772005SRobert Watson * This software was developed by Pawel Jakub Dawidek under sponsorship from 6*aa772005SRobert Watson * the FreeBSD Foundation. 7*aa772005SRobert Watson * 8*aa772005SRobert Watson * Redistribution and use in source and binary forms, with or without 9*aa772005SRobert Watson * modification, are permitted provided that the following conditions 10*aa772005SRobert Watson * are met: 11*aa772005SRobert Watson * 1. Redistributions of source code must retain the above copyright 12*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer. 13*aa772005SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 14*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer in the 15*aa772005SRobert Watson * documentation and/or other materials provided with the distribution. 16*aa772005SRobert Watson * 17*aa772005SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18*aa772005SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*aa772005SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*aa772005SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21*aa772005SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*aa772005SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*aa772005SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*aa772005SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*aa772005SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*aa772005SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*aa772005SRobert Watson * SUCH DAMAGE. 28*aa772005SRobert Watson * 29*aa772005SRobert Watson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto.c#1 $ 30*aa772005SRobert Watson */ 31*aa772005SRobert Watson 32*aa772005SRobert Watson #include <sys/types.h> 33*aa772005SRobert Watson #include <sys/queue.h> 34*aa772005SRobert Watson #include <sys/socket.h> 35*aa772005SRobert Watson 36*aa772005SRobert Watson #include <errno.h> 37*aa772005SRobert Watson #include <stdint.h> 38*aa772005SRobert Watson #include <string.h> 39*aa772005SRobert Watson #include <strings.h> 40*aa772005SRobert Watson 41*aa772005SRobert Watson #include "pjdlog.h" 42*aa772005SRobert Watson #include "proto.h" 43*aa772005SRobert Watson #include "proto_impl.h" 44*aa772005SRobert Watson 45*aa772005SRobert Watson #define PROTO_CONN_MAGIC 0x907041c 46*aa772005SRobert Watson struct proto_conn { 47*aa772005SRobert Watson int pc_magic; 48*aa772005SRobert Watson struct proto *pc_proto; 49*aa772005SRobert Watson void *pc_ctx; 50*aa772005SRobert Watson int pc_side; 51*aa772005SRobert Watson #define PROTO_SIDE_CLIENT 0 52*aa772005SRobert Watson #define PROTO_SIDE_SERVER_LISTEN 1 53*aa772005SRobert Watson #define PROTO_SIDE_SERVER_WORK 2 54*aa772005SRobert Watson }; 55*aa772005SRobert Watson 56*aa772005SRobert Watson static TAILQ_HEAD(, proto) protos = TAILQ_HEAD_INITIALIZER(protos); 57*aa772005SRobert Watson 58*aa772005SRobert Watson void 59*aa772005SRobert Watson proto_register(struct proto *proto, bool isdefault) 60*aa772005SRobert Watson { 61*aa772005SRobert Watson static bool seen_default = false; 62*aa772005SRobert Watson 63*aa772005SRobert Watson if (!isdefault) 64*aa772005SRobert Watson TAILQ_INSERT_HEAD(&protos, proto, prt_next); 65*aa772005SRobert Watson else { 66*aa772005SRobert Watson PJDLOG_ASSERT(!seen_default); 67*aa772005SRobert Watson seen_default = true; 68*aa772005SRobert Watson TAILQ_INSERT_TAIL(&protos, proto, prt_next); 69*aa772005SRobert Watson } 70*aa772005SRobert Watson } 71*aa772005SRobert Watson 72*aa772005SRobert Watson static struct proto_conn * 73*aa772005SRobert Watson proto_alloc(struct proto *proto, int side) 74*aa772005SRobert Watson { 75*aa772005SRobert Watson struct proto_conn *conn; 76*aa772005SRobert Watson 77*aa772005SRobert Watson PJDLOG_ASSERT(proto != NULL); 78*aa772005SRobert Watson PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || 79*aa772005SRobert Watson side == PROTO_SIDE_SERVER_LISTEN || 80*aa772005SRobert Watson side == PROTO_SIDE_SERVER_WORK); 81*aa772005SRobert Watson 82*aa772005SRobert Watson conn = malloc(sizeof(*conn)); 83*aa772005SRobert Watson if (conn != NULL) { 84*aa772005SRobert Watson conn->pc_proto = proto; 85*aa772005SRobert Watson conn->pc_side = side; 86*aa772005SRobert Watson conn->pc_magic = PROTO_CONN_MAGIC; 87*aa772005SRobert Watson } 88*aa772005SRobert Watson return (conn); 89*aa772005SRobert Watson } 90*aa772005SRobert Watson 91*aa772005SRobert Watson static void 92*aa772005SRobert Watson proto_free(struct proto_conn *conn) 93*aa772005SRobert Watson { 94*aa772005SRobert Watson 95*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 96*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 97*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT || 98*aa772005SRobert Watson conn->pc_side == PROTO_SIDE_SERVER_LISTEN || 99*aa772005SRobert Watson conn->pc_side == PROTO_SIDE_SERVER_WORK); 100*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 101*aa772005SRobert Watson 102*aa772005SRobert Watson bzero(conn, sizeof(*conn)); 103*aa772005SRobert Watson free(conn); 104*aa772005SRobert Watson } 105*aa772005SRobert Watson 106*aa772005SRobert Watson static int 107*aa772005SRobert Watson proto_common_setup(const char *srcaddr, const char *dstaddr, int timeout, 108*aa772005SRobert Watson int side, struct proto_conn **connp) 109*aa772005SRobert Watson { 110*aa772005SRobert Watson struct proto *proto; 111*aa772005SRobert Watson struct proto_conn *conn; 112*aa772005SRobert Watson void *ctx; 113*aa772005SRobert Watson int ret; 114*aa772005SRobert Watson 115*aa772005SRobert Watson PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || 116*aa772005SRobert Watson side == PROTO_SIDE_SERVER_LISTEN); 117*aa772005SRobert Watson 118*aa772005SRobert Watson TAILQ_FOREACH(proto, &protos, prt_next) { 119*aa772005SRobert Watson if (side == PROTO_SIDE_CLIENT) { 120*aa772005SRobert Watson if (proto->prt_connect == NULL) { 121*aa772005SRobert Watson ret = -1; 122*aa772005SRobert Watson } else { 123*aa772005SRobert Watson ret = proto->prt_connect(srcaddr, dstaddr, 124*aa772005SRobert Watson timeout, &ctx); 125*aa772005SRobert Watson } 126*aa772005SRobert Watson } else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ { 127*aa772005SRobert Watson if (proto->prt_server == NULL) 128*aa772005SRobert Watson ret = -1; 129*aa772005SRobert Watson else 130*aa772005SRobert Watson ret = proto->prt_server(dstaddr, &ctx); 131*aa772005SRobert Watson } 132*aa772005SRobert Watson /* 133*aa772005SRobert Watson * ret == 0 - success 134*aa772005SRobert Watson * ret == -1 - dstaddr is not for this protocol 135*aa772005SRobert Watson * ret > 0 - right protocol, but an error occured 136*aa772005SRobert Watson */ 137*aa772005SRobert Watson if (ret >= 0) 138*aa772005SRobert Watson break; 139*aa772005SRobert Watson } 140*aa772005SRobert Watson if (proto == NULL) { 141*aa772005SRobert Watson /* Unrecognized address. */ 142*aa772005SRobert Watson errno = EINVAL; 143*aa772005SRobert Watson return (-1); 144*aa772005SRobert Watson } 145*aa772005SRobert Watson if (ret > 0) { 146*aa772005SRobert Watson /* An error occured. */ 147*aa772005SRobert Watson errno = ret; 148*aa772005SRobert Watson return (-1); 149*aa772005SRobert Watson } 150*aa772005SRobert Watson conn = proto_alloc(proto, side); 151*aa772005SRobert Watson if (conn == NULL) { 152*aa772005SRobert Watson if (proto->prt_close != NULL) 153*aa772005SRobert Watson proto->prt_close(ctx); 154*aa772005SRobert Watson errno = ENOMEM; 155*aa772005SRobert Watson return (-1); 156*aa772005SRobert Watson } 157*aa772005SRobert Watson conn->pc_ctx = ctx; 158*aa772005SRobert Watson *connp = conn; 159*aa772005SRobert Watson 160*aa772005SRobert Watson return (0); 161*aa772005SRobert Watson } 162*aa772005SRobert Watson 163*aa772005SRobert Watson int 164*aa772005SRobert Watson proto_connect(const char *srcaddr, const char *dstaddr, int timeout, 165*aa772005SRobert Watson struct proto_conn **connp) 166*aa772005SRobert Watson { 167*aa772005SRobert Watson 168*aa772005SRobert Watson PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); 169*aa772005SRobert Watson PJDLOG_ASSERT(dstaddr != NULL); 170*aa772005SRobert Watson PJDLOG_ASSERT(timeout >= -1); 171*aa772005SRobert Watson 172*aa772005SRobert Watson return (proto_common_setup(srcaddr, dstaddr, timeout, 173*aa772005SRobert Watson PROTO_SIDE_CLIENT, connp)); 174*aa772005SRobert Watson } 175*aa772005SRobert Watson 176*aa772005SRobert Watson int 177*aa772005SRobert Watson proto_connect_wait(struct proto_conn *conn, int timeout) 178*aa772005SRobert Watson { 179*aa772005SRobert Watson int error; 180*aa772005SRobert Watson 181*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 182*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 183*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT); 184*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 185*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_connect_wait != NULL); 186*aa772005SRobert Watson PJDLOG_ASSERT(timeout >= 0); 187*aa772005SRobert Watson 188*aa772005SRobert Watson error = conn->pc_proto->prt_connect_wait(conn->pc_ctx, timeout); 189*aa772005SRobert Watson if (error != 0) { 190*aa772005SRobert Watson errno = error; 191*aa772005SRobert Watson return (-1); 192*aa772005SRobert Watson } 193*aa772005SRobert Watson 194*aa772005SRobert Watson return (0); 195*aa772005SRobert Watson } 196*aa772005SRobert Watson 197*aa772005SRobert Watson int 198*aa772005SRobert Watson proto_server(const char *addr, struct proto_conn **connp) 199*aa772005SRobert Watson { 200*aa772005SRobert Watson 201*aa772005SRobert Watson PJDLOG_ASSERT(addr != NULL); 202*aa772005SRobert Watson 203*aa772005SRobert Watson return (proto_common_setup(NULL, addr, -1, PROTO_SIDE_SERVER_LISTEN, 204*aa772005SRobert Watson connp)); 205*aa772005SRobert Watson } 206*aa772005SRobert Watson 207*aa772005SRobert Watson int 208*aa772005SRobert Watson proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) 209*aa772005SRobert Watson { 210*aa772005SRobert Watson struct proto_conn *newconn; 211*aa772005SRobert Watson int error; 212*aa772005SRobert Watson 213*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 214*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 215*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); 216*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 217*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_accept != NULL); 218*aa772005SRobert Watson 219*aa772005SRobert Watson newconn = proto_alloc(conn->pc_proto, PROTO_SIDE_SERVER_WORK); 220*aa772005SRobert Watson if (newconn == NULL) 221*aa772005SRobert Watson return (-1); 222*aa772005SRobert Watson 223*aa772005SRobert Watson error = conn->pc_proto->prt_accept(conn->pc_ctx, &newconn->pc_ctx); 224*aa772005SRobert Watson if (error != 0) { 225*aa772005SRobert Watson proto_free(newconn); 226*aa772005SRobert Watson errno = error; 227*aa772005SRobert Watson return (-1); 228*aa772005SRobert Watson } 229*aa772005SRobert Watson 230*aa772005SRobert Watson *newconnp = newconn; 231*aa772005SRobert Watson 232*aa772005SRobert Watson return (0); 233*aa772005SRobert Watson } 234*aa772005SRobert Watson 235*aa772005SRobert Watson int 236*aa772005SRobert Watson proto_send(const struct proto_conn *conn, const void *data, size_t size) 237*aa772005SRobert Watson { 238*aa772005SRobert Watson int error; 239*aa772005SRobert Watson 240*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 241*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 242*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 243*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); 244*aa772005SRobert Watson 245*aa772005SRobert Watson error = conn->pc_proto->prt_send(conn->pc_ctx, data, size, -1); 246*aa772005SRobert Watson if (error != 0) { 247*aa772005SRobert Watson errno = error; 248*aa772005SRobert Watson return (-1); 249*aa772005SRobert Watson } 250*aa772005SRobert Watson return (0); 251*aa772005SRobert Watson } 252*aa772005SRobert Watson 253*aa772005SRobert Watson int 254*aa772005SRobert Watson proto_recv(const struct proto_conn *conn, void *data, size_t size) 255*aa772005SRobert Watson { 256*aa772005SRobert Watson int error; 257*aa772005SRobert Watson 258*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 259*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 260*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 261*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); 262*aa772005SRobert Watson 263*aa772005SRobert Watson error = conn->pc_proto->prt_recv(conn->pc_ctx, data, size, NULL); 264*aa772005SRobert Watson if (error != 0) { 265*aa772005SRobert Watson errno = error; 266*aa772005SRobert Watson return (-1); 267*aa772005SRobert Watson } 268*aa772005SRobert Watson return (0); 269*aa772005SRobert Watson } 270*aa772005SRobert Watson 271*aa772005SRobert Watson int 272*aa772005SRobert Watson proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn) 273*aa772005SRobert Watson { 274*aa772005SRobert Watson const char *protoname; 275*aa772005SRobert Watson int error, fd; 276*aa772005SRobert Watson 277*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 278*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 279*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 280*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); 281*aa772005SRobert Watson PJDLOG_ASSERT(mconn != NULL); 282*aa772005SRobert Watson PJDLOG_ASSERT(mconn->pc_magic == PROTO_CONN_MAGIC); 283*aa772005SRobert Watson PJDLOG_ASSERT(mconn->pc_proto != NULL); 284*aa772005SRobert Watson fd = proto_descriptor(mconn); 285*aa772005SRobert Watson PJDLOG_ASSERT(fd >= 0); 286*aa772005SRobert Watson protoname = mconn->pc_proto->prt_name; 287*aa772005SRobert Watson PJDLOG_ASSERT(protoname != NULL); 288*aa772005SRobert Watson 289*aa772005SRobert Watson error = conn->pc_proto->prt_send(conn->pc_ctx, 290*aa772005SRobert Watson (const unsigned char *)protoname, strlen(protoname) + 1, fd); 291*aa772005SRobert Watson proto_close(mconn); 292*aa772005SRobert Watson if (error != 0) { 293*aa772005SRobert Watson errno = error; 294*aa772005SRobert Watson return (-1); 295*aa772005SRobert Watson } 296*aa772005SRobert Watson return (0); 297*aa772005SRobert Watson } 298*aa772005SRobert Watson 299*aa772005SRobert Watson int 300*aa772005SRobert Watson proto_wrap(const char *protoname, bool client, int fd, 301*aa772005SRobert Watson struct proto_conn **newconnp) 302*aa772005SRobert Watson { 303*aa772005SRobert Watson struct proto *proto; 304*aa772005SRobert Watson struct proto_conn *newconn; 305*aa772005SRobert Watson int error; 306*aa772005SRobert Watson 307*aa772005SRobert Watson TAILQ_FOREACH(proto, &protos, prt_next) { 308*aa772005SRobert Watson if (strcmp(proto->prt_name, protoname) == 0) 309*aa772005SRobert Watson break; 310*aa772005SRobert Watson } 311*aa772005SRobert Watson if (proto == NULL) { 312*aa772005SRobert Watson errno = EINVAL; 313*aa772005SRobert Watson return (-1); 314*aa772005SRobert Watson } 315*aa772005SRobert Watson 316*aa772005SRobert Watson newconn = proto_alloc(proto, 317*aa772005SRobert Watson client ? PROTO_SIDE_CLIENT : PROTO_SIDE_SERVER_WORK); 318*aa772005SRobert Watson if (newconn == NULL) 319*aa772005SRobert Watson return (-1); 320*aa772005SRobert Watson PJDLOG_ASSERT(newconn->pc_proto->prt_wrap != NULL); 321*aa772005SRobert Watson error = newconn->pc_proto->prt_wrap(fd, client, &newconn->pc_ctx); 322*aa772005SRobert Watson if (error != 0) { 323*aa772005SRobert Watson proto_free(newconn); 324*aa772005SRobert Watson errno = error; 325*aa772005SRobert Watson return (-1); 326*aa772005SRobert Watson } 327*aa772005SRobert Watson 328*aa772005SRobert Watson *newconnp = newconn; 329*aa772005SRobert Watson 330*aa772005SRobert Watson return (0); 331*aa772005SRobert Watson } 332*aa772005SRobert Watson 333*aa772005SRobert Watson int 334*aa772005SRobert Watson proto_connection_recv(const struct proto_conn *conn, bool client, 335*aa772005SRobert Watson struct proto_conn **newconnp) 336*aa772005SRobert Watson { 337*aa772005SRobert Watson char protoname[128]; 338*aa772005SRobert Watson int error, fd; 339*aa772005SRobert Watson 340*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 341*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 342*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 343*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); 344*aa772005SRobert Watson PJDLOG_ASSERT(newconnp != NULL); 345*aa772005SRobert Watson 346*aa772005SRobert Watson bzero(protoname, sizeof(protoname)); 347*aa772005SRobert Watson 348*aa772005SRobert Watson error = conn->pc_proto->prt_recv(conn->pc_ctx, 349*aa772005SRobert Watson (unsigned char *)protoname, sizeof(protoname) - 1, &fd); 350*aa772005SRobert Watson if (error != 0) { 351*aa772005SRobert Watson errno = error; 352*aa772005SRobert Watson return (-1); 353*aa772005SRobert Watson } 354*aa772005SRobert Watson 355*aa772005SRobert Watson PJDLOG_ASSERT(fd >= 0); 356*aa772005SRobert Watson 357*aa772005SRobert Watson return (proto_wrap(protoname, client, fd, newconnp)); 358*aa772005SRobert Watson } 359*aa772005SRobert Watson 360*aa772005SRobert Watson int 361*aa772005SRobert Watson proto_descriptor(const struct proto_conn *conn) 362*aa772005SRobert Watson { 363*aa772005SRobert Watson 364*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 365*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 366*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 367*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_descriptor != NULL); 368*aa772005SRobert Watson 369*aa772005SRobert Watson return (conn->pc_proto->prt_descriptor(conn->pc_ctx)); 370*aa772005SRobert Watson } 371*aa772005SRobert Watson 372*aa772005SRobert Watson bool 373*aa772005SRobert Watson proto_address_match(const struct proto_conn *conn, const char *addr) 374*aa772005SRobert Watson { 375*aa772005SRobert Watson 376*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 377*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 378*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 379*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_address_match != NULL); 380*aa772005SRobert Watson 381*aa772005SRobert Watson return (conn->pc_proto->prt_address_match(conn->pc_ctx, addr)); 382*aa772005SRobert Watson } 383*aa772005SRobert Watson 384*aa772005SRobert Watson void 385*aa772005SRobert Watson proto_local_address(const struct proto_conn *conn, char *addr, size_t size) 386*aa772005SRobert Watson { 387*aa772005SRobert Watson 388*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 389*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 390*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 391*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_local_address != NULL); 392*aa772005SRobert Watson 393*aa772005SRobert Watson conn->pc_proto->prt_local_address(conn->pc_ctx, addr, size); 394*aa772005SRobert Watson } 395*aa772005SRobert Watson 396*aa772005SRobert Watson void 397*aa772005SRobert Watson proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) 398*aa772005SRobert Watson { 399*aa772005SRobert Watson 400*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 401*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 402*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 403*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_remote_address != NULL); 404*aa772005SRobert Watson 405*aa772005SRobert Watson conn->pc_proto->prt_remote_address(conn->pc_ctx, addr, size); 406*aa772005SRobert Watson } 407*aa772005SRobert Watson 408*aa772005SRobert Watson int 409*aa772005SRobert Watson proto_timeout(const struct proto_conn *conn, int timeout) 410*aa772005SRobert Watson { 411*aa772005SRobert Watson struct timeval tv; 412*aa772005SRobert Watson int fd; 413*aa772005SRobert Watson 414*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 415*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 416*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 417*aa772005SRobert Watson 418*aa772005SRobert Watson fd = proto_descriptor(conn); 419*aa772005SRobert Watson if (fd < 0) 420*aa772005SRobert Watson return (-1); 421*aa772005SRobert Watson 422*aa772005SRobert Watson tv.tv_sec = timeout; 423*aa772005SRobert Watson tv.tv_usec = 0; 424*aa772005SRobert Watson if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) 425*aa772005SRobert Watson return (-1); 426*aa772005SRobert Watson if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) 427*aa772005SRobert Watson return (-1); 428*aa772005SRobert Watson 429*aa772005SRobert Watson return (0); 430*aa772005SRobert Watson } 431*aa772005SRobert Watson 432*aa772005SRobert Watson void 433*aa772005SRobert Watson proto_close(struct proto_conn *conn) 434*aa772005SRobert Watson { 435*aa772005SRobert Watson 436*aa772005SRobert Watson PJDLOG_ASSERT(conn != NULL); 437*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); 438*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto != NULL); 439*aa772005SRobert Watson PJDLOG_ASSERT(conn->pc_proto->prt_close != NULL); 440*aa772005SRobert Watson 441*aa772005SRobert Watson conn->pc_proto->prt_close(conn->pc_ctx); 442*aa772005SRobert Watson proto_free(conn); 443*aa772005SRobert Watson } 444*aa772005SRobert Watson 445*aa772005SRobert Watson int 446*aa772005SRobert Watson proto_exec(int argc, char *argv[]) 447*aa772005SRobert Watson { 448*aa772005SRobert Watson struct proto *proto; 449*aa772005SRobert Watson int error; 450*aa772005SRobert Watson 451*aa772005SRobert Watson if (argc == 0) { 452*aa772005SRobert Watson errno = EINVAL; 453*aa772005SRobert Watson return (-1); 454*aa772005SRobert Watson } 455*aa772005SRobert Watson TAILQ_FOREACH(proto, &protos, prt_next) { 456*aa772005SRobert Watson if (strcmp(proto->prt_name, argv[0]) == 0) 457*aa772005SRobert Watson break; 458*aa772005SRobert Watson } 459*aa772005SRobert Watson if (proto == NULL) { 460*aa772005SRobert Watson errno = EINVAL; 461*aa772005SRobert Watson return (-1); 462*aa772005SRobert Watson } 463*aa772005SRobert Watson if (proto->prt_exec == NULL) { 464*aa772005SRobert Watson errno = EOPNOTSUPP; 465*aa772005SRobert Watson return (-1); 466*aa772005SRobert Watson } 467*aa772005SRobert Watson error = proto->prt_exec(argc, argv); 468*aa772005SRobert Watson if (error != 0) { 469*aa772005SRobert Watson errno = error; 470*aa772005SRobert Watson return (-1); 471*aa772005SRobert Watson } 472*aa772005SRobert Watson /* NOTREACHED */ 473*aa772005SRobert Watson return (0); 474*aa772005SRobert Watson } 475*aa772005SRobert Watson 476*aa772005SRobert Watson struct proto_nvpair { 477*aa772005SRobert Watson char *pnv_name; 478*aa772005SRobert Watson char *pnv_value; 479*aa772005SRobert Watson TAILQ_ENTRY(proto_nvpair) pnv_next; 480*aa772005SRobert Watson }; 481*aa772005SRobert Watson 482*aa772005SRobert Watson static TAILQ_HEAD(, proto_nvpair) proto_nvpairs = 483*aa772005SRobert Watson TAILQ_HEAD_INITIALIZER(proto_nvpairs); 484*aa772005SRobert Watson 485*aa772005SRobert Watson int 486*aa772005SRobert Watson proto_set(const char *name, const char *value) 487*aa772005SRobert Watson { 488*aa772005SRobert Watson struct proto_nvpair *pnv; 489*aa772005SRobert Watson 490*aa772005SRobert Watson TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { 491*aa772005SRobert Watson if (strcmp(pnv->pnv_name, name) == 0) 492*aa772005SRobert Watson break; 493*aa772005SRobert Watson } 494*aa772005SRobert Watson if (pnv != NULL) { 495*aa772005SRobert Watson TAILQ_REMOVE(&proto_nvpairs, pnv, pnv_next); 496*aa772005SRobert Watson free(pnv->pnv_value); 497*aa772005SRobert Watson } else { 498*aa772005SRobert Watson pnv = malloc(sizeof(*pnv)); 499*aa772005SRobert Watson if (pnv == NULL) 500*aa772005SRobert Watson return (-1); 501*aa772005SRobert Watson pnv->pnv_name = strdup(name); 502*aa772005SRobert Watson if (pnv->pnv_name == NULL) { 503*aa772005SRobert Watson free(pnv); 504*aa772005SRobert Watson return (-1); 505*aa772005SRobert Watson } 506*aa772005SRobert Watson } 507*aa772005SRobert Watson pnv->pnv_value = strdup(value); 508*aa772005SRobert Watson if (pnv->pnv_value == NULL) { 509*aa772005SRobert Watson free(pnv->pnv_name); 510*aa772005SRobert Watson free(pnv); 511*aa772005SRobert Watson return (-1); 512*aa772005SRobert Watson } 513*aa772005SRobert Watson TAILQ_INSERT_TAIL(&proto_nvpairs, pnv, pnv_next); 514*aa772005SRobert Watson return (0); 515*aa772005SRobert Watson } 516*aa772005SRobert Watson 517*aa772005SRobert Watson const char * 518*aa772005SRobert Watson proto_get(const char *name) 519*aa772005SRobert Watson { 520*aa772005SRobert Watson struct proto_nvpair *pnv; 521*aa772005SRobert Watson 522*aa772005SRobert Watson TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { 523*aa772005SRobert Watson if (strcmp(pnv->pnv_name, name) == 0) 524*aa772005SRobert Watson break; 525*aa772005SRobert Watson } 526*aa772005SRobert Watson if (pnv != NULL) 527*aa772005SRobert Watson return (pnv->pnv_value); 528*aa772005SRobert Watson return (NULL); 529*aa772005SRobert Watson } 530