157416Smarkm/*
257416Smarkm * Copyright (c) 1988, 1993
357416Smarkm *	The Regents of the University of California.  All rights reserved.
457416Smarkm *
557416Smarkm * Redistribution and use in source and binary forms, with or without
657416Smarkm * modification, are permitted provided that the following conditions
757416Smarkm * are met:
857416Smarkm * 1. Redistributions of source code must retain the above copyright
957416Smarkm *    notice, this list of conditions and the following disclaimer.
1057416Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1157416Smarkm *    notice, this list of conditions and the following disclaimer in the
1257416Smarkm *    documentation and/or other materials provided with the distribution.
1357416Smarkm * 3. All advertising materials mentioning features or use of this software
1457416Smarkm *    must display the following acknowledgement:
1557416Smarkm *	This product includes software developed by the University of
1657416Smarkm *	California, Berkeley and its contributors.
1757416Smarkm * 4. Neither the name of the University nor the names of its contributors
1857416Smarkm *    may be used to endorse or promote products derived from this software
1957416Smarkm *    without specific prior written permission.
2057416Smarkm *
2157416Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2257416Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2357416Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2457416Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2557416Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2657416Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2757416Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2857416Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2957416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3057416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3157416Smarkm * SUCH DAMAGE.
3257416Smarkm */
3357416Smarkm
3457416Smarkm#include "telnet_locl.h"
3557416Smarkm
36233294SstasRCSID("$Id$");
3757416Smarkm
3857416SmarkmRing		netoring, netiring;
39142403Snectarsize_t		netobufsize = 64*1024;
40142403Snectarsize_t		netibufsize = 64*1024;
4157416Smarkm
4257416Smarkm/*
4357416Smarkm * Initialize internal network data structures.
4457416Smarkm */
4557416Smarkm
4657416Smarkmvoid
4757416Smarkminit_network(void)
4857416Smarkm{
49142403Snectar    void *obuf, *ibuf;
50233294Sstas
51142403Snectar    if ((obuf = malloc(netobufsize)) == NULL)
5257416Smarkm	exit(1);
53142403Snectar    if ((ibuf = malloc(netibufsize)) == NULL)
54142403Snectar	exit(1);
55142403Snectar
56142403Snectar    if (ring_init(&netoring, obuf, netobufsize) != 1) {
57142403Snectar	exit(1);
5857416Smarkm    }
59142403Snectar    if (ring_init(&netiring, ibuf, netibufsize) != 1) {
6057416Smarkm	exit(1);
6157416Smarkm    }
6257416Smarkm    NetTrace = stdout;
6357416Smarkm}
6457416Smarkm
6557416Smarkm
6657416Smarkm/*
6757416Smarkm * Check to see if any out-of-band data exists on a socket (for
6857416Smarkm * Telnet "synch" processing).
6957416Smarkm */
7057416Smarkm
7157416Smarkmint
7257416Smarkmstilloob(void)
7357416Smarkm{
7457416Smarkm    static struct timeval timeout = { 0 };
7557416Smarkm    fd_set	excepts;
7657416Smarkm    int value;
7757416Smarkm
7857416Smarkm    do {
7957416Smarkm	FD_ZERO(&excepts);
8072445Sassar	if (net >= FD_SETSIZE)
8172445Sassar	    errx (1, "fd too large");
8257416Smarkm	FD_SET(net, &excepts);
8357416Smarkm	value = select(net+1, 0, 0, &excepts, &timeout);
8457416Smarkm    } while ((value == -1) && (errno == EINTR));
8557416Smarkm
8657416Smarkm    if (value < 0) {
8757416Smarkm	perror("select");
8857416Smarkm	quit();
8957416Smarkm	/* NOTREACHED */
9057416Smarkm    }
9157416Smarkm    if (FD_ISSET(net, &excepts)) {
9257416Smarkm	return 1;
9357416Smarkm    } else {
9457416Smarkm	return 0;
9557416Smarkm    }
9657416Smarkm}
9757416Smarkm
9857416Smarkm
9957416Smarkm/*
10057416Smarkm *  setneturg()
10157416Smarkm *
10257416Smarkm *	Sets "neturg" to the current location.
10357416Smarkm */
10457416Smarkm
10557416Smarkmvoid
10657416Smarkmsetneturg(void)
10757416Smarkm{
10857416Smarkm    ring_mark(&netoring);
10957416Smarkm}
11057416Smarkm
11157416Smarkm
11257416Smarkm/*
11357416Smarkm *  netflush
11457416Smarkm *		Send as much data as possible to the network,
11557416Smarkm *	handling requests for urgent data.
11657416Smarkm *
11757416Smarkm *		The return value indicates whether we did any
11857416Smarkm *	useful work.
11957416Smarkm */
12057416Smarkm
12157416Smarkm
12257416Smarkmint
12357416Smarkmnetflush(void)
12457416Smarkm{
12557416Smarkm    int n, n1;
12657416Smarkm
12757416Smarkm#if	defined(ENCRYPTION)
12857416Smarkm    if (encrypt_output)
12957416Smarkm	ring_encrypt(&netoring, encrypt_output);
13057416Smarkm#endif
13157416Smarkm    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
13257416Smarkm	if (!ring_at_mark(&netoring)) {
13357416Smarkm	    n = send(net, (char *)netoring.consume, n, 0); /* normal write */
13457416Smarkm	} else {
13557416Smarkm	    /*
13657416Smarkm	     * In 4.2 (and 4.3) systems, there is some question about
13757416Smarkm	     * what byte in a sendOOB operation is the "OOB" data.
13857416Smarkm	     * To make ourselves compatible, we only send ONE byte
13957416Smarkm	     * out of band, the one WE THINK should be OOB (though
14057416Smarkm	     * we really have more the TCP philosophy of urgent data
14157416Smarkm	     * rather than the Unix philosophy of OOB data).
14257416Smarkm	     */
14357416Smarkm	    n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
14457416Smarkm	}
14557416Smarkm    }
14657416Smarkm    if (n < 0) {
14757416Smarkm	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
14857416Smarkm	    setcommandmode();
14957416Smarkm	    perror(hostname);
15057416Smarkm	    NetClose(net);
15157416Smarkm	    ring_clear_mark(&netoring);
15257416Smarkm	    longjmp(peerdied, -1);
15357416Smarkm	    /*NOTREACHED*/
15457416Smarkm	}
15557416Smarkm	n = 0;
15657416Smarkm    }
15757416Smarkm    if (netdata && n) {
15857416Smarkm	Dump('>', netoring.consume, n);
15957416Smarkm    }
16057416Smarkm    if (n) {
16157416Smarkm	ring_consumed(&netoring, n);
16257416Smarkm	/*
16357416Smarkm	 * If we sent all, and more to send, then recurse to pick
16457416Smarkm	 * up the other half.
16557416Smarkm	 */
16657416Smarkm	if ((n1 == n) && ring_full_consecutive(&netoring)) {
16757416Smarkm	    netflush();
16857416Smarkm	}
16957416Smarkm	return 1;
17057416Smarkm    } else {
17157416Smarkm	return 0;
17257416Smarkm    }
17357416Smarkm}
174