1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1998 by Internet Software Consortium. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 10*7c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 11*7c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14*7c478bd9Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16*7c478bd9Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17*7c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18*7c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19*7c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*7c478bd9Sstevel@tonic-gate * SOFTWARE. 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER) 26*7c478bd9Sstevel@tonic-gate static const char rcsid[] = "$Id: irp.c,v 8.8 2001/09/25 04:50:29 marka Exp $"; 27*7c478bd9Sstevel@tonic-gate #endif 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Imports */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include "port_before.h" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <syslog.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/un.h> 37*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 38*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 39*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <string.h> 42*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 43*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 44*7c478bd9Sstevel@tonic-gate #include <syslog.h> 45*7c478bd9Sstevel@tonic-gate #include <ctype.h> 46*7c478bd9Sstevel@tonic-gate #include <unistd.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include <isc/memcluster.h> 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include <irs.h> 51*7c478bd9Sstevel@tonic-gate #include <irp.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #include "irs_p.h" 54*7c478bd9Sstevel@tonic-gate #include "irp_p.h" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include "port_after.h" 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* Forward. */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static void irp_close(struct irs_acc *); 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #define LINEINCR 128 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #if !defined(SUN_LEN) 65*7c478bd9Sstevel@tonic-gate #define SUN_LEN(su) \ 66*7c478bd9Sstevel@tonic-gate (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) 67*7c478bd9Sstevel@tonic-gate #endif 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* Public */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* send errors to syslog if true. */ 74*7c478bd9Sstevel@tonic-gate int irp_log_errors = 1; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * This module handles the irp module connection to irpd. 78*7c478bd9Sstevel@tonic-gate * 79*7c478bd9Sstevel@tonic-gate * The client expects a synchronous interface to functions like 80*7c478bd9Sstevel@tonic-gate * getpwnam(3), so we can't use the ctl_* i/o library on this end of 81*7c478bd9Sstevel@tonic-gate * the wire (it's used in the server). 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * irs_acc *irs_irp_acc(const char *options); 86*7c478bd9Sstevel@tonic-gate * 87*7c478bd9Sstevel@tonic-gate * Initialize the irp module. 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate struct irs_acc * 90*7c478bd9Sstevel@tonic-gate irs_irp_acc(const char *options) { 91*7c478bd9Sstevel@tonic-gate struct irs_acc *acc; 92*7c478bd9Sstevel@tonic-gate struct irp_p *irp; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate UNUSED(options); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate if (!(acc = memget(sizeof *acc))) { 97*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 98*7c478bd9Sstevel@tonic-gate return (NULL); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate memset(acc, 0x5e, sizeof *acc); 101*7c478bd9Sstevel@tonic-gate if (!(irp = memget(sizeof *irp))) { 102*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 103*7c478bd9Sstevel@tonic-gate free(acc); 104*7c478bd9Sstevel@tonic-gate return (NULL); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate irp->inlast = 0; 107*7c478bd9Sstevel@tonic-gate irp->incurr = 0; 108*7c478bd9Sstevel@tonic-gate irp->fdCxn = -1; 109*7c478bd9Sstevel@tonic-gate acc->private = irp; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #ifdef WANT_IRS_GR 112*7c478bd9Sstevel@tonic-gate acc->gr_map = irs_irp_gr; 113*7c478bd9Sstevel@tonic-gate #else 114*7c478bd9Sstevel@tonic-gate acc->gr_map = NULL; 115*7c478bd9Sstevel@tonic-gate #endif 116*7c478bd9Sstevel@tonic-gate #ifdef WANT_IRS_PW 117*7c478bd9Sstevel@tonic-gate acc->pw_map = irs_irp_pw; 118*7c478bd9Sstevel@tonic-gate #else 119*7c478bd9Sstevel@tonic-gate acc->pw_map = NULL; 120*7c478bd9Sstevel@tonic-gate #endif 121*7c478bd9Sstevel@tonic-gate acc->sv_map = irs_irp_sv; 122*7c478bd9Sstevel@tonic-gate acc->pr_map = irs_irp_pr; 123*7c478bd9Sstevel@tonic-gate acc->ho_map = irs_irp_ho; 124*7c478bd9Sstevel@tonic-gate acc->nw_map = irs_irp_nw; 125*7c478bd9Sstevel@tonic-gate acc->ng_map = irs_irp_ng; 126*7c478bd9Sstevel@tonic-gate acc->close = irp_close; 127*7c478bd9Sstevel@tonic-gate return (acc); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate int 132*7c478bd9Sstevel@tonic-gate irs_irp_connection_setup(struct irp_p *cxndata, int *warned) { 133*7c478bd9Sstevel@tonic-gate if (irs_irp_is_connected(cxndata)) { 134*7c478bd9Sstevel@tonic-gate return (0); 135*7c478bd9Sstevel@tonic-gate } else if (irs_irp_connect(cxndata) != 0) { 136*7c478bd9Sstevel@tonic-gate if (warned != NULL && !*warned) { 137*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "irpd connection failed: %m\n"); 138*7c478bd9Sstevel@tonic-gate (*warned)++; 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate return (-1); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate return (0); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * int irs_irp_connect(void); 150*7c478bd9Sstevel@tonic-gate * 151*7c478bd9Sstevel@tonic-gate * Sets up the connection to the remote irpd server. 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * Returns: 154*7c478bd9Sstevel@tonic-gate * 155*7c478bd9Sstevel@tonic-gate * 0 on success, -1 on failure. 156*7c478bd9Sstevel@tonic-gate * 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate int 159*7c478bd9Sstevel@tonic-gate irs_irp_connect(struct irp_p *pvt) { 160*7c478bd9Sstevel@tonic-gate int flags; 161*7c478bd9Sstevel@tonic-gate struct sockaddr *addr; 162*7c478bd9Sstevel@tonic-gate struct sockaddr_in iaddr; 163*7c478bd9Sstevel@tonic-gate #ifndef NO_SOCKADDR_UN 164*7c478bd9Sstevel@tonic-gate struct sockaddr_un uaddr; 165*7c478bd9Sstevel@tonic-gate #endif 166*7c478bd9Sstevel@tonic-gate long ipaddr; 167*7c478bd9Sstevel@tonic-gate const char *irphost; 168*7c478bd9Sstevel@tonic-gate int code; 169*7c478bd9Sstevel@tonic-gate char text[256]; 170*7c478bd9Sstevel@tonic-gate int socklen = 0; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate if (pvt->fdCxn != -1) { 173*7c478bd9Sstevel@tonic-gate perror("fd != 1"); 174*7c478bd9Sstevel@tonic-gate return (-1); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate #ifndef NO_SOCKADDR_UN 178*7c478bd9Sstevel@tonic-gate memset(&uaddr, 0, sizeof uaddr); 179*7c478bd9Sstevel@tonic-gate #endif 180*7c478bd9Sstevel@tonic-gate memset(&iaddr, 0, sizeof iaddr); 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate irphost = getenv(IRPD_HOST_ENV); 183*7c478bd9Sstevel@tonic-gate if (irphost == NULL) { 184*7c478bd9Sstevel@tonic-gate irphost = "127.0.0.1"; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate #ifndef NO_SOCKADDR_UN 188*7c478bd9Sstevel@tonic-gate if (irphost[0] == '/') { 189*7c478bd9Sstevel@tonic-gate addr = (struct sockaddr *)&uaddr; 190*7c478bd9Sstevel@tonic-gate strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path); 191*7c478bd9Sstevel@tonic-gate uaddr.sun_family = AF_UNIX; 192*7c478bd9Sstevel@tonic-gate socklen = SUN_LEN(&uaddr); 193*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN 194*7c478bd9Sstevel@tonic-gate uaddr.sun_len = socklen; 195*7c478bd9Sstevel@tonic-gate #endif 196*7c478bd9Sstevel@tonic-gate } else 197*7c478bd9Sstevel@tonic-gate #endif 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, irphost, &ipaddr) != 1) { 200*7c478bd9Sstevel@tonic-gate errno = EADDRNOTAVAIL; 201*7c478bd9Sstevel@tonic-gate perror("inet_pton"); 202*7c478bd9Sstevel@tonic-gate return (-1); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate addr = (struct sockaddr *)&iaddr; 206*7c478bd9Sstevel@tonic-gate socklen = sizeof iaddr; 207*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN 208*7c478bd9Sstevel@tonic-gate iaddr.sin_len = socklen; 209*7c478bd9Sstevel@tonic-gate #endif 210*7c478bd9Sstevel@tonic-gate iaddr.sin_family = AF_INET; 211*7c478bd9Sstevel@tonic-gate iaddr.sin_port = htons(IRPD_PORT); 212*7c478bd9Sstevel@tonic-gate iaddr.sin_addr.s_addr = ipaddr; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC); 217*7c478bd9Sstevel@tonic-gate if (pvt->fdCxn < 0) { 218*7c478bd9Sstevel@tonic-gate perror("socket"); 219*7c478bd9Sstevel@tonic-gate return (-1); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate if (connect(pvt->fdCxn, addr, socklen) != 0) { 223*7c478bd9Sstevel@tonic-gate perror("connect"); 224*7c478bd9Sstevel@tonic-gate return (-1); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate flags = fcntl(pvt->fdCxn, F_GETFL, 0); 228*7c478bd9Sstevel@tonic-gate if (flags < 0) { 229*7c478bd9Sstevel@tonic-gate close(pvt->fdCxn); 230*7c478bd9Sstevel@tonic-gate perror("close"); 231*7c478bd9Sstevel@tonic-gate return (-1); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate #if 0 235*7c478bd9Sstevel@tonic-gate flags |= O_NONBLOCK; 236*7c478bd9Sstevel@tonic-gate if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) { 237*7c478bd9Sstevel@tonic-gate close(pvt->fdCxn); 238*7c478bd9Sstevel@tonic-gate perror("fcntl"); 239*7c478bd9Sstevel@tonic-gate return (-1); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate #endif 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate code = irs_irp_read_response(pvt, text, sizeof text); 244*7c478bd9Sstevel@tonic-gate if (code != IRPD_WELCOME_CODE) { 245*7c478bd9Sstevel@tonic-gate if (irp_log_errors) { 246*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "Connection failed: %s", text); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate irs_irp_disconnect(pvt); 249*7c478bd9Sstevel@tonic-gate return (-1); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate return (0); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * int irs_irp_is_connected(struct irp_p *pvt); 259*7c478bd9Sstevel@tonic-gate * 260*7c478bd9Sstevel@tonic-gate * Returns: 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * Non-zero if streams are setup to remote. 263*7c478bd9Sstevel@tonic-gate * 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate int 267*7c478bd9Sstevel@tonic-gate irs_irp_is_connected(struct irp_p *pvt) { 268*7c478bd9Sstevel@tonic-gate return (pvt->fdCxn >= 0); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * void 275*7c478bd9Sstevel@tonic-gate * irs_irp_disconnect(struct irp_p *pvt); 276*7c478bd9Sstevel@tonic-gate * 277*7c478bd9Sstevel@tonic-gate * Closes streams to remote. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate void 281*7c478bd9Sstevel@tonic-gate irs_irp_disconnect(struct irp_p *pvt) { 282*7c478bd9Sstevel@tonic-gate if (pvt->fdCxn != -1) { 283*7c478bd9Sstevel@tonic-gate close(pvt->fdCxn); 284*7c478bd9Sstevel@tonic-gate pvt->fdCxn = -1; 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate int 291*7c478bd9Sstevel@tonic-gate irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) { 292*7c478bd9Sstevel@tonic-gate char *realstart = &pvt->inbuffer[0]; 293*7c478bd9Sstevel@tonic-gate char *p, *start, *end; 294*7c478bd9Sstevel@tonic-gate int spare; 295*7c478bd9Sstevel@tonic-gate int i; 296*7c478bd9Sstevel@tonic-gate int buffpos = 0; 297*7c478bd9Sstevel@tonic-gate int left = len - 1; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate while (left > 0) { 300*7c478bd9Sstevel@tonic-gate start = p = &pvt->inbuffer[pvt->incurr]; 301*7c478bd9Sstevel@tonic-gate end = &pvt->inbuffer[pvt->inlast]; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate while (p != end && *p != '\n') 304*7c478bd9Sstevel@tonic-gate p++; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (p == end) { 307*7c478bd9Sstevel@tonic-gate /* Found no newline so shift data down if necessary 308*7c478bd9Sstevel@tonic-gate * and append new data to buffer 309*7c478bd9Sstevel@tonic-gate */ 310*7c478bd9Sstevel@tonic-gate if (start > realstart) { 311*7c478bd9Sstevel@tonic-gate memmove(realstart, start, end - start); 312*7c478bd9Sstevel@tonic-gate pvt->inlast = end - start; 313*7c478bd9Sstevel@tonic-gate start = realstart; 314*7c478bd9Sstevel@tonic-gate pvt->incurr = 0; 315*7c478bd9Sstevel@tonic-gate end = &pvt->inbuffer[pvt->inlast]; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate spare = sizeof (pvt->inbuffer) - pvt->inlast; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate p = end; 321*7c478bd9Sstevel@tonic-gate i = read(pvt->fdCxn, end, spare); 322*7c478bd9Sstevel@tonic-gate if (i < 0) { 323*7c478bd9Sstevel@tonic-gate close(pvt->fdCxn); 324*7c478bd9Sstevel@tonic-gate pvt->fdCxn = -1; 325*7c478bd9Sstevel@tonic-gate return (buffpos > 0 ? buffpos : -1); 326*7c478bd9Sstevel@tonic-gate } else if (i == 0) { 327*7c478bd9Sstevel@tonic-gate return (buffpos); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate end += i; 331*7c478bd9Sstevel@tonic-gate pvt->inlast += i; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate while (p != end && *p != '\n') 334*7c478bd9Sstevel@tonic-gate p++; 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate if (p == end) { 338*7c478bd9Sstevel@tonic-gate /* full buffer and still no newline */ 339*7c478bd9Sstevel@tonic-gate i = sizeof pvt->inbuffer; 340*7c478bd9Sstevel@tonic-gate } else { 341*7c478bd9Sstevel@tonic-gate /* include newline */ 342*7c478bd9Sstevel@tonic-gate i = p - start + 1; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (i > left) 346*7c478bd9Sstevel@tonic-gate i = left; 347*7c478bd9Sstevel@tonic-gate memcpy(buffer + buffpos, start, i); 348*7c478bd9Sstevel@tonic-gate pvt->incurr += i; 349*7c478bd9Sstevel@tonic-gate buffpos += i; 350*7c478bd9Sstevel@tonic-gate buffer[buffpos] = '\0'; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate if (p != end) { 353*7c478bd9Sstevel@tonic-gate left = 0; 354*7c478bd9Sstevel@tonic-gate } else { 355*7c478bd9Sstevel@tonic-gate left -= i; 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate #if 0 360*7c478bd9Sstevel@tonic-gate fprintf(stderr, "read line: %s\n", buffer); 361*7c478bd9Sstevel@tonic-gate #endif 362*7c478bd9Sstevel@tonic-gate return (buffpos); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * int irp_read_response(struct irp_p *pvt); 371*7c478bd9Sstevel@tonic-gate * 372*7c478bd9Sstevel@tonic-gate * Returns: 373*7c478bd9Sstevel@tonic-gate * 374*7c478bd9Sstevel@tonic-gate * The number found at the beginning of the line read from 375*7c478bd9Sstevel@tonic-gate * FP. 0 on failure(0 is not a legal response code). The 376*7c478bd9Sstevel@tonic-gate * rest of the line is discarded. 377*7c478bd9Sstevel@tonic-gate * 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate int 381*7c478bd9Sstevel@tonic-gate irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { 382*7c478bd9Sstevel@tonic-gate char line[1024]; 383*7c478bd9Sstevel@tonic-gate int code; 384*7c478bd9Sstevel@tonic-gate char *p; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if (irs_irp_read_line(pvt, line, sizeof line) <= 0) { 387*7c478bd9Sstevel@tonic-gate return (0); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate p = strchr(line, '\n'); 391*7c478bd9Sstevel@tonic-gate if (p == NULL) { 392*7c478bd9Sstevel@tonic-gate return (0); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate if (sscanf(line, "%d", &code) != 1) { 396*7c478bd9Sstevel@tonic-gate code = 0; 397*7c478bd9Sstevel@tonic-gate } else if (text != NULL && textlen > 0) { 398*7c478bd9Sstevel@tonic-gate p = line; 399*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*p)) p++; 400*7c478bd9Sstevel@tonic-gate while (isdigit((unsigned char)*p)) p++; 401*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*p)) p++; 402*7c478bd9Sstevel@tonic-gate strncpy(text, p, textlen - 1); 403*7c478bd9Sstevel@tonic-gate p[textlen - 1] = '\0'; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate return (code); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* 412*7c478bd9Sstevel@tonic-gate * char *irp_read_body(struct irp_p *pvt, size_t *size); 413*7c478bd9Sstevel@tonic-gate * 414*7c478bd9Sstevel@tonic-gate * Read in the body of a response. Terminated by a line with 415*7c478bd9Sstevel@tonic-gate * just a dot on it. Lines should be terminated with a CR-LF 416*7c478bd9Sstevel@tonic-gate * sequence, but we're nt piccky if the CR is missing. 417*7c478bd9Sstevel@tonic-gate * No leading dot escaping is done as the protcol doesn't 418*7c478bd9Sstevel@tonic-gate * use leading dots anywhere. 419*7c478bd9Sstevel@tonic-gate * 420*7c478bd9Sstevel@tonic-gate * Returns: 421*7c478bd9Sstevel@tonic-gate * 422*7c478bd9Sstevel@tonic-gate * Pointer to null-terminated buffer allocated by memget. 423*7c478bd9Sstevel@tonic-gate * *SIZE is set to the length of the buffer. 424*7c478bd9Sstevel@tonic-gate * 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate char * 428*7c478bd9Sstevel@tonic-gate irs_irp_read_body(struct irp_p *pvt, size_t *size) { 429*7c478bd9Sstevel@tonic-gate char line[1024]; 430*7c478bd9Sstevel@tonic-gate u_int linelen; 431*7c478bd9Sstevel@tonic-gate size_t len = LINEINCR; 432*7c478bd9Sstevel@tonic-gate char *buffer = memget(len); 433*7c478bd9Sstevel@tonic-gate int idx = 0; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate for (;;) { 436*7c478bd9Sstevel@tonic-gate if (irs_irp_read_line(pvt, line, sizeof line) <= 0 || 437*7c478bd9Sstevel@tonic-gate strchr(line, '\n') == NULL) 438*7c478bd9Sstevel@tonic-gate goto death; 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate linelen = strlen(line); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (line[linelen - 1] != '\n') 443*7c478bd9Sstevel@tonic-gate goto death; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate /* We're not strict about missing \r. Should we be?? */ 446*7c478bd9Sstevel@tonic-gate if (linelen > 2 && line[linelen - 2] == '\r') { 447*7c478bd9Sstevel@tonic-gate line[linelen - 2] = '\n'; 448*7c478bd9Sstevel@tonic-gate line[linelen - 1] = '\0'; 449*7c478bd9Sstevel@tonic-gate linelen--; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (linelen == 2 && line[0] == '.') { 453*7c478bd9Sstevel@tonic-gate *size = len; 454*7c478bd9Sstevel@tonic-gate buffer[idx] = '\0'; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate return (buffer); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate if (linelen > (len - (idx + 1))) { 460*7c478bd9Sstevel@tonic-gate char *p = memget(len + LINEINCR); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate if (p == NULL) 463*7c478bd9Sstevel@tonic-gate goto death; 464*7c478bd9Sstevel@tonic-gate memcpy(p, buffer, len); 465*7c478bd9Sstevel@tonic-gate memput(buffer, len); 466*7c478bd9Sstevel@tonic-gate buffer = p; 467*7c478bd9Sstevel@tonic-gate len += LINEINCR; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate memcpy(buffer + idx, line, linelen); 471*7c478bd9Sstevel@tonic-gate idx += linelen; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate death: 474*7c478bd9Sstevel@tonic-gate memput(buffer, len); 475*7c478bd9Sstevel@tonic-gate return (NULL); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* 480*7c478bd9Sstevel@tonic-gate * int irs_irp_get_full_response(struct irp_p *pvt, int *code, 481*7c478bd9Sstevel@tonic-gate * char **body, size_t *bodylen); 482*7c478bd9Sstevel@tonic-gate * 483*7c478bd9Sstevel@tonic-gate * Gets the response to a command. If the response indicates 484*7c478bd9Sstevel@tonic-gate * there's a body to follow(code % 10 == 1), then the 485*7c478bd9Sstevel@tonic-gate * body buffer is allcoated with memget and stored in 486*7c478bd9Sstevel@tonic-gate * *BODY. The length of the allocated body buffer is stored 487*7c478bd9Sstevel@tonic-gate * in *BODY. The caller must give the body buffer back to 488*7c478bd9Sstevel@tonic-gate * memput when done. The results code is stored in *CODE. 489*7c478bd9Sstevel@tonic-gate * 490*7c478bd9Sstevel@tonic-gate * Returns: 491*7c478bd9Sstevel@tonic-gate * 492*7c478bd9Sstevel@tonic-gate * 0 if a result was read. -1 on some sort of failure. 493*7c478bd9Sstevel@tonic-gate * 494*7c478bd9Sstevel@tonic-gate */ 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate int 497*7c478bd9Sstevel@tonic-gate irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, 498*7c478bd9Sstevel@tonic-gate size_t textlen, char **body, size_t *bodylen) { 499*7c478bd9Sstevel@tonic-gate int result = irs_irp_read_response(pvt, text, textlen); 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate *body = NULL; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate if (result == 0) { 504*7c478bd9Sstevel@tonic-gate return (-1); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate *code = result; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate /* Code that matches 2xx is a good result code. 510*7c478bd9Sstevel@tonic-gate * Code that matches xx1 means there's a response body coming. 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate if ((result / 100) == 2 && (result % 10) == 1) { 513*7c478bd9Sstevel@tonic-gate *body = irs_irp_read_body(pvt, bodylen); 514*7c478bd9Sstevel@tonic-gate if (*body == NULL) { 515*7c478bd9Sstevel@tonic-gate return (-1); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate return (0); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate /* 524*7c478bd9Sstevel@tonic-gate * int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); 525*7c478bd9Sstevel@tonic-gate * 526*7c478bd9Sstevel@tonic-gate * Sends command to remote connected via the PVT 527*7c478bd9Sstevel@tonic-gate * struture. FMT and args after it are fprintf-like 528*7c478bd9Sstevel@tonic-gate * arguments for formatting. 529*7c478bd9Sstevel@tonic-gate * 530*7c478bd9Sstevel@tonic-gate * Returns: 531*7c478bd9Sstevel@tonic-gate * 532*7c478bd9Sstevel@tonic-gate * 0 on success, -1 on failure. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate int 536*7c478bd9Sstevel@tonic-gate irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { 537*7c478bd9Sstevel@tonic-gate va_list ap; 538*7c478bd9Sstevel@tonic-gate char buffer[1024]; 539*7c478bd9Sstevel@tonic-gate int pos = 0; 540*7c478bd9Sstevel@tonic-gate int i, todo; 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (pvt->fdCxn < 0) { 544*7c478bd9Sstevel@tonic-gate return (-1); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 548*7c478bd9Sstevel@tonic-gate todo = vsprintf(buffer, fmt, ap); 549*7c478bd9Sstevel@tonic-gate va_end(ap); 550*7c478bd9Sstevel@tonic-gate if (todo > (int)sizeof(buffer) - 3) { 551*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); 552*7c478bd9Sstevel@tonic-gate exit(1); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate strcat(buffer, "\r\n"); 555*7c478bd9Sstevel@tonic-gate todo = strlen(buffer); 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate while (todo > 0) { 558*7c478bd9Sstevel@tonic-gate i = write(pvt->fdCxn, buffer + pos, todo); 559*7c478bd9Sstevel@tonic-gate #if 0 560*7c478bd9Sstevel@tonic-gate /* XXX brister */ 561*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Wrote: \""); 562*7c478bd9Sstevel@tonic-gate fwrite(buffer + pos, sizeof (char), todo, stderr); 563*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\"\n"); 564*7c478bd9Sstevel@tonic-gate #endif 565*7c478bd9Sstevel@tonic-gate if (i < 0) { 566*7c478bd9Sstevel@tonic-gate close(pvt->fdCxn); 567*7c478bd9Sstevel@tonic-gate pvt->fdCxn = -1; 568*7c478bd9Sstevel@tonic-gate return (-1); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate todo -= i; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate return (0); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate /* Methods */ 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * void irp_close(struct irs_acc *this) 583*7c478bd9Sstevel@tonic-gate * 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate static void 587*7c478bd9Sstevel@tonic-gate irp_close(struct irs_acc *this) { 588*7c478bd9Sstevel@tonic-gate struct irp_p *irp = (struct irp_p *)this->private; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate if (irp != NULL) { 591*7c478bd9Sstevel@tonic-gate irs_irp_disconnect(irp); 592*7c478bd9Sstevel@tonic-gate memput(irp, sizeof *irp); 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate memput(this, sizeof *this); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate 600