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