1 1.4 christos /* $NetBSD: ip_trans.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */ 2 1.1 christos /*- 3 1.1 christos * Copyright (c) 1996 4 1.1 christos * Keith Bostic. All rights reserved. 5 1.1 christos * 6 1.1 christos * See the LICENSE file for redistribution information. 7 1.1 christos */ 8 1.1 christos 9 1.1 christos #include "config.h" 10 1.1 christos 11 1.4 christos #include <sys/cdefs.h> 12 1.4 christos #if 0 13 1.1 christos #ifndef lint 14 1.1 christos static const char sccsid[] = "Id: ip_trans.c,v 8.18 2001/06/25 15:19:25 skimo Exp (Berkeley) Date: 2001/06/25 15:19:25 "; 15 1.1 christos #endif /* not lint */ 16 1.4 christos #else 17 1.4 christos __RCSID("$NetBSD: ip_trans.c,v 1.4 2014/01/26 21:43:45 christos Exp $"); 18 1.4 christos #endif 19 1.1 christos 20 1.1 christos #include <sys/types.h> 21 1.1 christos #include <sys/queue.h> 22 1.1 christos #ifdef HAVE_SYS_SELECT_H 23 1.1 christos #include <sys/select.h> 24 1.1 christos #endif 25 1.1 christos 26 1.1 christos #include <bitstring.h> 27 1.1 christos #include <stdio.h> 28 1.1 christos #include <string.h> 29 1.1 christos #include <unistd.h> 30 1.1 christos #include <netinet/in.h> 31 1.1 christos 32 1.1 christos #ifdef __STDC__ 33 1.1 christos #include <stdarg.h> 34 1.1 christos #else 35 1.1 christos #include <varargs.h> 36 1.1 christos #endif 37 1.1 christos 38 1.1 christos #include "../common/common.h" 39 1.1 christos #include "ip.h" 40 1.1 christos #include "ipc_def.h" 41 1.1 christos 42 1.1 christos static char ibuf[2048]; /* Input buffer. */ 43 1.1 christos static size_t ibuf_len; /* Length of current input. */ 44 1.1 christos 45 1.1 christos extern IPFUNLIST const ipfuns[]; 46 1.1 christos 47 1.1 christos /* 48 1.1 christos * vi_input -- 49 1.1 christos * Read from the vi message queue. 50 1.1 christos * 51 1.1 christos * PUBLIC: int vi_input __P((IPVIWIN *, int)); 52 1.1 christos */ 53 1.1 christos int 54 1.1 christos vi_input(IPVIWIN *ipviwin, int fd) 55 1.1 christos { 56 1.1 christos ssize_t nr; 57 1.1 christos 58 1.1 christos /* Read waiting vi messages and translate to X calls. */ 59 1.1 christos switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) { 60 1.1 christos case 0: 61 1.1 christos return (0); 62 1.1 christos case -1: 63 1.1 christos return (-1); 64 1.1 christos default: 65 1.1 christos break; 66 1.1 christos } 67 1.1 christos ibuf_len += nr; 68 1.1 christos 69 1.1 christos /* Parse to data end or partial message. */ 70 1.1 christos (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL); 71 1.1 christos 72 1.1 christos return (ibuf_len > 0); 73 1.1 christos } 74 1.1 christos 75 1.1 christos /* 76 1.1 christos * vi_wsend -- 77 1.1 christos * Construct and send an IP buffer, and wait for an answer. 78 1.1 christos * 79 1.1 christos * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *)); 80 1.1 christos */ 81 1.1 christos int 82 1.1 christos vi_wsend(IPVIWIN *ipviwin, char *fmt, IP_BUF *ipbp) 83 1.1 christos { 84 1.1 christos fd_set rdfd; 85 1.1 christos ssize_t nr; 86 1.1 christos 87 1.1 christos if (vi_send(ipviwin->ofd, fmt, ipbp)) 88 1.1 christos return (1); 89 1.1 christos 90 1.1 christos FD_ZERO(&rdfd); 91 1.1 christos ipbp->code = CODE_OOB; 92 1.1 christos 93 1.1 christos for (;;) { 94 1.1 christos FD_SET(ipviwin->ifd, &rdfd); 95 1.1 christos if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0) 96 1.1 christos return (-1); 97 1.1 christos 98 1.1 christos /* Read waiting vi messages and translate to X calls. */ 99 1.1 christos switch (nr = 100 1.1 christos read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) { 101 1.1 christos case 0: 102 1.1 christos return (0); 103 1.1 christos case -1: 104 1.1 christos return (-1); 105 1.1 christos default: 106 1.1 christos break; 107 1.1 christos } 108 1.1 christos ibuf_len += nr; 109 1.1 christos 110 1.1 christos /* Parse to data end or partial message. */ 111 1.1 christos (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp); 112 1.1 christos 113 1.1 christos if (ipbp->code != CODE_OOB) 114 1.1 christos break; 115 1.1 christos } 116 1.1 christos return (0); 117 1.1 christos } 118 1.1 christos 119 1.1 christos /* 120 1.1 christos * vi_translate -- 121 1.1 christos * Translate vi messages into function calls. 122 1.1 christos * 123 1.1 christos * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *)); 124 1.1 christos */ 125 1.1 christos int 126 1.1 christos vi_translate(IPVIWIN *ipviwin, char *bp, size_t *lenp, IP_BUF *ipbp) 127 1.1 christos { 128 1.1 christos IP_BUF ipb; 129 1.1 christos size_t len, needlen; 130 1.1 christos u_int32_t *vp; 131 1.2 christos const char *fmt; 132 1.2 christos char *p, *s_bp; 133 1.1 christos const char **vsp; 134 1.1 christos IPFunc fun; 135 1.1 christos 136 1.3 christos memset(&ipb, 0, sizeof(ipb)); 137 1.1 christos for (s_bp = bp, len = *lenp; len > 0;) { 138 1.1 christos fmt = ipfuns[(ipb.code = bp[0])-1].format; 139 1.1 christos 140 1.1 christos p = bp + IPO_CODE_LEN; 141 1.1 christos needlen = IPO_CODE_LEN; 142 1.1 christos for (; *fmt != '\0'; ++fmt) 143 1.1 christos switch (*fmt) { 144 1.1 christos case '1': /* Value #1. */ 145 1.1 christos vp = &ipb.val1; 146 1.1 christos goto value; 147 1.1 christos case '2': /* Value #2. */ 148 1.1 christos vp = &ipb.val2; 149 1.1 christos goto value; 150 1.1 christos case '3': /* Value #3. */ 151 1.1 christos vp = &ipb.val3; 152 1.1 christos value: needlen += IPO_INT_LEN; 153 1.1 christos if (len < needlen) 154 1.1 christos goto partial; 155 1.1 christos memcpy(vp, p, IPO_INT_LEN); 156 1.1 christos *vp = ntohl(*vp); 157 1.1 christos p += IPO_INT_LEN; 158 1.1 christos break; 159 1.1 christos case 'a': /* String #1. */ 160 1.1 christos vp = &ipb.len1; 161 1.1 christos vsp = &ipb.str1; 162 1.1 christos goto string; 163 1.1 christos case 'b': /* String #2. */ 164 1.1 christos vp = &ipb.len2; 165 1.1 christos vsp = &ipb.str2; 166 1.1 christos string: needlen += IPO_INT_LEN; 167 1.1 christos if (len < needlen) 168 1.1 christos goto partial; 169 1.1 christos memcpy(vp, p, IPO_INT_LEN); 170 1.1 christos *vp = ntohl(*vp); 171 1.1 christos p += IPO_INT_LEN; 172 1.1 christos needlen += *vp; 173 1.1 christos if (len < needlen) 174 1.1 christos goto partial; 175 1.1 christos *vsp = p; 176 1.1 christos p += *vp; 177 1.1 christos break; 178 1.1 christos } 179 1.1 christos bp += needlen; 180 1.1 christos len -= needlen; 181 1.1 christos 182 1.1 christos /* 183 1.1 christos * XXX 184 1.1 christos * Protocol error!?!? 185 1.1 christos */ 186 1.1 christos if (ipb.code >= SI_EVENT_SUP) { 187 1.1 christos len = 0; 188 1.1 christos break; 189 1.1 christos } 190 1.1 christos 191 1.1 christos /* 192 1.1 christos * If we're waiting for a reply and we got it, return it, and 193 1.1 christos * leave any unprocessed data in the buffer. If we got a reply 194 1.1 christos * and we're not waiting for one, discard it -- callers wait 195 1.1 christos * for responses. 196 1.1 christos */ 197 1.1 christos if (ipb.code == SI_REPLY) { 198 1.1 christos if (ipbp == NULL) 199 1.1 christos continue; 200 1.1 christos *ipbp = ipb; 201 1.1 christos break; 202 1.1 christos } 203 1.1 christos 204 1.1 christos /* Call the underlying routine. */ 205 1.1 christos fun = *(IPFunc *) 206 1.1 christos (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset); 207 1.1 christos if (fun != NULL && 208 1.1 christos ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun)) 209 1.1 christos break; 210 1.1 christos } 211 1.1 christos partial: 212 1.1 christos if ((*lenp = len) != 0) 213 1.1 christos memmove(s_bp, bp, len); 214 1.1 christos return (0); 215 1.1 christos } 216