network.c revision 29181
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
3429088Smarkm#ifndef lint
3529181Smarkmstatic const char sccsid[] = "@(#)network.c	8.2 (Berkeley) 12/15/93";
3629088Smarkm#endif /* not lint */
3729088Smarkm
3829088Smarkm#include <sys/types.h>
3929088Smarkm#include <sys/socket.h>
4029088Smarkm#include <sys/time.h>
4129088Smarkm
4229088Smarkm#include <errno.h>
4329088Smarkm
4429088Smarkm#include <arpa/telnet.h>
4529181Smarkm#include <unistd.h>
4629088Smarkm
4729088Smarkm#include "ring.h"
4829088Smarkm
4929088Smarkm#include "defines.h"
5029088Smarkm#include "externs.h"
5129088Smarkm#include "fdset.h"
5229088Smarkm
5329088SmarkmRing		netoring, netiring;
5429088Smarkmunsigned char	netobuf[2*BUFSIZ], netibuf[BUFSIZ];
5529088Smarkm
5629088Smarkm/*
5729088Smarkm * Initialize internal network data structures.
5829088Smarkm */
5929088Smarkm
6029088Smarkm    void
6129088Smarkminit_network()
6229088Smarkm{
6329088Smarkm    if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
6429088Smarkm	exit(1);
6529088Smarkm    }
6629088Smarkm    if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
6729088Smarkm	exit(1);
6829088Smarkm    }
6929088Smarkm    NetTrace = stdout;
7029088Smarkm}
7129088Smarkm
7229088Smarkm
7329088Smarkm/*
7429088Smarkm * Check to see if any out-of-band data exists on a socket (for
7529088Smarkm * Telnet "synch" processing).
7629088Smarkm */
7729088Smarkm
7829088Smarkm    int
7929088Smarkmstilloob()
8029088Smarkm{
8129088Smarkm    static struct timeval timeout = { 0 };
8229088Smarkm    fd_set	excepts;
8329088Smarkm    int value;
8429088Smarkm
8529088Smarkm    do {
8629088Smarkm	FD_ZERO(&excepts);
8729088Smarkm	FD_SET(net, &excepts);
8829088Smarkm	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
8929088Smarkm    } while ((value == -1) && (errno == EINTR));
9029088Smarkm
9129088Smarkm    if (value < 0) {
9229088Smarkm	perror("select");
9329088Smarkm	(void) quit();
9429088Smarkm	/* NOTREACHED */
9529088Smarkm    }
9629088Smarkm    if (FD_ISSET(net, &excepts)) {
9729088Smarkm	return 1;
9829088Smarkm    } else {
9929088Smarkm	return 0;
10029088Smarkm    }
10129088Smarkm}
10229088Smarkm
10329088Smarkm
10429088Smarkm/*
10529088Smarkm *  setneturg()
10629088Smarkm *
10729088Smarkm *	Sets "neturg" to the current location.
10829088Smarkm */
10929088Smarkm
11029088Smarkm    void
11129088Smarkmsetneturg()
11229088Smarkm{
11329088Smarkm    ring_mark(&netoring);
11429088Smarkm}
11529088Smarkm
11629088Smarkm
11729088Smarkm/*
11829088Smarkm *  netflush
11929088Smarkm *		Send as much data as possible to the network,
12029088Smarkm *	handling requests for urgent data.
12129088Smarkm *
12229088Smarkm *		The return value indicates whether we did any
12329088Smarkm *	useful work.
12429088Smarkm */
12529088Smarkm
12629088Smarkm
12729088Smarkm    int
12829088Smarkmnetflush()
12929088Smarkm{
13029088Smarkm    register int n, n1;
13129088Smarkm
13229088Smarkm#ifdef	ENCRYPTION
13329088Smarkm    if (encrypt_output)
13429088Smarkm	ring_encrypt(&netoring, encrypt_output);
13529088Smarkm#endif	/* ENCRYPTION */
13629088Smarkm    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
13729088Smarkm	if (!ring_at_mark(&netoring)) {
13829088Smarkm	    n = send(net, (char *)netoring.consume, n, 0); /* normal write */
13929088Smarkm	} else {
14029088Smarkm	    /*
14129088Smarkm	     * In 4.2 (and 4.3) systems, there is some question about
14229088Smarkm	     * what byte in a sendOOB operation is the "OOB" data.
14329088Smarkm	     * To make ourselves compatible, we only send ONE byte
14429088Smarkm	     * out of band, the one WE THINK should be OOB (though
14529088Smarkm	     * we really have more the TCP philosophy of urgent data
14629088Smarkm	     * rather than the Unix philosophy of OOB data).
14729088Smarkm	     */
14829088Smarkm	    n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
14929088Smarkm	}
15029088Smarkm    }
15129088Smarkm    if (n < 0) {
15229088Smarkm	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
15329088Smarkm	    setcommandmode();
15429088Smarkm	    perror(hostname);
15529088Smarkm	    (void)NetClose(net);
15629088Smarkm	    ring_clear_mark(&netoring);
15729088Smarkm	    longjmp(peerdied, -1);
15829088Smarkm	    /*NOTREACHED*/
15929088Smarkm	}
16029088Smarkm	n = 0;
16129088Smarkm    }
16229088Smarkm    if (netdata && n) {
16329088Smarkm	Dump('>', netoring.consume, n);
16429088Smarkm    }
16529088Smarkm    if (n) {
16629088Smarkm	ring_consumed(&netoring, n);
16729088Smarkm	/*
16829088Smarkm	 * If we sent all, and more to send, then recurse to pick
16929088Smarkm	 * up the other half.
17029088Smarkm	 */
17129088Smarkm	if ((n1 == n) && ring_full_consecutive(&netoring)) {
17229088Smarkm	    (void) netflush();
17329088Smarkm	}
17429088Smarkm	return 1;
17529088Smarkm    } else {
17629088Smarkm	return 0;
17729088Smarkm    }
17829088Smarkm}
179