129088Smarkm/*
229088Smarkm * Copyright (c) 1988, 1993
329088Smarkm *	The Regents of the University of California.  All rights reserved.
429088Smarkm *
529088Smarkm * Redistribution and use in source and binary forms, with or without
629088Smarkm * modification, are permitted provided that the following conditions
729088Smarkm * are met:
829088Smarkm * 1. Redistributions of source code must retain the above copyright
929088Smarkm *    notice, this list of conditions and the following disclaimer.
1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1129088Smarkm *    notice, this list of conditions and the following disclaimer in the
1229088Smarkm *    documentation and/or other materials provided with the distribution.
1329088Smarkm * 3. All advertising materials mentioning features or use of this software
1429088Smarkm *    must display the following acknowledgement:
1529088Smarkm *	This product includes software developed by the University of
1629088Smarkm *	California, Berkeley and its contributors.
1729088Smarkm * 4. Neither the name of the University nor the names of its contributors
1829088Smarkm *    may be used to endorse or promote products derived from this software
1929088Smarkm *    without specific prior written permission.
2029088Smarkm *
2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2429088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3129088Smarkm * SUCH DAMAGE.
3229088Smarkm */
3329088Smarkm
34114630Sobrien#if 0
3529088Smarkm#ifndef lint
3629181Smarkmstatic const char sccsid[] = "@(#)network.c	8.2 (Berkeley) 12/15/93";
3763248Speter#endif
38114630Sobrien#endif
39114630Sobrien#include <sys/cdefs.h>
40114630Sobrien__FBSDID("$FreeBSD$");
4129088Smarkm
4229088Smarkm#include <sys/types.h>
4329088Smarkm#include <sys/socket.h>
4429088Smarkm#include <sys/time.h>
4529088Smarkm
4629088Smarkm#include <errno.h>
4796385Salfred#include <stdlib.h>
4829088Smarkm
4929088Smarkm#include <arpa/telnet.h>
5029181Smarkm#include <unistd.h>
5129088Smarkm
5229088Smarkm#include "ring.h"
5329088Smarkm
5429088Smarkm#include "defines.h"
5529088Smarkm#include "externs.h"
5629088Smarkm#include "fdset.h"
5729088Smarkm
5829088SmarkmRing		netoring, netiring;
5929088Smarkmunsigned char	netobuf[2*BUFSIZ], netibuf[BUFSIZ];
6029088Smarkm
6129088Smarkm/*
6229088Smarkm * Initialize internal network data structures.
6329088Smarkm */
6429088Smarkm
6587139Smarkmvoid
6687139Smarkminit_network(void)
6729088Smarkm{
6829088Smarkm    if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
6929088Smarkm	exit(1);
7029088Smarkm    }
7129088Smarkm    if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
7229088Smarkm	exit(1);
7329088Smarkm    }
7429088Smarkm    NetTrace = stdout;
7529088Smarkm}
7629088Smarkm
7729088Smarkm
7829088Smarkm/*
7929088Smarkm * Check to see if any out-of-band data exists on a socket (for
8029088Smarkm * Telnet "synch" processing).
8129088Smarkm */
8229088Smarkm
8387139Smarkmint
8487139Smarkmstilloob(void)
8529088Smarkm{
8687139Smarkm    static struct timeval timeout = { 0, 0 };
8729088Smarkm    fd_set	excepts;
8829088Smarkm    int value;
8929088Smarkm
9029088Smarkm    do {
9129088Smarkm	FD_ZERO(&excepts);
9229088Smarkm	FD_SET(net, &excepts);
9329088Smarkm	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
9429088Smarkm    } while ((value == -1) && (errno == EINTR));
9529088Smarkm
9629088Smarkm    if (value < 0) {
9729088Smarkm	perror("select");
9829088Smarkm	(void) quit();
9929088Smarkm	/* NOTREACHED */
10029088Smarkm    }
10129088Smarkm    if (FD_ISSET(net, &excepts)) {
10229088Smarkm	return 1;
10329088Smarkm    } else {
10429088Smarkm	return 0;
10529088Smarkm    }
10629088Smarkm}
10729088Smarkm
10829088Smarkm
10929088Smarkm/*
11029088Smarkm *  setneturg()
11129088Smarkm *
11229088Smarkm *	Sets "neturg" to the current location.
11329088Smarkm */
11429088Smarkm
11587139Smarkmvoid
11687139Smarkmsetneturg(void)
11729088Smarkm{
11829088Smarkm    ring_mark(&netoring);
11929088Smarkm}
12029088Smarkm
12129088Smarkm
12229088Smarkm/*
12329088Smarkm *  netflush
12429088Smarkm *		Send as much data as possible to the network,
12529088Smarkm *	handling requests for urgent data.
12629088Smarkm *
12729088Smarkm *		The return value indicates whether we did any
12829088Smarkm *	useful work.
12929088Smarkm */
13029088Smarkm
13187139Smarkmint
13287139Smarkmnetflush(void)
13329088Smarkm{
13487139Smarkm    int n, n1;
13529088Smarkm
13629088Smarkm#ifdef	ENCRYPTION
13729088Smarkm    if (encrypt_output)
13829088Smarkm	ring_encrypt(&netoring, encrypt_output);
13929088Smarkm#endif	/* ENCRYPTION */
14029088Smarkm    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
14129088Smarkm	if (!ring_at_mark(&netoring)) {
14229088Smarkm	    n = send(net, (char *)netoring.consume, n, 0); /* normal write */
14329088Smarkm	} else {
14429088Smarkm	    /*
14529088Smarkm	     * In 4.2 (and 4.3) systems, there is some question about
14629088Smarkm	     * what byte in a sendOOB operation is the "OOB" data.
14729088Smarkm	     * To make ourselves compatible, we only send ONE byte
14829088Smarkm	     * out of band, the one WE THINK should be OOB (though
14929088Smarkm	     * we really have more the TCP philosophy of urgent data
15029088Smarkm	     * rather than the Unix philosophy of OOB data).
15129088Smarkm	     */
15229088Smarkm	    n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
15329088Smarkm	}
15429088Smarkm    }
15529088Smarkm    if (n < 0) {
15629088Smarkm	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
15729088Smarkm	    setcommandmode();
15829088Smarkm	    perror(hostname);
15929088Smarkm	    (void)NetClose(net);
16029088Smarkm	    ring_clear_mark(&netoring);
161207449Sjilles	    ExitString("Connection closed by foreign host.\n", 1);
16229088Smarkm	    /*NOTREACHED*/
16329088Smarkm	}
16429088Smarkm	n = 0;
16529088Smarkm    }
16629088Smarkm    if (netdata && n) {
16729088Smarkm	Dump('>', netoring.consume, n);
16829088Smarkm    }
16929088Smarkm    if (n) {
17029088Smarkm	ring_consumed(&netoring, n);
17129088Smarkm	/*
17229088Smarkm	 * If we sent all, and more to send, then recurse to pick
17329088Smarkm	 * up the other half.
17429088Smarkm	 */
17529088Smarkm	if ((n1 == n) && ring_full_consecutive(&netoring)) {
17629088Smarkm	    (void) netflush();
17729088Smarkm	}
17829088Smarkm	return 1;
17929088Smarkm    } else {
18029088Smarkm	return 0;
18129088Smarkm    }
18229088Smarkm}
183