network.c revision 63248
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
3563248Speter#if 0
3629181Smarkmstatic const char sccsid[] = "@(#)network.c	8.2 (Berkeley) 12/15/93";
3763248Speter#else
3863248Speterstatic const char rcsid[] =
3963248Speter "$FreeBSD: head/contrib/telnet/telnet/network.c 63248 2000-07-16 05:48:49Z peter $";
4063248Speter#endif
4129088Smarkm#endif /* not lint */
4229088Smarkm
4329088Smarkm#include <sys/types.h>
4429088Smarkm#include <sys/socket.h>
4529088Smarkm#include <sys/time.h>
4629088Smarkm
4729088Smarkm#include <errno.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
6529088Smarkm    void
6629088Smarkminit_network()
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
8329088Smarkm    int
8429088Smarkmstilloob()
8529088Smarkm{
8629088Smarkm    static struct timeval timeout = { 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
11529088Smarkm    void
11629088Smarkmsetneturg()
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
13129088Smarkm
13229088Smarkm    int
13329088Smarkmnetflush()
13429088Smarkm{
13529088Smarkm    register int n, n1;
13629088Smarkm
13729088Smarkm#ifdef	ENCRYPTION
13829088Smarkm    if (encrypt_output)
13929088Smarkm	ring_encrypt(&netoring, encrypt_output);
14029088Smarkm#endif	/* ENCRYPTION */
14129088Smarkm    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
14229088Smarkm	if (!ring_at_mark(&netoring)) {
14329088Smarkm	    n = send(net, (char *)netoring.consume, n, 0); /* normal write */
14429088Smarkm	} else {
14529088Smarkm	    /*
14629088Smarkm	     * In 4.2 (and 4.3) systems, there is some question about
14729088Smarkm	     * what byte in a sendOOB operation is the "OOB" data.
14829088Smarkm	     * To make ourselves compatible, we only send ONE byte
14929088Smarkm	     * out of band, the one WE THINK should be OOB (though
15029088Smarkm	     * we really have more the TCP philosophy of urgent data
15129088Smarkm	     * rather than the Unix philosophy of OOB data).
15229088Smarkm	     */
15329088Smarkm	    n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
15429088Smarkm	}
15529088Smarkm    }
15629088Smarkm    if (n < 0) {
15729088Smarkm	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
15829088Smarkm	    setcommandmode();
15929088Smarkm	    perror(hostname);
16029088Smarkm	    (void)NetClose(net);
16129088Smarkm	    ring_clear_mark(&netoring);
16229088Smarkm	    longjmp(peerdied, -1);
16329088Smarkm	    /*NOTREACHED*/
16429088Smarkm	}
16529088Smarkm	n = 0;
16629088Smarkm    }
16729088Smarkm    if (netdata && n) {
16829088Smarkm	Dump('>', netoring.consume, n);
16929088Smarkm    }
17029088Smarkm    if (n) {
17129088Smarkm	ring_consumed(&netoring, n);
17229088Smarkm	/*
17329088Smarkm	 * If we sent all, and more to send, then recurse to pick
17429088Smarkm	 * up the other half.
17529088Smarkm	 */
17629088Smarkm	if ((n1 == n) && ring_full_consecutive(&netoring)) {
17729088Smarkm	    (void) netflush();
17829088Smarkm	}
17929088Smarkm	return 1;
18029088Smarkm    } else {
18129088Smarkm	return 0;
18229088Smarkm    }
18329088Smarkm}
184