1*0a6a1f1dSLionel Sambuc /* $NetBSD: ip_trans.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc * Copyright (c) 1996
484d9c625SLionel Sambuc * Keith Bostic. All rights reserved.
584d9c625SLionel Sambuc *
684d9c625SLionel Sambuc * See the LICENSE file for redistribution information.
784d9c625SLionel Sambuc */
884d9c625SLionel Sambuc
984d9c625SLionel Sambuc #include "config.h"
1084d9c625SLionel Sambuc
11*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
12*0a6a1f1dSLionel Sambuc #if 0
1384d9c625SLionel Sambuc #ifndef lint
1484d9c625SLionel Sambuc 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 ";
1584d9c625SLionel Sambuc #endif /* not lint */
16*0a6a1f1dSLionel Sambuc #else
17*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ip_trans.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
18*0a6a1f1dSLionel Sambuc #endif
1984d9c625SLionel Sambuc
2084d9c625SLionel Sambuc #include <sys/types.h>
2184d9c625SLionel Sambuc #include <sys/queue.h>
2284d9c625SLionel Sambuc #ifdef HAVE_SYS_SELECT_H
2384d9c625SLionel Sambuc #include <sys/select.h>
2484d9c625SLionel Sambuc #endif
2584d9c625SLionel Sambuc
2684d9c625SLionel Sambuc #include <bitstring.h>
2784d9c625SLionel Sambuc #include <stdio.h>
2884d9c625SLionel Sambuc #include <string.h>
2984d9c625SLionel Sambuc #include <unistd.h>
3084d9c625SLionel Sambuc #include <netinet/in.h>
3184d9c625SLionel Sambuc
3284d9c625SLionel Sambuc #ifdef __STDC__
3384d9c625SLionel Sambuc #include <stdarg.h>
3484d9c625SLionel Sambuc #else
3584d9c625SLionel Sambuc #include <varargs.h>
3684d9c625SLionel Sambuc #endif
3784d9c625SLionel Sambuc
3884d9c625SLionel Sambuc #include "../common/common.h"
3984d9c625SLionel Sambuc #include "ip.h"
4084d9c625SLionel Sambuc #include "ipc_def.h"
4184d9c625SLionel Sambuc
4284d9c625SLionel Sambuc static char ibuf[2048]; /* Input buffer. */
4384d9c625SLionel Sambuc static size_t ibuf_len; /* Length of current input. */
4484d9c625SLionel Sambuc
4584d9c625SLionel Sambuc extern IPFUNLIST const ipfuns[];
4684d9c625SLionel Sambuc
4784d9c625SLionel Sambuc /*
4884d9c625SLionel Sambuc * vi_input --
4984d9c625SLionel Sambuc * Read from the vi message queue.
5084d9c625SLionel Sambuc *
5184d9c625SLionel Sambuc * PUBLIC: int vi_input __P((IPVIWIN *, int));
5284d9c625SLionel Sambuc */
5384d9c625SLionel Sambuc int
vi_input(IPVIWIN * ipviwin,int fd)5484d9c625SLionel Sambuc vi_input(IPVIWIN *ipviwin, int fd)
5584d9c625SLionel Sambuc {
5684d9c625SLionel Sambuc ssize_t nr;
5784d9c625SLionel Sambuc
5884d9c625SLionel Sambuc /* Read waiting vi messages and translate to X calls. */
5984d9c625SLionel Sambuc switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
6084d9c625SLionel Sambuc case 0:
6184d9c625SLionel Sambuc return (0);
6284d9c625SLionel Sambuc case -1:
6384d9c625SLionel Sambuc return (-1);
6484d9c625SLionel Sambuc default:
6584d9c625SLionel Sambuc break;
6684d9c625SLionel Sambuc }
6784d9c625SLionel Sambuc ibuf_len += nr;
6884d9c625SLionel Sambuc
6984d9c625SLionel Sambuc /* Parse to data end or partial message. */
7084d9c625SLionel Sambuc (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL);
7184d9c625SLionel Sambuc
7284d9c625SLionel Sambuc return (ibuf_len > 0);
7384d9c625SLionel Sambuc }
7484d9c625SLionel Sambuc
7584d9c625SLionel Sambuc /*
7684d9c625SLionel Sambuc * vi_wsend --
7784d9c625SLionel Sambuc * Construct and send an IP buffer, and wait for an answer.
7884d9c625SLionel Sambuc *
7984d9c625SLionel Sambuc * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
8084d9c625SLionel Sambuc */
8184d9c625SLionel Sambuc int
vi_wsend(IPVIWIN * ipviwin,char * fmt,IP_BUF * ipbp)8284d9c625SLionel Sambuc vi_wsend(IPVIWIN *ipviwin, char *fmt, IP_BUF *ipbp)
8384d9c625SLionel Sambuc {
8484d9c625SLionel Sambuc fd_set rdfd;
8584d9c625SLionel Sambuc ssize_t nr;
8684d9c625SLionel Sambuc
8784d9c625SLionel Sambuc if (vi_send(ipviwin->ofd, fmt, ipbp))
8884d9c625SLionel Sambuc return (1);
8984d9c625SLionel Sambuc
9084d9c625SLionel Sambuc FD_ZERO(&rdfd);
9184d9c625SLionel Sambuc ipbp->code = CODE_OOB;
9284d9c625SLionel Sambuc
9384d9c625SLionel Sambuc for (;;) {
9484d9c625SLionel Sambuc FD_SET(ipviwin->ifd, &rdfd);
9584d9c625SLionel Sambuc if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
9684d9c625SLionel Sambuc return (-1);
9784d9c625SLionel Sambuc
9884d9c625SLionel Sambuc /* Read waiting vi messages and translate to X calls. */
9984d9c625SLionel Sambuc switch (nr =
10084d9c625SLionel Sambuc read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
10184d9c625SLionel Sambuc case 0:
10284d9c625SLionel Sambuc return (0);
10384d9c625SLionel Sambuc case -1:
10484d9c625SLionel Sambuc return (-1);
10584d9c625SLionel Sambuc default:
10684d9c625SLionel Sambuc break;
10784d9c625SLionel Sambuc }
10884d9c625SLionel Sambuc ibuf_len += nr;
10984d9c625SLionel Sambuc
11084d9c625SLionel Sambuc /* Parse to data end or partial message. */
11184d9c625SLionel Sambuc (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp);
11284d9c625SLionel Sambuc
11384d9c625SLionel Sambuc if (ipbp->code != CODE_OOB)
11484d9c625SLionel Sambuc break;
11584d9c625SLionel Sambuc }
11684d9c625SLionel Sambuc return (0);
11784d9c625SLionel Sambuc }
11884d9c625SLionel Sambuc
11984d9c625SLionel Sambuc /*
12084d9c625SLionel Sambuc * vi_translate --
12184d9c625SLionel Sambuc * Translate vi messages into function calls.
12284d9c625SLionel Sambuc *
12384d9c625SLionel Sambuc * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
12484d9c625SLionel Sambuc */
12584d9c625SLionel Sambuc int
vi_translate(IPVIWIN * ipviwin,char * bp,size_t * lenp,IP_BUF * ipbp)12684d9c625SLionel Sambuc vi_translate(IPVIWIN *ipviwin, char *bp, size_t *lenp, IP_BUF *ipbp)
12784d9c625SLionel Sambuc {
12884d9c625SLionel Sambuc IP_BUF ipb;
12984d9c625SLionel Sambuc size_t len, needlen;
13084d9c625SLionel Sambuc u_int32_t *vp;
13184d9c625SLionel Sambuc const char *fmt;
13284d9c625SLionel Sambuc char *p, *s_bp;
13384d9c625SLionel Sambuc const char **vsp;
13484d9c625SLionel Sambuc IPFunc fun;
13584d9c625SLionel Sambuc
13684d9c625SLionel Sambuc memset(&ipb, 0, sizeof(ipb));
13784d9c625SLionel Sambuc for (s_bp = bp, len = *lenp; len > 0;) {
13884d9c625SLionel Sambuc fmt = ipfuns[(ipb.code = bp[0])-1].format;
13984d9c625SLionel Sambuc
14084d9c625SLionel Sambuc p = bp + IPO_CODE_LEN;
14184d9c625SLionel Sambuc needlen = IPO_CODE_LEN;
14284d9c625SLionel Sambuc for (; *fmt != '\0'; ++fmt)
14384d9c625SLionel Sambuc switch (*fmt) {
14484d9c625SLionel Sambuc case '1': /* Value #1. */
14584d9c625SLionel Sambuc vp = &ipb.val1;
14684d9c625SLionel Sambuc goto value;
14784d9c625SLionel Sambuc case '2': /* Value #2. */
14884d9c625SLionel Sambuc vp = &ipb.val2;
14984d9c625SLionel Sambuc goto value;
15084d9c625SLionel Sambuc case '3': /* Value #3. */
15184d9c625SLionel Sambuc vp = &ipb.val3;
15284d9c625SLionel Sambuc value: needlen += IPO_INT_LEN;
15384d9c625SLionel Sambuc if (len < needlen)
15484d9c625SLionel Sambuc goto partial;
15584d9c625SLionel Sambuc memcpy(vp, p, IPO_INT_LEN);
15684d9c625SLionel Sambuc *vp = ntohl(*vp);
15784d9c625SLionel Sambuc p += IPO_INT_LEN;
15884d9c625SLionel Sambuc break;
15984d9c625SLionel Sambuc case 'a': /* String #1. */
16084d9c625SLionel Sambuc vp = &ipb.len1;
16184d9c625SLionel Sambuc vsp = &ipb.str1;
16284d9c625SLionel Sambuc goto string;
16384d9c625SLionel Sambuc case 'b': /* String #2. */
16484d9c625SLionel Sambuc vp = &ipb.len2;
16584d9c625SLionel Sambuc vsp = &ipb.str2;
16684d9c625SLionel Sambuc string: needlen += IPO_INT_LEN;
16784d9c625SLionel Sambuc if (len < needlen)
16884d9c625SLionel Sambuc goto partial;
16984d9c625SLionel Sambuc memcpy(vp, p, IPO_INT_LEN);
17084d9c625SLionel Sambuc *vp = ntohl(*vp);
17184d9c625SLionel Sambuc p += IPO_INT_LEN;
17284d9c625SLionel Sambuc needlen += *vp;
17384d9c625SLionel Sambuc if (len < needlen)
17484d9c625SLionel Sambuc goto partial;
17584d9c625SLionel Sambuc *vsp = p;
17684d9c625SLionel Sambuc p += *vp;
17784d9c625SLionel Sambuc break;
17884d9c625SLionel Sambuc }
17984d9c625SLionel Sambuc bp += needlen;
18084d9c625SLionel Sambuc len -= needlen;
18184d9c625SLionel Sambuc
18284d9c625SLionel Sambuc /*
18384d9c625SLionel Sambuc * XXX
18484d9c625SLionel Sambuc * Protocol error!?!?
18584d9c625SLionel Sambuc */
18684d9c625SLionel Sambuc if (ipb.code >= SI_EVENT_SUP) {
18784d9c625SLionel Sambuc len = 0;
18884d9c625SLionel Sambuc break;
18984d9c625SLionel Sambuc }
19084d9c625SLionel Sambuc
19184d9c625SLionel Sambuc /*
19284d9c625SLionel Sambuc * If we're waiting for a reply and we got it, return it, and
19384d9c625SLionel Sambuc * leave any unprocessed data in the buffer. If we got a reply
19484d9c625SLionel Sambuc * and we're not waiting for one, discard it -- callers wait
19584d9c625SLionel Sambuc * for responses.
19684d9c625SLionel Sambuc */
19784d9c625SLionel Sambuc if (ipb.code == SI_REPLY) {
19884d9c625SLionel Sambuc if (ipbp == NULL)
19984d9c625SLionel Sambuc continue;
20084d9c625SLionel Sambuc *ipbp = ipb;
20184d9c625SLionel Sambuc break;
20284d9c625SLionel Sambuc }
20384d9c625SLionel Sambuc
20484d9c625SLionel Sambuc /* Call the underlying routine. */
20584d9c625SLionel Sambuc fun = *(IPFunc *)
20684d9c625SLionel Sambuc (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset);
20784d9c625SLionel Sambuc if (fun != NULL &&
20884d9c625SLionel Sambuc ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun))
20984d9c625SLionel Sambuc break;
21084d9c625SLionel Sambuc }
21184d9c625SLionel Sambuc partial:
21284d9c625SLionel Sambuc if ((*lenp = len) != 0)
21384d9c625SLionel Sambuc memmove(s_bp, bp, len);
21484d9c625SLionel Sambuc return (0);
21584d9c625SLionel Sambuc }
216