This commit (temporarily) leaves MINIX 3 without a TCP/IP service.
Thanks go out to Philip Homburg for providing this TCP/IP stack in the
first place. It has served MINIX well for a long time.
Change-Id: I0e3eb6fe64204081e4e3c2b9d6e6bd642f121973
./etc/gettytab minix-base
./etc/group minix-base
./etc/hostname.file minix-base
-./etc/inet.conf minix-base
+./etc/inet.conf minix-base obsolete
./etc/kyua minix-tests kyua
./etc/man.conf minix-base
./etc/master.passwd minix-base
./etc/rc.d/syslogd minix-base
./etc/rc.d/ttys minix-base
./etc/rc.d/wscons minix-base
-./etc/rc.daemons.dist minix-base
+./etc/rc.daemons.dist minix-base obsolete
./etc/rc.minix minix-base
./etc/rc.shutdown minix-base
./etc/rc.subr minix-base
./etc/release minix-base
./etc/resolv.conf minix-base
-./etc/rs.inet minix-base
+./etc/rs.inet minix-base obsolete
./etc/rs.single minix-base
./etc/saslc.d minix-base crypto
./etc/saslc.d/postfix minix-base crypto
./etc/system.conf minix-base
./etc/system.conf.d minix-base
./etc/system.conf.d/hello minix-base
-./etc/system.conf.d/inet minix-base
+./etc/system.conf.d/inet minix-base obsolete
./etc/system.conf.d/ipc minix-base
./etc/system.conf.d/lwip minix-base obsolete
./etc/system.conf.d/random minix-base
./service/ds minix-base
./service/ext2 minix-base
./service/hello minix-base
-./service/inet minix-base
+./service/inet minix-base obsolete
./service/input minix-base
./service/ipc minix-base
./service/is minix-base
./usr/include/minix/priv.h minix-comp
./usr/include/minix/procfs.h minix-comp
./usr/include/minix/profile.h minix-comp
-./usr/include/minix/queryparam.h minix-comp
+./usr/include/minix/queryparam.h minix-comp obsolete
./usr/include/minix/rmib.h minix-comp
./usr/include/minix/rs.h minix-comp
./usr/include/minix/safecopies.h minix-comp
./usr/libdata/debug/service/ds.debug minix-debug debug
./usr/libdata/debug/service/ext2.debug minix-debug debug
./usr/libdata/debug/service/hello.debug minix-debug debug
-./usr/libdata/debug/service/inet.debug minix-debug debug
+./usr/libdata/debug/service/inet.debug minix-debug debug,obsolete
./usr/libdata/debug/service/input.debug minix-debug debug
./usr/libdata/debug/service/ipc.debug minix-debug debug
./usr/libdata/debug/service/is.debug minix-debug debug
./usr/man/man4/disk.4 minix-man
./usr/man/man4/dosfile.4 minix-man
./usr/man/man4/esdi.4 minix-man
-./usr/man/man4/eth.4 minix-man
+./usr/man/man4/eth.4 minix-man obsolete
./usr/man/man4/fd.4 minix-man
-./usr/man/man4/ip.4 minix-man
+./usr/man/man4/ip.4 minix-man obsolete
./usr/man/man4/keyboard.4 minix-man
./usr/man/man4/lp.4 minix-man
./usr/man/man4/mtio.4 minix-man
./usr/man/man4/ncr810.4 minix-man
-./usr/man/man4/psip.4 minix-man
+./usr/man/man4/psip.4 minix-man obsolete
./usr/man/man4/tape.4 minix-man
./usr/man/man4/tty.4 minix-man
-./usr/man/man4/udp.4 minix-man
+./usr/man/man4/udp.4 minix-man obsolete
./usr/man/man4/uds.4 minix-man obsolete
./usr/man/man5 minix-man
./usr/man/man5/TZ.5 minix-man
./usr/man/man8/i2cscan.8 minix-man
./usr/man/man8/ifconfig.8 minix-man
./usr/man/man8/in.httpd.8 minix-man obsolete
-./usr/man/man8/inet.8 minix-man
+./usr/man/man8/inet.8 minix-man obsolete
./usr/man/man8/init.8 minix-man
./usr/man/man8/installboot_nbsd.8 minix-man
./usr/man/man8/intr.8 minix-man
rc.shutdown services shells \
syslog.conf
# MINIX-only files:
-BIN1+= boot.cfg.default rc.daemons.dist rc.minix \
- rs.inet rs.single termcap utmp
+BIN1+= boot.cfg.default rc.minix \
+ rs.single termcap utmp
.else
BIN1+= bootptab changelist csh.cshrc csh.login \
csh.logout daily daily.conf dm.conf envsys.conf floppytab ftpchroot \
.for owner group mode sdir tdir files in \
${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ group \
${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ hostname.file \
- ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ inet.conf \
${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ mk.conf \
${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ resolv.conf \
${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ motd \
+++ /dev/null
-daemonize talkd
-daemonize tcpd shell /usr/libexec/rshd
-daemonize tcpd telnet in.telnetd
-daemonize tcpd ftp /usr/libexec/ftpd
-daemonize tcpd finger /usr/libexec/fingerd
+++ /dev/null
-#!/bin/sh
-
-# Recovery script for INET. It restarts daemons dependent on it in order
-# to recover TCP state.
-
-kill_by_name()
-{
- label="$1"
- pid=`ps ax | grep "$label" | grep -v grep | sed 's,[ ]*\([0-9]*\).*,\1,'`
- if [ X"$pid" = X ]
- then
- return 1 # No such process
- fi
- echo "killing pid $pid for $label"
- kill -9 $pid
-}
-
-daemonize()
-{
- # Function to start a daemon, if it exists.
- local IFS=':'
- local name="$1"
- test "$1" = tcpd && name="$2"
-
- for dir in $PATH
- do
- if [ -f "$dir/$1" ]
- then
-
- # check if this service is disabled at the boot monitor.
- if disabled $name; then return; fi
-
- echo -n " $name"
- "$@" &
- return
- fi
- done
-}
-
-disabled()
-{
- ifs="$IFS"; IFS=,
- for skip in `sysenv disable`
- do
- if [ "$skip" = "$1" ]
- then
- IFS="$ifs"; unset ifs
- return 0
- fi
- done
- IFS="$ifs"; unset ifs
- return 1
-}
-
-exec > /dev/console
-echo "Arguments: $@"
-
-restarts=$(grep restarts /proc/service/$1 |cut -d: -f2)
-restarts=$(( $restarts + 1 ))
-minix-service down "$1"
-kill_by_name dhcpd
-kill_by_name nonamed
-kill_by_name syslogd
-
-# Wait a moment to let daemons clean themselves up
-sleep 3
-minix-service up /service/inet -script /etc/rs.inet -dev /dev/ip -restarts $restarts
-daemonize dhcpd
-daemonize nonamed -L
-daemonize syslogd
-
-# Restart SSH daemon if installed and running
-if [ -f /usr/pkg/etc/rc.d/sshd ]
-then
- /usr/pkg/etc/rc.d/sshd status | grep -v not > /dev/null
- if [ $? -eq 0 ]
- then
- /usr/pkg/etc/rc.d/sshd restart
- fi
-fi
}
get_eth_labels() {
- # Filter out the non-vlan ethernet entries from inet.conf.
- # Produce as output a list of "drivername_instancenr"-formatted labels.
- sed 's/\008/ /g' /etc/inet.conf | \
- sed -n 's/^ *eth[0-9][0-9]* *\([^ ][^ ]*\) *\([0-9][0-9]*\).*$/\1_\2/p' | \
- grep -v '^vlan_'
+ # Nothing yet.
}
# Detect expansion boards on the BeagleBone and load the proper drivers.
done
}
-DAEMONS=/etc/rc.daemons
-
case $action in
start)
# Select console font.
eval up $driver -label $label $arg -period 5HZ
done
- up inet -script /etc/rs.inet -dev /dev/ip
-
# pty needs to know the "tty" group ID
up pty -dev /dev/ptmx -args "gid=`stat -f '%g' /dev/ptmx`"
echo .
- # Network initialization.
- (: </dev/tcp) 2>/dev/null && net=t # Is there a TCP/IP server?
-
echo -n "Starting daemons:"
daemonize update
echo .
fi
- if [ "$net" ]
- then
- if [ -f /etc/rc.net ]
- then
- # Let a customized TCP/IP initialization script figure it out.
- . /etc/rc.net
- else
- # Standard network daemons.
- echo -n "Starting networking:"
- if grep -s 'psip0.*default' /etc/inet.conf >/dev/null
- then ifconfig -h 10.0.0.1
- else
- daemonize dhcpd
- fi
- daemonize nonamed -L
- if [ -f "$DAEMONS" ]
- then . "$DAEMONS"
- fi
- # The last daemon has been started, so close the list:
- echo .
- fi
- fi
-
- if [ "$net" ]
- then
- # Get the nodename from the DNS and set it.
- trap '' 2
- intr -t 20 hostaddr -h
- trap 2
- fi
-
# Load the stored hostname into the sysctl database.
test -r /etc/hostname.file && hostname $(cat /etc/hostname.file)
;;
6,0) des="line printer, parallel port" dev=lp
;;
- 7,*)
- d=`expr $minor % 8`
- n=`expr $minor / 8`
- case $d in
- 0) des="IP stat" dev=ipstat
- ;;
- 1) case $name in
- psip*)
- des="Pseudo IP #$n" dev=psip
- ;;
- *) des="raw ethernet #$n" dev=eth
- esac
- ;;
- 2) des="raw IP #$n" dev=ip
- ;;
- 3) des="TCP/IP #$n" dev=tcp
- ;;
- 4) des="UDP #$n" dev=udp
- esac
- case $d in
- [0123])
- if [ "$name" = "$dev" ]
- then
- des="$des (default)"
- else
- dev=$dev$n
- fi
- esac
- ;;
9,0)
des="unix98 pseudoterminal master" dev=ptmx
;;
ttyc1 ttyc2 ttyc3 tty00 tty01 tty02 tty03
"
-#eth => ip tcp udp
STD_DEVICES="
${RAMDISK_DEVICES}
bmp085b1s77 bmp085b2s77 bmp085b3s77
eepromb2s54 eepromb2s55 eepromb2s56 eepromb2s57
eepromb3s50 eepromb3s51 eepromb3s52 eepromb3s53
eepromb3s54 eepromb3s55 eepromb3s56 eepromb3s57
- eth fb0 fbd filter hello
+ fb0 fbd filter hello
i2c-1 i2c-2 i2c-3
klog ptmx random
sht21b1s40 sht21b2s40 sht21b3s40
ttyc1 ... ttyc7 # Virtual consoles
tty00 ... tty03 # Make serial lines
ttyp0 ... ttyq0 ... # Make tty, pty pairs
- eth ip tcp udp # One of these makes some TCP/IP devices
audio mixer # Make audio devices
klog # Make /dev/klog
ptmx # Make /dev/ptmx
makedev eepromb${bus}s5${slave_low} b ${major} 0 ${uname} ${gname} ${permissions}
;;
- eth|ip|tcp|udp|eth0|ip0|tcp0|udp0)
- # TCP/IP devices.
- makedev ipstat c 7 0 ${uname} ${gname} 666
- makedev eth0 c 7 1 ${uname} ${gname} ${permissions}
- makedev ip0 c 7 2 ${uname} ${gname} ${permissions}
- makedev tcp0 c 7 3 ${uname} ${gname} 666
- makedev udp0 c 7 4 ${uname} ${gname} 666
-
- # Default interface
- makedev eth c 7 1 ${uname} ${gname} ${permissions}
- makedev ip c 7 2 ${uname} ${gname} ${permissions}
- makedev tcp c 7 3 ${uname} ${gname} 666
- makedev udp c 7 4 ${uname} ${gname} 666
- ;;
fb0)
# Framebuffer driver
makedev ${dev} c 19 0 ${uname} ${gname} 644
{ .label = "ptyfs", .policy_str = "" },
{ .label = "vbfs", .policy_str = "" },
/* net */
- { .label = "inet", .policy_str = "reset" },
{ .label = "lwip", .policy_str = "" },
/* servers */
{ .label = "devman", .policy_str = "restart" },
inputdriver.h ipc.h ipc_filter.h ipcconst.h \
keymap.h log.h mmio.h mthread.h minlib.h \
netdriver.h optset.h padconf.h partition.h portio.h \
- priv.h procfs.h profile.h queryparam.h \
+ priv.h procfs.h profile.h \
rmib.h rs.h safecopies.h sched.h sef.h sffs.h \
sockdriver.h sockevent.h sound.h spin.h \
sys_config.h sysctl.h sysinfo.h \
#define TTY_MAJOR 4 /* 4 = /dev/tty00 (ttys) */
#define CTTY_MAJOR 5 /* 5 = /dev/tty */
#define PRINTER_MAJOR 6 /* 6 = /dev/lp (printer driver) */
-#define INET_MAJOR 7 /* 7 = /dev/ip (inet) */
+ /* 7 = (unused) */
/* 8 = /dev/c1 */
#define PTY_MAJOR 9 /* 9 = /dev/ptyp0 (pty driver) */
/* 10 = /dev/c2 */
+++ /dev/null
-/* queryparam.h - query program parameters Author: Kees J. Bot
- * 22 Apr 1994
- */
-#ifndef _MINIX__QUERYPARAM_H
-#define _MINIX__QUERYPARAM_H
-
-
-typedef size_t _mnx_size_t;
-
-struct export_param_list {
- char *name; /* "variable", "[", ".field", or NULL. */
- void *offset; /* Address of a variable or field offset. */
- size_t size; /* Size of the resulting object. */
-};
-
-struct export_params {
- struct export_param_list *list; /* List of exported parameters. */
- struct export_params *next; /* Link several sets of parameters. */
-};
-
-#ifdef __STDC__
-#define qp_stringize(var) #var
-#define qp_dotstringize(var) "." #var
-#else
-#define qp_stringize(var) "var"
-#define qp_dotstringize(var) ".var"
-#endif
-#define QP_VARIABLE(var) { qp_stringize(var), &(var), sizeof(var) }
-#define QP_ARRAY(var) { "[", 0, sizeof((var)[0]) }
-#define QP_VECTOR(var,ptr,len) { qp_stringize(var), &(ptr), -1 },\
- { "[", &(len), sizeof(*(ptr)) }
-#define QP_FIELD(field, type) { qp_dotstringize(field), \
- (void *)offsetof(type, field), \
- sizeof(((type *)0)->field) }
-#define QP_END() { 0, 0, 0 }
-
-void qp_export(struct export_params *_ex_params);
-int queryparam(int (*_qgetc) (void), void **_paddress, _mnx_size_t
- *_psize);
-#endif /* _MINIX__QUERYPARAM_H */
-
-/* $PchId: queryparam.h,v 1.1 2005/06/28 14:31:26 philip Exp $ */
#define DEBUG_DUMPIPCF 0
/* If defined, restrict DEBUG_DUMPIPC to particular process names */
-/* #define DEBUG_DUMPIPC_NAMES { "tty", "inet" } */
+/* #define DEBUG_DUMPIPC_NAMES { "tty", "pty" } */
/* DEBUG_IPCSTATS collects information on who sends messages to whom. */
#define DEBUG_IPCSTATS 0
, for reading, writing, or exceptional conditions, respectively.
.B Select
currently supports regular files, pipes, named pipes,
-inet, and tty file descriptors (including pty).
+sockets, and character devices.
If the
.I readfds
.BR shutdown(2),
.BR getsockopt(2),
.BR setsockopt(2),
-.BR ip(4),
-.BR inet(8),
.BR unix(8)
-MAN= console.4 controller.4 dev.4 fd.4 ip.4 lp.4 mtio.4 tty.4
+MAN= console.4 controller.4 dev.4 fd.4 lp.4 mtio.4 tty.4
MLINKS += console.4 keyboard.4
MLINKS += controller.4 disk.4
MLINKS += controller.4 aha1540.4
MLINKS += controller.4 ncr810.4
MLINKS += controller.4 dosfile.4
-MLINKS += ip.4 eth.4
-MLINKS += ip.4 psip.4
-MLINKS += ip.4 udp.4
.include <bsd.man.mk>
device sends any bytes written to it to the printer.
.SS "TCP/IP (major 7)"
The TCP/IP task is not a kernel task, but a server like PM and VFS. It sits
-between VFS and the DP8390 task that manages the ethernet boards. Together
-they implement the TCP/IP protocol. See also
-.BR ip (4).
+between VFS and the drivers that manage the ethernet boards. Together
+they implement the TCP/IP protocol.
.SS "Controller 1 (major 8)"
Like controller 0 (major 3), but managing a second controller with devices
.BR /dev/c1* .
.BR console (4),
.BR fd (4),
.BR controller (4),
-.BR ip (4),
.BR uds (4),
.BR tty (4),
.BR MAKEDEV (8).
There are five prominent errors that processes accessing device files may
provoke:
.IP "ENODEV \- No such device" 5
-There is no driver managing the device class this device belongs to. Either
-the driver is configured out, or it is not loaded (inet).
+There is no driver managing the device class this device belongs to, typically
+because it is not loaded.
.IP "ENXIO \- No such device or address"
This device is not available. Either the driver does not support it at all,
or the hardware isn't available, i.e. accessing the second disk on a system
+++ /dev/null
-.\"
-.\" Copyright 1994 Vrije Universiteit, The Netherlands.
-.\" For full copyright and restrictions on use see the file COPYRIGHT in the
-.\" top level of the Amoeba distribution.
-.\"
-.ig
- Software: Philip Homburg, 1991
- Document: Philip Homburg, Sept 3, 1991
- Modified: Greg Sharp and Philip Homburg, March 1992
- - merged with udp(L) and made a little more complete.
- Greg Sharp, April 1992
- - updated keywords for auto index generation
- Modified: Kees J. Bot, June 1994
- - changed to man(7) format for MINIX 3.
-..
-.TH IP 4
-.SH NAME
-ip, eth, psip, udp, tcp \- Internet Protocol server devices and definitions
-.SH DESCRIPTION
-.de SP
-.if t .sp 0.4
-.if n .sp
-..
-The
-.BR ip* ,
-.BR eth* ,
-.BR psip* ,
-.BR tcp* ,
-and
-.B udp*
-devices give access to the Internet Protocol (IP) services in MINIX 3.
-There can be up to 16 different networks, with 4 network devices each
-(a network has either an
-.B eth*
-or a
-.B psip*
-device, not both.)
-The
-.B *
-in the device names is a decimal number, so one may see names from
-.B ip0
-to
-.BR ip15 .
-A program scanning all networks must try all 16, and not stop if one in
-between is missing. One network is the default network. Its devices are
-linked to names without numbers.
-.PP
-The
-.B eth*
-and
-.B psip*
-devices give direct access to the network packets at the lowest level.
-The
-.BR ip* ,
-.BR tcp* ,
-and
-.B udp*
-devices give access to IP, TCP, or UDP services.
-.PP
-Most programs that use TCP/IP use code like the following to access the
-proper devices:
-.PP
-.RS
-.nf
-if ((tcp_device= getenv("TCP_DEVICE")) == NULL)
- tcp_device= "/dev/tcp";
-.fi
-.RE
-.PP
-The low level networking programs such as
-.BR ifconfig (8)
-also have options to select the device they are working with. The
-convention is:
-.PP
-.RS
-.BI ETH_DEVICE= device
-.br
-.BI -E " device"
-.RS
-Device to use as raw ethernet device instead of the default /dev/eth.
-.RE
-.SP
-.BI PSIP_DEVICE= device
-.br
-.BI -P " device"
-.RS
-Pseudo IP device to use instead of
-.BR /dev/psip .
-.RE
-.SP
-.BI IP_DEVICE= device
-.br
-.BI -I " device"
-.RS
-IP device to use instead of
-.BR /dev/ip .
-.RE
-.SP
-.BI TCP_DEVICE= device
-.br
-.BI -T " device"
-.RS
-TCP device to use instead of
-.BR /dev/tcp .
-.RE
-.SP
-.BI UDP_DEVICE= device
-.br
-.BI -U " device"
-.RS
-UDP device to use instead of
-.BR /dev/udp .
-.RE
-.RE
-.SS Programming
-Access to the IP services is provided using filedescriptors to open IP
-devices. These open IP channels can be configured with
-.BR ioctl (2)
-calls, and data can be transferred by calls to
-.BR read (2),
-and
-.BR write (2).
-.SS "Types (general)"
-.IP <sys/types.h>
-.br
-Defines
-.BR u8_t ,
-.BR u16_t ,
-.B u32_t
-and
-.B i32_t
-(and
-.BR U8_t ,
-.BR U16_t ,
-.B U32_t
-and
-.B I32_t
-for use in prototypes).
-.SS "Types (eth)"
-.IP <net/gen/ether.h>
-.br
-Defines struct ether_addr (\fBether_addr_t\fP) and
-.B ether_type_t
-and
-.B Ether_type_t
-for use in prototypes.
-.IP <net/gen/eth_io.h>
-.br
-Defines struct nwio_ethopt (\fBnwio_ethopt_t\fP) and
-struct nwio_ethstat (\fBnwio_ethstat_t\fP)
-.IP <net/gen/eth_hdr.h>
-.br
-Defines struct eth_hdr (\fBeth_hdr_t\fP)
-.SS "Types (psip)"
-.IP <net/gen/psip_hdr.h>
-.br
-[[[No description available yet.]]]
-.IP <net/gen/psip_io.h>
-.br
-[[[No description available yet.]]]
-.SS "Types (ip)"
-.IP <net/gen/in.h>
-.br
-Defines
-.BR ipaddr_t ,
-.BR ipproto_t
-and struct ip_hdropt (\fBip_hdropt_t\fP).
-.IP <net/gen/ip_io.h>
-.br
-Defines struct nwio_ipconf (\fBnwio_ipconf_t\fP) and
-struct nwio_ipopt (\fBnwio_ipopt_t\fP)
-.IP <net/gen/ip_hdr.h>
-.br
-Defines struct ip_hdr (\fBip_hdr_t\fP)
-.IP <net/gen/route.h>
-.br
-Defines struct nwio_route (\fBnwio_route_t\fP)
-.SS "Types (tcp)"
-.IP <net/gen/tcp.h>
-.br
-Defines
-.B tcpport_t
-and
-.B Tcpport_t
-for use in prototypes.
-.IP <net/gen/tcp_io.h>
-.br
-Defines struct nwio_tcpconf (\fBnwio_tcpconf_t\fP),
-struct nwio_tcpcl (\fBnwio_tcpcl_t\fP),
-struct nwio_tcpatt (\fBnwio_tcpatt_t\fP) and
-struct nwio_tcpopt (\fBnwio_tcpopt_t\fP).
-.IP <net/gen/tcp_hdr.h>
-.br
-Defines struct tcp_hdr (\fBtcp_hdr_t\fP) and struct tcp_hdropt
-(\fBtcp_hdropt_t\fP).
-.SS "Types (udp)"
-.IP <net/gen/udp.h>
-.br
-Defines
-.B udpport_t
-and
-.B Udpport_t
-for use in prototypes.
-.IP <net/gen/udp_io.h>
-.br
-Defines struct nwio_udpopt (\fBnwio_udpopt_t\fP).
-.IP <net/gen/udp_hdr.h>
-.br
-Defines struct udp_hdr (\fBudp_hdr_t\fP) and struct udp_io_hdr
-(\fBudp_io_hdr_t\fP).
-.SS "Byte Order Conversion"
-All 16-bit and 32-bit quantities in IP headers must be in network byte
-order. The macros described in
-.BR hton (3)
-can be used to convert these values to and from the byte order used by
-the host machine.
-.SS "The Internet Checksum"
-The
-.B oneC_sum
-function (see
-.BR oneC_sum (3))
-is used to calculate the one's complement checksum needed for IP network
-packets.
-.SS "General Functions"
-.PP
-.ft B
-\fIfd\fP = open(\fItcpip_device\fP, O_RDWR)
-.ft R
-.PP
-This is how one normally obtains a filedescriptor for a new TCP/IP channel.
-.I tcpip_device
-names one of the TCP/IP devices. The channel may be used both to send or to
-receive data.
-.PP
-.ft B
-\fIn\fP = read(\fIfd\fP, \fIbuf\fP, \fIsize\fP)
-.ft R
-.PP
-Receives one packet (low level devices) or a number of bytes (TCP stream).
-Returns the the number of bytes placed into
-.IR buf ,
-or returns -1 with an error code placed into
-.BR errno .
-.PP
-.ft B
-\fIn\fP = write(\fIfd\fP, \fIbuf\fP, \fIsize\fP)
-.ft R
-.PP
-Sends one packet (low level devices) or a number of bytes (TCP stream).
-Returns
-.I size
-or -1 with the error code placed into
-.BR errno .
-The TCP/IP
-.B read
-and
-.B write
-functions behave like reads and writes on pipes when it comes to signals.
-.SS "ETH Functions"
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGETHSTAT, &struct nwio_ethstat)
-.ft R
-.PP
-The
-.B NWIOGETHSTAT
-ioctl
-returns the Ethernet address and some statistics of the Ethernet server of
-the channel
-.IR fd .
-The result is returned in the nwio_ethstat structure.
-The \fBstruct nwio_ethstat\fP is defined in <net/gen/eth_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_ethstat
-{
- ether_addr_t nwes_addr;
- eth_stat_t nwes_stat;
-} nwio_ethstat_t;
-.SP
-typedef struct eth_stat
-{
- unsigned long ets_recvErr, /* # receive errors */
- ets_sendErr, /* # send error */
- ets_OVW, /* # buffer overwrite warnings,
- (packets arrive faster than
- can be processed) */
- ets_CRCerr, /* # crc errors of read */
- ets_frameAll, /* # frames not aligned (# bits
- not a multiple of 8) */
- ets_missedP, /* # packets missed due to too
- slow packet processing */
- ets_packetR, /* # packets received */
- ets_packetT, /* # packets transmitted */
- ets_transDef, /* # transmission deferred (there
- was a transmission of an
- other station in progress */
- ets_collision, /* # collisions */
- ets_transAb, /* # transmissions aborted due
- to excessive collisions */
- ets_carrSense, /* # carrier sense lost */
- ets_fifoUnder, /* # fifo underruns (processor
- is too busy) */
- ets_fifoOver, /* # fifo overruns (processor is
- too busy) */
- ets_CDheartbeat, /* # times unable to transmit
- collision signal */
- ets_OWC; /* # times out of window
- collision */
-} eth_stat_t;
-.if t .ft R
-.fi
-.RE
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSETHOPT, &struct nwio_ethopt)
-.ft R
-.PP
-Before an Ethernet channel can be used to send or receive
-Ethernet packets, it has to be configured using the
-.B NWIOSETHOPT
-ioctl.
-The structure
-.B nwio_ethopt
-is defined in <net/gen/eth_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_ethopt
-{
- u32_t nweo_flags;
- ether_addr_t nweo_multi, nweo_rem;
- ether_type_t nweo_type;
-} nwio_ethopt_t;
-.SP
-#define NWEO_NOFLAGS 0x0000L
-#define NWEO_ACC_MASK 0x0003L
-# define NWEO_EXCL 0x00000001L
-# define NWEO_SHARED 0x00000002L
-# define NWEO_COPY 0x00000003L
-#define NWEO_LOC_MASK 0x0010L
-# define NWEO_EN_LOC 0x00000010L
-# define NWEO_DI_LOC 0x00100000L
-#define NWEO_BROAD_MASK 0x0020L
-# define NWEO_EN_BROAD 0x00000020L
-# define NWEO_DI_BROAD 0x00200000L
-#define NWEO_MULTI_MASK 0x0040L
-# define NWEO_EN_MULTI 0x00000040L
-# define NWEO_DI_MULTI 0x00400000L
-#define NWEO_PROMISC_MASK 0x0080L
-# define NWEO_EN_PROMISC 0x00000080L
-# define NWEO_DI_PROMISC 0x00800000L
-#define NWEO_REM_MASK 0x0100L
-# define NWEO_REMSPEC 0x00000100L
-# define NWEO_REMANY 0x01000000L
-#define NWEO_TYPE_MASK 0x0200L
-# define NWEO_TYPESPEC 0x00000200L
-# define NWEO_TYPEANY 0x02000000L
-#define NWEO_RW_MASK 0x1000L
-# define NWEO_RWDATONLY 0x00001000L
-# define NWEO_RWDATALL 0x10000000L
-.if t .ft R
-.fi
-.RE
-.PP
-The configuration is divided in a number of section (covered by the xx_MASK
-macros).
-Options can be set in the
-.B nweo_flags
-field.
-The first section (\fBNWEO_ACC_MASK\fP) controls the access to a certain
-Ethernet packet type.
-If
-.B NWEO_EXCL
-is selected then this is the only channel that can send or
-receive Ethernet packets of the selected type.
-If
-.B NWEO_SHARED
-is selected then multiple channels (which all have to
-select
-.BR NWEO_SHARED )
-can use the same Ethernet type, they all can send
-packets but incoming packets will be delivered to at most one of them.
-If
-.B NWEO_COPY
-is selected then multiple channels have access to the same
-Ethernet type and all receive a copy of an incoming packet.
-.LP
-The
-.B NWEO_LOC_MASK
-flags control the delivery of packets with a destination
-address equal to the Ethernet address of the machine.
-If
-.B NWEO_EN_LOC
-is selected then these packets will be delivered and with
-.B NWEO_DI_LOC
-they will be discarded.
-.PP
-.BR NWEO_BROAD_MASK ,
-.BR NWEO_MULTI_MASK ,
-and
-.B NWEO_PROMISC_MASK
-do the same to broadcast packets,
-multicast packets and promiscuous mode packets as
-.B NWEO_LOC_MASK
-does for local packets.
-Except that the precise multicast address is taken from the \fBnweo_multi\fP
-field.
-.LP
-The
-.B NWEO_REM_MASK
-flags control whether communication is restricted to
-single destination or not.
-.B NWEO_REMSPEC
-restricts sending and receiving of packets to the single
-remote computer specified in the \fBnweo_rem\fP field.
-.B NWEO_REMANY
-allows sending to and receiving from any remote computer.
-.PP
-.B NWEO_TYPESPEC
-restricts sending and receiving of packets to the type
-specified in \fBnweo_type\fP.
-The type has to be in network byte order (using
-.BR hton (3)).
-.B NWEO_TYPEANY
-allows any type.
-.PP
-If the Ethernet header is completely specified by the
-.B nweo_flags
-i.e., all of
-.BR NWEO_EN_LOC ,
-.BR NWEO_DI_BROAD ,
-.BR NWEO_DI_MULTI ,
-.BR NWEO_DI_PROMISC ,
-.BR NWEO_REMSPEC
-and
-.B NWEO_TYPESPEC
-are
-specified, then
-.B NWEO_RWDATONLY
-can be used to send and receive only the data part of an Ethernet packet.
-If
-.B NWEO_RWDATALL
-is specified then both Ethernet header and data are used.
-.SS "PSIP Functions"
-.PP
-[[[No description available yet.]]]
-.SS "IP Functions"
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGIPCONF, &struct nwio_ipconf)
-.ft R
-.PP
-The
-.B NWIOGIPCONF
-ioctl reports the Internet Address and the netmask.
-For the \fInwio_ipconf\fP structure see the \fBNWIOSIPCONF\fP ioctl below.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGIPOROUTE, &struct nwio_route)
-.ft R
-.PP
-The
-.B NWIOGIPOROUTE
-ioctl can be used to query an IP server about its routing table.
-[[[NWIODIPOROUTE, NWIOGIPIROUTE, NWIODIPIROUTE?]]]
-The structure \fBnwio_route\fP is defined in <net/gen/route.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_route
-{
- u32_t nwr_ent_no;
- u32_t nwr_ent_count;
- ipaddr_t nwr_dest;
- ipaddr_t nwr_netmask;
- ipaddr_t nwr_gateway;
- u32_t nwr_dist;
- u32_t nwr_flags;
- u32_t nwr_pref;
-} nwio_route_t;
-.SP
-#define NWRF_EMPTY 0
-#define NWRF_INUSE 1
-#define NWRF_FIXED 2
-.if t .ft R
-.fi
-.RE
-.PP
-The requested entry is taken from \fBnwr_ent_no\fP.
-Entries are counted from 0, so the value 0 can be used for an initial query.
-The size of the routing table is returned in \fBnwr_ent_count\fP.
-The \fBnwr_flags\fP indicates if the entry is in use (\fBNWRF_INUSE\fP) and
-if the entry was inserted manually (using \fBNWIOSIPOROUTE\fP) or generated
-by the IP server itself.
-The route is described by
-.BR nwr_dest ,
-.BR nwr_netmask ,
-.BR nwr_gateway ,
-.BR nwr_dist ,
-and
-.BR nwr_pref .
-\fBNwr_dest\fP and \fBnwr_netmask\fP select the destination addresses.
-A value of 0.0.0.0 (0x0) in both \fBnwr_dest\fP and \fBnwr_netmask\fP means
-every host.
-A value of 255.255.255.255 (0xffffffff) in \fBnwr_netmask\fP means a single
-host.
-Other values of \fBnwr_netmask\fP are netmasks for the network specified
-by \fBnwr_dest\fP.
-\fBNwr_gateway\fP is gateway that should be used.
-\fBNwr_dist\fP is a minimal distance.
-Packets with a time to live smaller than \fBnwr_dist\fP will not reach the
-destination.
-If two routes have equal netmask and distance fields but different
-gateways then the gateway with highest value in \fBnwr_pref\fP is used.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSIPCONF, &struct nwio_ipconf)
-.ft R
-.PP
-The
-.B NWIOSIPCONF
-ioctl can be used to inform the IP server about its Internet Address
-and/or its netmask.
-Normally an IP server will discover its Internet Address using the RARP
-protocol.
-.B NWIOSIPCONF
-can be used in the case that the RARP failed, or the netmask has to be changed.
-Note that higher level protocols (TCP and UDP) assume that the Internet Address
-of an IP device does not change, therefore TCP and UDP stop functioning if
-the Internet Address is changed.
-.PP
-The structure \fBnwio_ipconf\fP is defined in <net/gen/ip_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_ipconf
-{
- u32_t nwic_flags;
- ipaddr_t nwic_ipaddr;
- ipaddr_t nwic_netmask;
-} nwio_ipconf_t;
-.SP
-#define NWIC_NOFLAGS 0x0
-#define NWIC_FLAGS 0x3
-# define NWIC_IPADDR_SET 0x1
-# define NWIC_NETMASK_SET 0x2
-.if t .ft R
-.fi
-.RE
-.PP
-The function of \fBnwio_ipconf\fP depends on the value of \fBnwic_flags\fP.
-If
-.B NWIC_IPADDR_SET
-is set then the Internet Address will be set to
-\fBnwic_ipaddr\fP.
-If
-.B NWIC_NETMASK_SET
-is set then the Internet Address will be set to
-\fBnwic_netmask\fP.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSIPOPT, &struct nwio_ipopt)
-.ft R
-.PP
-Before an IP channel can be used, it has to be configured using the
-.B NWIOSIPOPT
-ioctl.
-The structure \fBnwio_ipopt\fP is defined in <net/gen/ip_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_ipopt
-{
- u32_t nwio_flags;
- ipaddr_t nwio_rem;
- ip_hdropt_t nwio_hdropt;
- u8_t nwio_tos;
- u8_t nwio_ttl;
- u8_t nwio_df;
- ipproto_t nwio_proto;
-} nwio_ipopt_t;
-.SP
-#define NWIO_NOFLAGS 0x0000L
-#define NWIO_ACC_MASK 0x0003L
-# define NWIO_EXCL 0x00000001L
-# define NWIO_SHARED 0x00000002L
-# define NWIO_COPY 0x00000003L
-#define NWIO_LOC_MASK 0x0010L
-# define NWIO_EN_LOC 0x00000010L
-# define NWIO_DI_LOC 0x00100000L
-#define NWIO_BROAD_MASK 0x0020L
-# define NWIO_EN_BROAD 0x00000020L
-# define NWIO_DI_BROAD 0x00200000L
-#define NWIO_REM_MASK 0x0100L
-# define NWIO_REMSPEC 0x00000100L
-# define NWIO_REMANY 0x01000000L
-#define NWIO_PROTO_MASK 0x0200L
-# define NWIO_PROTOSPEC 0x00000200L
-# define NWIO_PROTOANY 0x02000000L
-#define NWIO_HDR_O_MASK 0x0400L
-# define NWIO_HDR_O_SPEC 0x00000400L
-# define NWIO_HDR_O_ANY 0x04000000L
-#define NWIO_RW_MASK 0x1000L
-# define NWIO_RWDATONLY 0x00001000L
-# define NWIO_RWDATALL 0x10000000L
-.if t .ft R
-.fi
-.RE
-.PP
-The options are divided in several categories:
-.BR NWIO_ACC_MASK ,
-.BR NWIO_LOC_MASK ,
-.BR NWIO_BROAD_MASK ,
-.BR NWIO_REM_MASK ,
-.BR NWIO_PROTO_MASK ,
-.B NWIO_HDR_O_MASK
-and
-.BR NWIO_RW_MASK .
-A channel is configured when one option of each category is set.
-.PP
-The options covered by
-.B NWIO_ACC_MASK
-control the number of channels that
-can use one IP protocol.
-If
-.B NWIO_EXCL
-is specified then only that channel can use a certain IP protocol.
-If
-.B NWIO_SHARED
-then multiple channels that all have to specify
-.B NWIO_SHARED
-can use the same IP protocol, but incoming packets will
-be delivered to a most one channel.
-.B NWIO_COPY
-does not impose any restrictions.
-Every channel gets a copy of an incoming packet.
-.PP
-.B NWIO_LOC_MASK
-and
-.B NWIO_BROAD_MASK
-control the delivery of packets.
-If
-.B NWIO_EN_LOC
-is specified then packets that are explicitly send to
-the IP server are delivered.
-If
-.B NWIO_EN_BROAD
-is specified then broadcast packets are delivered.
-Either one or both of them can be disabled with
-.B NWIO_DI_LOC
-and
-.BR NWIO_DI_BROAD .
-.PP
-.B NWIO_REMSPEC
-can be used to restrict communication to one remote host.
-This host is taken from the \fBnwio_rem\fP field.
-If any remote host is to be allowed then
-.B NWIO_REMANY
-can be used.
-.PP
-.B NWIO_PROTOSPEC
-restricts communication to one IP protocol, specified
-in \fBnwio_proto\fP.
-.B NWIO_PROTOANY
-allows any protocol to be sent or received.
-.PP
-.B NWIO_HDR_O_SPEC
-specifies all IP header options in advance.
-The values are taken from
-.BR nwio_hdropt ,
-.BR nwio_tos ,
-.BR nwio_ttl ,
-and
-.BR nwio_df .
-\fBNwio_hdropt\fP specifies the IP options that should be present in an
-outgoing packet.
-\fBIp_hdropt_t\fP is defined in <net/gen/in.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct ip_hdropt
-{
- u8_t iho_opt_siz;
- u8_t iho_data[IP_MAX_HDR_SIZE-IP_MIN_HDR_SIZE];
-} ip_hdropt_t;
-.if t .ft R
-.fi
-.RE
-.PP
-The bytes of size \fBiho_opt_siz\fP in \fBiho_data\fP are appended to the IP
-header.
-\fBNwio_tos\fP specifies the value of the ``type of service'' bits,
-\fBnwio_ttl\fP gives the value of the ``time to live'' field and \fBnwio_df\fP
-specifies whether fragmentation is disallowed or not.
-.B NWIO_HDR_O_ANY
-specifies that the header options should be specified at
-each write request.
-.PP
-.B NWIO_RWDATONLY
-specifies that the header should be omitted from a
-write request.
-This option can only be used when all header fields are specified in previous
-options:
-.BR NWIO_EN_LOC ,
-.BR NWIO_DI_BROAD ,
-.BR NWIO_REMSPEC ,
-.B NWIO_PROTOSPEC
-and
-.BR NWIO_HDR_O_SPEC .
-A read operation will also only return the data part, so the IP options will
-be lost.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSIPOROUTE, &struct nwio_route)
-.ft R
-.PP
-The
-.B NWIOSIPOROUTE
-ioctl adds a route to the routing table.
-See \fBNWIOGIPOROUTE\fP above for a description of the \fBnwio_route\fP
-structure.
-The fields \fBnwr_ent_no\fP and \fBnwr_ent_count\fP are ignored.
-.SS "TCP Functions"
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOTCPCONN, &struct nwio_tcpcl)
-.ft R
-.PP
-The
-.B NWIOTCPCONN
-ioctl tries to setup a connection with a remote TCP/IP server.
-The channel must be fully configured (see
-.BR NWIOSTCPCONF )
-and values for the local port, the remote port and the remote address have be
-specified using
-.B NWTC_LP_SET
-or
-.BR NWTC_LP_SEL ,
-.B NWTC_SET_RA
-and
-.BR NWTC_SET_RP .
-The struct nwio_tcpcl is defined in <net/gen/tcp_io.h> as:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_tcpcl
-{
- long nwtcl_flags;
- long nwtcl_ttl;
-} nwio_tcpcl_t;
-.if t .ft R
-.fi
-.RE
-.PP
-Set the
-.B nwtcl_flags
-field to zero before the connect or listen call. [[[Further explanation of
-nwio_tcpcl?]]]
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGTCPCONF, &struct nwio_tcpconf)
-.ft R
-.PP
-This call reports the current configuration of a TCP channel.
-The
-.B nwtc_flags
-field shows the status of the
-.BR access ,
-.BR locport ,
-.B remaddr
-and
-.B remport
-fields.
-.B Nwtc_locaddr
-contains the Internet address of the TCP/IP server.
-.B Remaddr
-contains the Internet address of the remote TCP/IP server when set with
-.B NWTC_SET_RA
-or after a successful connect or listen (see
-.B NWIOTCPCONN
-or
-.BR NWIOTCPLISTEN ).
-.B Nwio_locport
-contains the local TCP/IP port set with
-.B NWTC_LP_SET
-or the selected port set with
-.BR NWTC_LP_SEL .
-.B Nwtc_remport
-contains the TCP port of the remote TCP/IP server as set with
-.B NWIO_SET_RP
-or after a successful connect or listen.
-.PP
-A value of 0 (zero) is reported for
-.BR nwtc_remaddr ,
-.B nwtc_locport
-or
-.B nwtc_remport
-when no value is set either explicitly or implicitly.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOTCPLISTEN, &struct nwio_tcpcl)
-.ft R
-.PP
-The
-.B NWIOTCPLISTEN
-ioctl waits until a remote TCP/IP server tries to connect to this channel.
-The channel has to be configured (see
-.BR NWIOSTCPCONF ).
-An additional restriction is that the local port
-must be set (with
-.BR NWTC_LP_SET )
-or selected (with
-.BR NWTC_LP_SEL ).
-When a remote address is set only connections for that host are accepted, and
-when a remote port is set only connections from that port are accepted.
-After a successful listen
-.B NWIOGTCPCONF
-can be used to find out what the address and port of the other side are.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSTCPCONF, &struct nwio_tcpconf)
-.ft R
-.PP
-Before a TCP channel can be used it must configured using the
-.B NWIOSTCPCONF
-ioctl.
-The parameters to
-.B NWIOSTCPCONF
-are the channel file descriptor and a
-.B struct nwio_tcpconf
-as defined in <net/gen/tcp_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_tcpconf
-{
- u32_t nwtc_flags;
- ipaddr_t nwtc_locaddr;
- ipaddr_t nwtc_remaddr;
- tcpport_t nwtc_locport;
- tcpport_t nwtc_remport;
-} nwio_tcpconf_t;
-.SP
-#define NWTC_NOFLAGS 0x0000L
-#define NWTC_ACC_MASK 0x0003L
-# define NWTC_EXCL 0x00000001L
-# define NWTC_SHARED 0x00000002L
-# define NWTC_COPY 0x00000003L
-#define NWTC_LOCPORT_MASK 0x0030L
-# define NWTC_LP_UNSET 0x00000010L
-# define NWTC_LP_SET 0x00000020L
-# define NWTC_LP_SEL 0x00000030L
-#define NWTC_REMADDR_MASK 0x0100L
-# define NWTC_SET_RA 0x00000100L
-# define NWTC_UNSET_RA 0x01000000L
-#define NWTC_REMPORT_MASK 0x0200L
-# define NWTC_SET_RP 0x00000200L
-# define NWTC_UNSET_RP 0x02000000L
-.if t .ft R
-.fi
-.RE
-.PP
-A tcp channel is considered configured when one flag in each category has
-been selected.
-Thus one of
-.BR NWTC_EXCL ,
-.B NWTC_SHARED
-or
-.BR NWTC_COPY ,
-one of
-.BR NWTC_LP_UNSET ,
-.B NWTC_LP_SET
-or
-.BR NWTC_LP_SEL ,
-one of
-.B NWTC_SET_RA
-or
-.BR NWTC_UNSET_RA ,
-and one of
-.B NWTC_SET_RP
-or
-.BR NWTC_UNSET_RP .
-.PP
-The acc flags control the access to a certain TCP port.
-.B NWTC_EXCL
-means exclusive access.
-An attempt to configure a channel will be denied if the same port is specified
-as that of a channel that requested exclusive access.
-.B NWTC_SHARED
-indicates that several channels use the same port but cooperate.
-If the shared mode is specified for one channel than all other channel that
-use the same port should also be configured with the
-.B NWTC_SHARED
-flag.
-.B NWTC_COPY
-is specified when the programmer does not care about other channels.
-This is the default.
-.PP
-The locport flags control which TCP port is used for communication.
-.B NWTC_LP_UNSET
-indicates the absence of a local port.
-This is the default.
-.B NWTC_LP_SET
-means that the
-.B nwtc_locport
-field contains the local port to be used by TCP.
-This value must be in network byte order (see
-.BR hton (3).)
-.B NWTC_LP_SEL
-requests the TCP server to pick a port.
-This port will be in the range from 32768 to 65535 and will be unique.
-.LP
-The
-.B remaddr
-flags specify which hosts are acceptable for connections.
-.B NWTC_SET_RA
-indicates that only connection to the host specified in
-.B nwtc_remaddr
-are acceptable.
-.B Nwtc_remaddr
-should be in network byte order (see
-.BR hton (3).)
-.B NWTC_UNSET_RA
-allows every host on the other side of a connection.
-This is the default.
-.PP
-The
-.B remport
-flags specify which remote ports are acceptable for connections.
-.B NWTC_SET_RP
-indicates that only the port specified in
-.B nwtc_remport
-is acceptable.
-.B NWTC_UNSET_RP
-allows every port on the other side of a connection.
-This is the default.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOTCPSHUTDOWN)
-.ft R
-.PP
-The
-.B NWIOTCPSHUTDOWN
-tells the TCP/IP server that no more data will be sent over the channel
-specified by
-.IR fd .
-This command can be issued when the channel is connected to a remote TCP/IP
-server.
-The TCP/IP server will tell the remote TCP/IP server and the client of the
-remote TCP/IP server will receive an end-of-file indication.
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGTCPOPT, &struct nwio_tcpopt)
-.br
-ioctl(\fIfd\fP, NWIOSTCPOPT, &struct nwio_tcpopt)
-.ft R
-.PP
-The behaviour of a TCP channel may be changed by setting a number of
-options. The TCP options can be obtained with the
-.B NWIOGTCPOPT
-ioctl and set with the
-.B NWIOSTCPOPT
-ioctl. The options are passed in a
-.B struct nwio_tcpopt
-as defined in <net/gen/tcp_io.h>:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_tcpopt
-{
- u32_t nwto_flags;
-} nwio_tcpopt_t;
-.SP
-#define NWTO_NOFLAG 0x0000L
-#define NWTO_SND_URG_MASK 0x0001L
-# define NWTO_SND_URG 0x00000001L
-# define NWTO_SND_NOTURG 0x00010000L
-#define NWTO_RCV_URG_MASK 0x0002L
-# define NWTO_RCV_URG 0x00000002L
-# define NWTO_RCV_NOTURG 0x00020000L
-#define NWTO_BSD_URG_MASK 0x0004L
-# define NWTO_BSD_URG 0x00000004L
-#define NWTO_DEL_RST_MASK 0x0008L
-# define NWTO_DEL_RST 0x00000008L
-.if t .ft R
-.fi
-.RE
-.PP
-The
-.B NWTO_SND_URG
-option causes bytes written to the channel to be send out as urgent data.
-On receiving an
-.B EURG
-error the
-.B NWTO_RCV_URG
-option must be set to switch over to reading urgent data. When all urgent
-data has been read an
-.B ENOURG
-error will follow,
-indicating that the option must be cleared with
-.BR NWTO_RCV_NOTURG .
-Alas the BSD implementation of urgent data disagrees with the RFC's, so to
-be BSD compatible one must set the
-.B NWTO_BSD_URG
-option beforehand on a channel that is to send or receive urgent data.
-Given that the BSD implementation is the regarded as the TCP/IP standard one
-should always use the BSD style. The
-.B NWTO_DEL_RST
-option delays a failure response on a connect to the same port as the
-current open connection. Without this option a connect would fail if
-a server is not yet listening. With this option a connect will linger
-on until the server starts listening. This option is useful for a server
-that opens a connection, tells the remote end the local port number and
-then listens (FTP), or for a program that forks off servers for incoming
-connections (TELNET). A new connection may come in before a new listen
-can be started, so it is nice if the new connect doesn't fail. Use this
-option only when it is clearly needed.
-.SS "UDP Functions"
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOGUDPOPT, &struct nwio_udpopt)
-.ft R
-.PP
-The
-.B NWIOGUDPOPT
-ioctl returns the current options that result from the default options
-and the options set with
-.BR NWIOSUDPOPT .
-When
-.B NWUO_LP_SEL
-or
-.B NWUO_LP_SET
-is selected the local port is returned in
-.BR nwuo_locport .
-When
-.B NWUO_RP_SET
-is selected the remote port is returned in
-.BR nwuo_remport .
-The local address is always returned in
-.BR nwuo_locaddr ,
-and when
-.B NWUO_RA_SET
-is selected the remote address is returned in
-.BR nwuo_remaddr .
-.PP
-.ft B
-ioctl(\fIfd\fP, NWIOSUDPOPT, &struct nwio_udpopt)
-.ft R
-.PP
-A UDP channel must be configured using the
-.B NWIOSUDPOPT
-ioctl before any data can be read or written.
-.B NWIOSUDPOPT
-takes two parameters, a file descriptor to an open UDP device and
-pointer to a
-.B nwio_udpopt
-structure that describes the requested configuration.
-The
-.B nwio_udpopt
-structure is defined in <net/gen/udp_io.h> as:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct nwio_udpopt
-{
- unsigned long nwuo_flags;
- udpport_t nwuo_locport;
- udpport_t nwuo_remport;
- ipaddr_t nwuo_locaddr;
- ipaddr_t nwuo_remaddr;
-} nwio_udpopt_t;
-.SP
-#define NWUO_NOFLAGS 0x0000L
-#define NWUO_ACC_MASK 0x0003L
-#define NWUO_EXCL 0x00000001L
-#define NWUO_SHARED 0x00000002L
-#define NWUO_COPY 0x00000003L
-#define NWUO_LOCPORT_MASK 0x000CL
-#define NWUO_LP_SEL 0x00000004L
-#define NWUO_LP_SET 0x00000008L
-#define NWUO_LP_ANY 0x0000000CL
-#define NWUO_LOCADDR_MASK 0x0010L
-#define NWUO_EN_LOC 0x00000010L
-#define NWUO_DI_LOC 0x00100000L
-#define NWUO_BROAD_MASK 0x0020L
-#define NWUO_EN_BROAD 0x00000020L
-#define NWUO_DI_BROAD 0x00200000L
-#define NWUO_REMPORT_MASK 0x0100L
-#define NWUO_RP_SET 0x00000100L
-#define NWUO_RP_ANY 0x01000000L
-#define NWUO_REMADDR_MASK 0x0200L
-#define NWUO_RA_SET 0x00000200L
-#define NWUO_RA_ANY 0x02000000L
-#define NWUO_RW_MASK 0x1000L
-#define NWUO_RWDATONLY 0x00001000L
-#define NWUO_RWDATALL 0x10000000L
-#define NWUO_IPOPT_MASK 0x2000L
-#define NWUO_EN_IPOPT 0x00002000L
-#define NWUO_DI_IPOPT 0x20000000L
-.if t .ft R
-.fi
-.RE
-.PP
-A UDP channel is considered configured when one flag in each category has been
-selected.
-Thus one of
-.BR NWUO_EXCL ,
-.B NWUO_SHARED
-or
-.BR NWUO_COPY ,
-one of
-.BR NWUO_LP_SEL ,
-.B NWUO_LP_SET
-or
-.BR NWUO_LP_ANY ,
-one of
-.B NWUO_EN_LOC
-or
-.BR NWUO_DI_LOC ,
-one of
-.BR NWUO_EN_BROAD ,
-or
-.BR NWUO_DI_BROAD ,
-one of
-.BR NWUO_RP_SET ,
-or
-.BR NWUO_RP_ANY ,
-one of
-.BR NWUO_RA_SET ,
-or
-.BR NWUO_RA_ANY ,
-one of
-.BR NWUO_RWDATONLY ,
-or
-.BR NWUO_RWDATALL ,
-and one of
-.BR NWUO_EN_IPOPT ,
-or
-.BR NWUO_DI_IPOPT .
-The acc flags control the access to a certain UDP port.
-.B NWUO_EXCL
-means exclusive access:
-no other channel can use this port.
-.B NWUO_SHARED
-means shared access:
-only channels that specify shared access can use this port
-and all packets that are received are handed to at most one channel.
-.B NWUO_COPY
-imposes no access restriction and all channels get a copy of every received
-packet for that port.
-.PP
-The
-.B locport
-flags control the selection of the UDP port for this channel.
-.B NWUO_LP_SEL
-requests the server to pick a port.
-This port will be in the range from 32768 to 65535 and it will be unique.
-.B NWUO_LP_SET
-sets the local port to the value of the
-.B nwuo_locport
-field.
-.B NWUO_LP_ANY
-does not select a port.
-Reception of data is therefore not possible but it is
-possible to send data.
-.PP
-The
-.B locaddr
-flags control the reception of packets.
-.B NWUO_EN_LOC
-enables the reception of packets with the local IP address as destination.
-.B NWUO_DI_LOC
-disables the reception of packet for the local IP address.
-.PP
-The
-.B broad
-flags control the reception of broadcast packets.
-.B NWUO_EN_BROAD
-enables the reception of broadcast packets and
-.B NWUO_DI_BROAD
-disables the reception of broadcast packets.
-.PP
-The
-.B remport
-flags let the client to specify one specific remote UDP port or
-to allow any remote port.
-.B NWUO_RP_SET
-sets the remote UDP port to the value of
-.BR nwuo_remport .
-Only packets with a matching remote port will be delivered
-and all packets will be sent to that port.
-.B NWUO_RP_ANY
-allows reception of packets form any port and when transmitting packets the
-remote port has to be specified.
-.PP
-The
-.B remaddr
-flags control the remote IP address.
-.B NWUO_RA_SET
-sets the remote IP address the value of
-.BR nwuo_remaddr .
-Only packets from that address will be delivered and all packets will be sent
-to that address.
-.B NWUO_RA_ANY
-allows reception of packets from any host and when transmitting packets the
-remote host has to be specified.
-.PP
-The
-.B rw
-flags control the format of the data to be sent or received.
-With
-.B NWUO_RWDATONLY
-only the data part of a UDP packet is sent to the server and only the data
-part is received from the server.
-The
-.B NWUO_RWDATALL
-mode presents the data part of a UDP packet with a header that contains
-the source and destination IP address, source and destination UDP ports,
-the IP options, etc.
-The server expects such a header in front of the data to be transmitted.
-.ig \" Some for Philip to explain properly:
-The header is defined in <net/gen/udp_hdr.h> and looks like this:
-.PP
-.RS
-.nf
-.if t .ft C
-typedef struct udp_io_hdr
-{
- ipaddr_t uih_src_addr;
- ipaddr_t uih_dst_addr;
- udpport_t uih_src_port;
- udpport_t uih_dst_port;
- u16_t uih_ip_opt_len;
- u16_t uih_data_len;
-} udp_io_hdr_t;
-.if t .ft R
-.fi
-.RE
-.PP
-The first four fields are the source and destination IP addresses and
-ports.
-.B Uih_ip_opt_len
-is ???.
-.B Uih_data_len
-should equal the length of the packet data (packet lenght minus the
-header.) ???
-..
-.PP
-The
-.B ipopt
-flags control the delivery and transmission of IP options.
-When
-.B NWUO_EN_IPOPT
-is set IP, options will be delivered and sent.
-When
-.B NWUO_DI_IPOPT
-is set IP option will be stripped from received packets and no IP options will
-be sent.
-.ig \" MINIX 3 doesn't have this stuff (yet? ever?)
-.SS "UDP Library Functions"
-.PP
-The following routines provide an somewhat easier to use interface to UDP than
-the routines described above (\fBtcpip_open\fP, \fBudp_ioc_setopt\fP,
-\fBtcpip_read\fP and \fBtcpip_write\fP).
-.LP
-.sC
-errstat
-udp_connect(udp_cap, chan_cap, srcport, dstport, dstaddr, flags)
-capability *udp_cap;
-capability *chan_cap;
-udpport_t srcport;
-udpport_t dstport;
-ipaddr_t dstaddr;
-int flags;
-.eC
-.kW "\fIudp_connect\fP"
-\fIUdp_connect\fP combines the functionality of \fItcpip_open\fP and
-\fIudp_ioc_setopt\fP.
-A pointer to a UDP server capability should be passed in \fIudp_cap\fP, and
-the channel capability will be returned in the capability pointed to by
-\fIchan_cap\fP.
-If \fIsrcport\fP is 0 then an unused port will be selected, otherwise the local
-port will be set to \fIsrcport\fP.
-If \fIdstport\fP is non-zero then communication will be restricted to remote ports
-that equal to \fIdstport\fP, otherwise any data can be sent to or received from
-any remote port.
-The same thing applies to \fIdstaddr\fP; if \fIdstaddr\fP is non-zero then
-only \fIdstaddr\fP can be reached.
-Currently no flags are defined so \fIflags\fP should be 0.
-.sH
-udp_reconnect
-.LP
-.sC
-errstat
-udp_reconnect(chan_cap, srcport, dstport, dstaddr, flags)
-capability *chan_cap;
-udpport_t srcport;
-udpport_t dstport;
-ipaddr_t dstaddr;
-int flags;
-.eC
-.kW "\fIudp_reconnect\fP"
-\fIUdp_reconnect\fP is the same as \fIudp_connect\fP except that an existing
-channel capability is (re)used.
-.sH
-udp_read_msg
-.LP
-.sC
-errstat
-udp_read_msg(chan_cap, msg, msglen, actlen, flags)
-capability *chan_cap;
-char *msg;
-int msglen;
-int *actlen;
-int flags;
-.eC
-.kW "\fIudp_read_msg\fP"
-\fIUdp_read_msg\fP delivers a UDP packet.
-The data part of the UDP packet is
-prepended with an \fIudp_io_hdr\fP.
-The actual length of the possibly truncated packet is returned in \fIactlen\fP.
-No flags are defined so \fIflags\fP should be 0.
-.sH
-udp_write_msg
-.LP
-.sC
-errstat
-udp_write_msg(chan_cap, msg, msglen, flags)
-capability *chan_cap;
-char *msg;
-int msglen;
-int flags;
-.eC
-.kW "\fIudp_write_msg\fP"
-A UDP packet can be sent with \fIudp_write_msg\fP.
-\fIMsg\fP should point to a \fIudp_io_hdr\fP followed by the data part of the
-UDP packet.
-The \fIuih_dst_addr\fP and \fIuih_dst_port\fP fields of the \fIudp_io_hdr\fP
-should be filled in if no values are specified in the \fIudp_connect\fP,
-or \fIudp_reconnect\fP.
-.sH
-udp_close
-.LP
-.sC
-errstat
-udp_close(chan_cap, flags)
-capability *chan_cap;
-int flags;
-.eC
-.kW "\fIudp_close\fP"
-\fIUdp_close\fP cleans up the administration kept by the UDP library but does
-not destroy the capability.
-The function should be used if the capability is passed to another process
-and should continue to exist.
-No flags are defined so \fIflags\fP should be 0.
-.sH
-udp_destroy
-.LP
-.sC
-errstat
-udp_destroy(chan_cap, flags)
-capability *chan_cap;
-int flags;
-.eC
-.kW "\fIudp_destroy\fP"
-\fIUdp_destroy\fP not only cleans up the administration kept by the UDP library
-but also destroys the channel capability.
-..
-.SH FILES
-.IP /dev/eth* \w'/dev/psip*mmm'u
-Raw ethernet. The numbers in the device names are decimal, so one may see
-names from
-.B eth0
-to
-.BR eth15 .
-
-.IP /dev/psip*
-First and second Pseudo IP network.
-.IP /dev/ip*
-IP devices for two ethernets and two Pseudo IP networks.
-.IP /dev/tcp*
-TCP devices for same four networks.
-.IP /dev/udp*
-UDP devices.
-.IP "/dev/eth, /dev/psip, /dev/ip, /dev/tcp, /dev/udp"
-Devices for the default network, links to the devices above.
-.B Eth
-is only present if ethernet is the default,
-.B psip
-only for pseudo IP.
-.SH "SEE ALSO"
-.BR hton (3),
-.BR oneC_sum (3),
-.BR inet (8),
-.BR boot (8).
-.SH DIAGNOSTICS
-Several errors may be returned by the TCP/IP server. The error code
-is found in the
-.B errno
-variable if the
-.BR read ,
-.BR write ,
-or
-.B ioctl
-call returns -1. The TCP/IP error codes defined in <errno.h> are, among others:
-.IP EPACKSIZE 5c
-This indicates an attempt to read or write with a buffer that is too
-large or too small.
-.IP ENOBUFS
-The TCP/IP server has insufficient memory to execute the request.
-.IP ENOTTY
-This indicates an attempt to execute a command the particular server
-does not understand.
-For example, a
-.B NWIOGTCPCONF
-on an ETH channel.
-.IP EBADMODE
-The request is refused because the channel is not fully configured, in the
-wrong state or the parameters are invalid.
-.IP ENETUNREACH
-The destination network is not reachable.
-.IP EHOSTUNREACH
-The destination host is not reachable.
-.IP EISCONN
-The channel is already connected so a second request is refused.
-.IP EADDRINUSE
-This address is in use.
-.IP ECONNREFUSED
-The connection is refused by the other side.
-.IP ECONNRESET
-The connection is reset (non-gracefully terminated) by the other side.
-.IP ETIMEDOUT
-The connection is terminated due to an expired timer.
-.IP EURG
-Urgent data is present and the current receive mode does not allow urgent data
-to be transferred.
-.IP ENOURG
-No urgent data is present and a request came for urgent data.
-.IP ENOTCONN
-The request requires a connected channel and the channel is not connected.
-.IP ESHUTDOWN
-The connection is shut down.
-That is, a
-.B NWIOTCPSHUTDOWN
-has been executed so no more data can be transmitted.
-.IP ENOCONN
-The connection does not exist.
-.IP EGENERIC
-A generic error code for extremely weird cases.
-.SH AUTHOR
-Philip Homburg (philip@cs.vu.nl)
-
-.\"
-.\" $PchId: ip.4,v 1.4 2001/01/08 19:58:14 philip Exp $
\fBhosts\fP TCP/IP hosts database, \fBhosts\fP(5)
\fBhosts.equiv\fP
trusted remote users or hosts, \fBrhosts\fP(5)
- \fBinet.conf\fP
- internet server config file, \fBinet\fP(8)
\fBkeymap\fP keymap for custom keyboard, \fBloadkeys\fP(1)
\fBman.conf\fP
configuration file for man(1), \fBman.conf\fP(5)
\fBarpa\fP include files for Internet service protocols
\fBmachine\fP machine specific include files
\fBminix\fP MINIX 3 kernel include files
- \fBnetinet\fP include files for Inernet standard protocols, see
- \fBinet\fP(8)
+ \fBnetinet\fP include files for Internet standard protocols
\fBsys\fP system C include files.
...
boot variable, you can use it to put more characters on the screen, at
the cost of video memory.
.TP
-.SB ENABLE_DP8390
-Master switch to enable the network drivers. They are required by the
-network server,
-.BR inet .
-See
-.BR boot (8)
-for information on configuring network support.
-.TP
-.SB ENABLE_WDETH
-Enable code for the WD8003 and WD8013 cards in the network driver.
-.TP
-.SB ENABLE_NE2000
-Enable code for the NE1000 and NE2000 cards.
-.TP
-.SB ENABLE_3C503
-Enable code for the 3Com Etherlink II (3C503).
-.TP
.SB NR_PTYS
Number of pseudo terminals supported, by default
.BR 0 ,
These locks are often used by programs that update a shared file, like mail
programs do with mail boxes. A "no locks available" error indicates that
this table has run out.
-.PP
-.ti 2m
-.B inet/inet_config.h
-.br
-The maximum number of TCP/IP networks is:
-.TP
-.B IP_PORT_MAX
-Sets the maximum number of networks that can be defined in
-.BR /etc/inet.conf .
-.BR 8086 ,
-.BR 286 :
-By default 2.
-.BR 386 :
-By default 4.
-.PP
-.ti 2m
-.B inet/buf.c
-.br
-The number of 512 byte buffers allocated for data within the TCP/IP server is:
-.TP
-.B BUF512_NR
-These buffers are a shared resource used by the server for any data it wants
-to play with. For incoming data this number of buffers determines the time
-packets are kept around, with each new packet evicting an old packet. It's
-no big deal if packets get lost before a user process reads them, packets
-get lost all the time. The only real problem is outgoing TCP data. The
-default setting for
-.SB BUF512_NR
-allows up to four backlogged TCP streams, i.e. when data is output faster
-then it is read. If more buffers are needed then one of the TCP connections
-is shut down. When this happens you will see a "not enough buffers left"
-error. This could happen for instance if a MINIX 3 web server is assaulted by
-a browser that likes to open several connections to the server
-simultaneously. The fix is to increase
-.SB BUF512_NR
-to allow more slow outgoing TCP streams.
-.BR 86 :
-The default of
-.B 32
-buffers can be increased up to
-.BR 64 .
-(The "TCP window size" has been limited in 16-bit mode to keep the buffer
-use by TCP down.)
-.BR 386 :
-The default of
-.B 128
-can be increased to any value you like, but
-.B 512
-seems to be more than enough. Minix-vmd uses 512 by default, and it seems
-happy that way.
.SH "SEE ALSO"
.BR controller (4),
.BR usage (8),
.include <bsd.own.mk>
.if ${MKIMAGEONLY} == "no"
-SUBDIR+= inet
SUBDIR+= uds
.endif # ${MKIMAGEONLY} == "no"
+++ /dev/null
-# Makefile for inet.
-PROG= inet
-SRCS= buf.c clock.c inet.c inet_config.c \
- mnx_eth.c mq.c qp.c sr.c \
- udp.c arp.c eth.c event.c \
- icmp.c io.c ip.c ip_ioctl.c \
- ip_lib.c ip_read.c ip_write.c \
- ipr.c rand256.c tcp.c tcp_lib.c \
- tcp_recv.c tcp_send.c ip_eth.c \
- ip_ps.c psip.c \
- queryparam.c version.c rtinfo.c
-MAN= inet.8
-
-FILES=${PROG}.conf
-FILESNAME=${PROG}
-FILESDIR= /etc/system.conf.d
-
-.PATH: ${.CURDIR}/generic
-
-DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
-LDADD+= -lchardriver -lsys
-
-CPPFLAGS+= -I${.CURDIR} -D'ARGS(a)=a'
-
-.include <minix.service.mk>
+++ /dev/null
-/*
-This file contains routines for buffer management.
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "generic/assert.h"
-#include "generic/buf.h"
-
-THIS_FILE
-
-#ifndef BUF_USEMALLOC
-#define BUF_USEMALLOC 0
-#endif
-
-#ifndef BUF512_NR
-#define BUF512_NR 512
-#endif
-#ifndef BUF2K_NR
-#define BUF2K_NR 0
-#endif
-#ifndef BUF32K_NR
-#define BUF32K_NR 0
-#endif
-
-#define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
-#define CLIENT_NR 10
-
-#define DECLARE_TYPE(Tag, Type, Size) \
- typedef struct Tag \
- { \
- buf_t buf_header; \
- char buf_data[Size]; \
- } Type
-
-#if BUF_USEMALLOC
-#define DECLARE_STORAGE(Type, Ident, Nitems) \
- PRIVATE Type *Ident
-
-#define ALLOC_STORAGE(Ident, Nitems, Label) \
- do \
- { \
- printf("buf.c: malloc %d %s\n", Nitems, Label); \
- Ident= malloc(sizeof(*Ident) * Nitems); \
- if (!Ident) \
- ip_panic(( "unable to alloc %s", Label )); \
- } while(0)
-#else
-#define DECLARE_STORAGE(Type, Ident, Nitems) \
- PRIVATE Type Ident[Nitems]
-
-#define ALLOC_STORAGE(Ident, Nitems, Label) \
- (void)0
-#endif
-
-#if BUF512_NR
-DECLARE_TYPE(buf512, buf512_t, 512);
-static acc_t *buf512_freelist;
-DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
-static void bf_512free ARGS(( acc_t *acc ));
-#endif
-#if BUF2K_NR
-DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
-static acc_t *buf2K_freelist;
-DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
-static void bf_2Kfree ARGS(( acc_t *acc ));
-#endif
-#if BUF32K_NR
-DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
-static acc_t *buf32K_freelist;
-DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
-static void bf_32Kfree ARGS(( acc_t *acc ));
-#endif
-
-static acc_t *acc_freelist;
-DECLARE_STORAGE(acc_t, accessors, ACC_NR);
-
-static bf_freereq_t freereq[CLIENT_NR];
-static size_t bf_buf_gran;
-
-size_t bf_free_bufsize;
-acc_t *bf_temporary_acc;
-acc_t *bf_linkcheck_acc;
-
-#ifdef BUF_CONSISTENCY_CHECK
-int inet_buf_debug;
-unsigned buf_generation;
-static bf_checkreq_t checkreq[CLIENT_NR];
-#endif
-
-#ifndef BUF_TRACK_ALLOC_FREE
-static acc_t *bf_small_memreq ARGS(( size_t size ));
-#else
-static acc_t *_bf_small_memreq ARGS(( char *clnt_file, int clnt_line,
- size_t size ));
-#define bf_small_memreq(a) _bf_small_memreq(clnt_file, clnt_line, a)
-#endif
-static void free_accs ARGS(( void ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void count_free_bufs ARGS(( acc_t *list ));
-static int report_buffer ARGS(( buf_t *buf, char *label, int i ));
-#endif
-
-void bf_init()
-{
- int i;
- size_t buf_s;
- acc_t *acc;
-
- bf_buf_gran= BUF_S;
- buf_s= 0;
-
- for (i=0;i<CLIENT_NR;i++)
- freereq[i]=0;
-#ifdef BUF_CONSISTENCY_CHECK
- for (i=0;i<CLIENT_NR;i++)
- checkreq[i]=0;
-#endif
-
-#if BUF512_NR
- ALLOC_STORAGE(buffers512, BUF512_NR, "512B-buffers");
-#endif
-#if BUF2K_NR
- ALLOC_STORAGE(buffers2K, BUF2K_NR, "2K-buffers");
-#endif
-#if BUF32K_NR
- ALLOC_STORAGE(buffers32K, BUF32K_NR, "32K-buffers");
-#endif
- ALLOC_STORAGE(accessors, ACC_NR, "accs");
-
- acc_freelist= NULL;
- for (i=0;i<ACC_NR;i++)
- {
- memset(&accessors[i], '\0', sizeof(accessors[i]));
-
- accessors[i].acc_linkC= 0;
- accessors[i].acc_next= acc_freelist;
- acc_freelist= &accessors[i];
- }
-
-#define INIT_BUFFERS(Ident, Nitems, Freelist, Freefunc) \
- do \
- { \
- Freelist= NULL; \
- for (i=0;i<Nitems;i++) \
- { \
- acc= acc_freelist; \
- if (!acc) \
- ip_panic(( "fewer accessors than buffers")); \
- acc_freelist= acc->acc_next; \
- acc->acc_linkC= 0; \
- \
- memset(&Ident[i], '\0', sizeof(Ident[i])); \
- Ident[i].buf_header.buf_linkC= 0; \
- Ident[i].buf_header.buf_free= Freefunc; \
- Ident[i].buf_header.buf_size= \
- sizeof(Ident[i].buf_data); \
- Ident[i].buf_header.buf_data_p= \
- Ident[i].buf_data; \
- \
- acc->acc_buffer= &Ident[i].buf_header; \
- acc->acc_next= Freelist; \
- Freelist= acc; \
- } \
- if (sizeof(Ident[0].buf_data) < bf_buf_gran) \
- bf_buf_gran= sizeof(Ident[0].buf_data); \
- if (sizeof(Ident[0].buf_data) > buf_s) \
- buf_s= sizeof(Ident[0].buf_data); \
- } while(0)
-
-#if BUF512_NR
- INIT_BUFFERS(buffers512, BUF512_NR, buf512_freelist, bf_512free);
-#endif
-#if BUF2K_NR
- INIT_BUFFERS(buffers2K, BUF2K_NR, buf2K_freelist, bf_2Kfree);
-#endif
-#if BUF32K_NR
- INIT_BUFFERS(buffers32K, BUF32K_NR, buf32K_freelist, bf_32Kfree);
-#endif
-
-#undef INIT_BUFFERS
-
- assert (buf_s == BUF_S);
-}
-
-#ifndef BUF_CONSISTENCY_CHECK
-void bf_logon(func)
-bf_freereq_t func;
-#else
-void bf_logon(func, checkfunc)
-bf_freereq_t func;
-bf_checkreq_t checkfunc;
-#endif
-{
- int i;
-
- for (i=0;i<CLIENT_NR;i++)
- if (!freereq[i])
- {
- freereq[i]=func;
-#ifdef BUF_CONSISTENCY_CHECK
- checkreq[i]= checkfunc;
-#endif
- return;
- }
-
- ip_panic(( "buf.c: too many clients" ));
-}
-
-/*
-bf_memreq
-*/
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_memreq(size)
-#else
-acc_t *_bf_memreq(clnt_file, clnt_line, size)
-char *clnt_file;
-int clnt_line;
-#endif
-size_t size;
-{
- acc_t *head, *tail, *new_acc;
- buf_t *buf;
- int i,j;
- size_t count;
-
- assert (size>0);
-
- head= NULL;
- tail= NULL;
- while (size)
- {
- new_acc= NULL;
-
- /* Note the tricky dangling else... */
-#define ALLOC_BUF(Freelist, Bufsize) \
- if (Freelist && (Bufsize == BUF_S || size <= Bufsize)) \
- { \
- new_acc= Freelist; \
- Freelist= new_acc->acc_next; \
- \
- assert(new_acc->acc_linkC == 0); \
- new_acc->acc_linkC= 1; \
- buf= new_acc->acc_buffer; \
- assert(buf->buf_linkC == 0); \
- buf->buf_linkC= 1; \
- } \
- else
-
- /* Sort attempts by buffer size */
-#if BUF512_NR
- ALLOC_BUF(buf512_freelist, 512)
-#endif
-#if BUF2K_NR
- ALLOC_BUF(buf2K_freelist, 2*1024)
-#endif
-#if BUF32K_NR
- ALLOC_BUF(buf32K_freelist, 32*1024)
-#endif
-#undef ALLOC_BUF
- {
- DBLOCK(2, printf("freeing buffers\n"));
-
- bf_free_bufsize= 0;
- for (i=0; bf_free_bufsize<size && i<MAX_BUFREQ_PRI;
- i++)
- {
- for (j=0; j<CLIENT_NR; j++)
- {
- if (freereq[j])
- (*freereq[j])(i);
- }
-#if DEBUG && 0
- { acc_t *acc;
- j= 0; for(acc= buf512_freelist; acc; acc= acc->acc_next) j++;
- printf("# of free 512-bytes buffer is now %d\n", j); }
-#endif
- }
-#if DEBUG && 0
- { printf("last level was level %d\n", i-1); }
-#endif
- if (bf_free_bufsize<size)
- ip_panic(( "not enough buffers freed" ));
-
- continue;
- }
-
-#ifdef BUF_TRACK_ALLOC_FREE
- new_acc->acc_alloc_file= clnt_file;
- new_acc->acc_alloc_line= clnt_line;
- buf->buf_alloc_file= clnt_file;
- buf->buf_alloc_line= clnt_line;
-#endif
-
- if (!head)
- head= new_acc;
- else
- tail->acc_next= new_acc;
- tail= new_acc;
-
- count= tail->acc_buffer->buf_size;
- if (count > size)
- count= size;
-
- tail->acc_offset= 0;
- tail->acc_length= count;
- size -= count;
- }
- tail->acc_next= NULL;
-
- return head;
-}
-
-/*
-bf_small_memreq
-*/
-
-#ifndef BUF_TRACK_ALLOC_FREE
-static acc_t *bf_small_memreq(size)
-#else
-static acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
-char *clnt_file;
-int clnt_line;
-#endif
-size_t size;
-{
- return bf_memreq(size);
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-void bf_afree(acc)
-#else
-void _bf_afree(clnt_file, clnt_line, acc)
-char *clnt_file;
-int clnt_line;
-#endif
-acc_t *acc;
-{
- acc_t *next_acc;
- buf_t *buf;
-
- while (acc)
- {
-#if defined(bf_afree)
- DIFBLOCK(1, (acc->acc_linkC <= 0),
- printf("clnt_file= %s, clnt_line= %d\n",
- clnt_file, clnt_line));
-#endif
- assert (acc->acc_linkC>0);
- if (--acc->acc_linkC > 0)
- break;
-
-#ifdef BUF_TRACK_ALLOC_FREE
- acc->acc_free_file= clnt_file;
- acc->acc_free_line= clnt_line;
-#endif
- buf= acc->acc_buffer;
- assert (buf);
-
-#if defined(bf_afree)
- DIFBLOCK(1, (buf->buf_linkC == 0),
- printf("clnt_file= %s, clnt_line= %d\n",
- clnt_file, clnt_line));
-#endif
- assert (buf->buf_linkC>0);
- if (--buf->buf_linkC > 0)
- {
- acc->acc_buffer= NULL;
- next_acc= acc->acc_next;
- acc->acc_next= acc_freelist;
- acc_freelist= acc;
-#ifdef BUF_CONSISTENCY_CHECK
- if (inet_buf_debug)
- {
- acc->acc_offset= 0xdeadbeaf;
- acc->acc_length= 0xdeadbeaf;
- acc->acc_buffer= (buf_t *)0xdeadbeaf;
- acc->acc_ext_link= (acc_t *)0xdeadbeaf;
- }
-#endif
- acc= next_acc;
- continue;
- }
-
- bf_free_bufsize += buf->buf_size;
-#ifdef BUF_TRACK_ALLOC_FREE
- buf->buf_free_file= clnt_file;
- buf->buf_free_line= clnt_line;
-#endif
- next_acc= acc->acc_next;
- buf->buf_free(acc);
- acc= next_acc;
- continue;
- }
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_dupacc(acc_ptr)
-#else
-acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
-char *clnt_file;
-int clnt_line;
-#endif
-register acc_t *acc_ptr;
-{
- register acc_t *new_acc;
-
- if (!acc_freelist)
- {
- free_accs();
- if (!acc_freelist)
- ip_panic(( "buf.c: out of accessors" ));
- }
- new_acc= acc_freelist;
- acc_freelist= new_acc->acc_next;
-
- *new_acc= *acc_ptr;
- if (acc_ptr->acc_next)
- acc_ptr->acc_next->acc_linkC++;
- if (acc_ptr->acc_buffer)
- acc_ptr->acc_buffer->buf_linkC++;
- new_acc->acc_linkC= 1;
-#ifdef BUF_TRACK_ALLOC_FREE
- new_acc->acc_alloc_file= clnt_file;
- new_acc->acc_alloc_line= clnt_line;
-#endif
- return new_acc;
-}
-
-size_t bf_bufsize(acc_ptr)
-register acc_t *acc_ptr;
-{
- register size_t size;
-
-assert(acc_ptr);
-
- size=0;
-
- while (acc_ptr)
- {
-assert(acc_ptr >= accessors && acc_ptr <= &accessors[ACC_NR-1]);
- size += acc_ptr->acc_length;
- acc_ptr= acc_ptr->acc_next;
- }
- return size;
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_packIffLess(pack, min_len)
-#else
-acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
-char *clnt_file;
-int clnt_line;
-#endif
-acc_t *pack;
-int min_len;
-{
- if (!pack || pack->acc_length >= min_len)
- return pack;
-
-#if DEBUG
-#ifdef bf_packIffLess
- { where(); printf("calling bf_pack because of %s %d: %d\n", bf_pack_file,
- bf_pack_line, min_len); }
-#endif
-#endif
- return bf_pack(pack);
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_pack(old_acc)
-#else
-acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
-char *clnt_file;
-int clnt_line;
-#endif
-acc_t *old_acc;
-{
- acc_t *new_acc, *acc_ptr_old, *acc_ptr_new;
- size_t size, offset_old, offset_new, block_size, block_size_old;
-
- /* Check if old acc is good enough. */
- if (!old_acc || (!old_acc->acc_next && old_acc->acc_linkC == 1 &&
- old_acc->acc_buffer->buf_linkC == 1))
- {
- return old_acc;
- }
-
- size= bf_bufsize(old_acc);
- assert(size > 0);
- new_acc= bf_memreq(size);
- acc_ptr_old= old_acc;
- acc_ptr_new= new_acc;
- offset_old= 0;
- offset_new= 0;
- while (size)
- {
- assert (acc_ptr_old);
- if (offset_old == acc_ptr_old->acc_length)
- {
- offset_old= 0;
- acc_ptr_old= acc_ptr_old->acc_next;
- continue;
- }
- assert (offset_old < acc_ptr_old->acc_length);
- block_size_old= acc_ptr_old->acc_length - offset_old;
- assert (acc_ptr_new);
- if (offset_new == acc_ptr_new->acc_length)
- {
- offset_new= 0;
- acc_ptr_new= acc_ptr_new->acc_next;
- continue;
- }
- assert (offset_new < acc_ptr_new->acc_length);
- block_size= acc_ptr_new->acc_length - offset_new;
- if (block_size > block_size_old)
- block_size= block_size_old;
- memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
- ptr2acc_data(acc_ptr_old)+offset_old, block_size);
- offset_new += block_size;
- offset_old += block_size;
- size -= block_size;
- }
- bf_afree(old_acc);
- return new_acc;
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_cut (data, offset, length)
-#else
-acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
-char *clnt_file;
-int clnt_line;
-#endif
-register acc_t *data;
-register unsigned offset;
-register unsigned length;
-{
- register acc_t *head, *tail;
-
- if (!data && !offset && !length)
- return NULL;
-#ifdef BUF_TRACK_ALLOC_FREE
- assert(data ||
- (printf("from %s, %d: %u, %u\n",
- clnt_file, clnt_line, offset, length), 0));
-#else
- assert(data);
-#endif
-
- assert(data);
-
- if (!length)
- {
- head= bf_dupacc(data);
- bf_afree(head->acc_next);
- head->acc_next= NULL;
- head->acc_length= 0;
- return head;
- }
- while (data && offset>=data->acc_length)
- {
- offset -= data->acc_length;
- data= data->acc_next;
- }
-
- assert (data);
-
- head= bf_dupacc(data);
- bf_afree(head->acc_next);
- head->acc_next= NULL;
- head->acc_offset += offset;
- head->acc_length -= offset;
- if (length >= head->acc_length)
- length -= head->acc_length;
- else
- {
- head->acc_length= length;
- length= 0;
- }
- tail= head;
- data= data->acc_next;
- while (data && length && length>=data->acc_length)
- {
- tail->acc_next= bf_dupacc(data);
- tail= tail->acc_next;
- bf_afree(tail->acc_next);
- tail->acc_next= NULL;
- data= data->acc_next;
- length -= tail->acc_length;
- }
- if (length)
- {
-#ifdef bf_cut
- assert (data ||
- (printf("bf_cut called from %s:%d\n",
- clnt_file, clnt_line), 0));
-#else
- assert (data);
-#endif
- tail->acc_next= bf_dupacc(data);
- tail= tail->acc_next;
- bf_afree(tail->acc_next);
- tail->acc_next= NULL;
- tail->acc_length= length;
- }
- return head;
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_delhead (data, offset)
-#else
-acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
-char *clnt_file;
-int clnt_line;
-#endif
-register acc_t *data;
-register unsigned offset;
-{
- acc_t *new_acc;
-
- assert(data);
-
- /* Find the acc we need to modify. */
- new_acc= data;
- while(offset >= new_acc->acc_length)
- {
- offset -= new_acc->acc_length;
- new_acc= new_acc->acc_next;
-#ifdef BUF_TRACK_ALLOC_FREE
- assert(new_acc || (printf("called from %s, %d\n",
- clnt_file, clnt_line),0));
-#else
- assert(new_acc);
-#endif
- }
-
- /* Discard the old acc(s) */
- if (new_acc != data)
- {
- new_acc->acc_linkC++;
- bf_afree(data);
- data= new_acc;
- }
-
- /* Make sure that acc_linkC == 1 */
- if (data->acc_linkC != 1)
- {
- new_acc= bf_dupacc(data);
- bf_afree(data);
- data= new_acc;
- }
-
- /* Delete the last bit by modifying acc_offset and acc_length */
- data->acc_offset += offset;
- data->acc_length -= offset;
- return data;
-}
-
-/*
-bf_append
-*/
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_append(data_first, data_second)
-#else
-acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
-char *clnt_file;
-int clnt_line;
-#endif
-acc_t *data_first;
-acc_t *data_second;
-{
- acc_t *head, *tail, *new_acc, *acc_ptr_new, tmp_acc, *curr;
- char *src_ptr, *dst_ptr;
- size_t size, offset_old, offset_new, block_size_old, block_size;
-
- if (!data_first)
- return data_second;
- if (!data_second)
- return data_first;
-
- head= NULL;
- tail= NULL;
- while (data_first)
- {
- if (data_first->acc_linkC == 1)
- curr= data_first;
- else
- {
- curr= bf_dupacc(data_first);
- assert (curr->acc_linkC == 1);
- bf_afree(data_first);
- }
- data_first= curr->acc_next;
- if (!curr->acc_length)
- {
- curr->acc_next= NULL;
- bf_afree(curr);
- continue;
- }
- if (!head)
- head= curr;
- else
- tail->acc_next= curr;
- tail= curr;
- }
- if (!head)
- return data_second;
- tail->acc_next= NULL;
-
- while (data_second && !data_second->acc_length)
- {
- curr= data_second;
- data_second= data_second->acc_next;
- if (data_second)
- data_second->acc_linkC++;
- bf_afree(curr);
- }
- if (!data_second)
- return head;
-
- if (tail->acc_length + data_second->acc_length >
- tail->acc_buffer->buf_size)
- {
- tail->acc_next= data_second;
- return head;
- }
-
- if (tail->acc_buffer->buf_size == bf_buf_gran &&
- tail->acc_buffer->buf_linkC == 1)
- {
- if (tail->acc_offset)
- {
- memmove(tail->acc_buffer->buf_data_p,
- ptr2acc_data(tail), tail->acc_length);
- tail->acc_offset= 0;
- }
- dst_ptr= ptr2acc_data(tail) + tail->acc_length;
- src_ptr= ptr2acc_data(data_second);
- memcpy(dst_ptr, src_ptr, data_second->acc_length);
- tail->acc_length += data_second->acc_length;
- tail->acc_next= data_second->acc_next;
- if (data_second->acc_next)
- data_second->acc_next->acc_linkC++;
- bf_afree(data_second);
- return head;
- }
-
- new_acc= bf_small_memreq(tail->acc_length+data_second->acc_length);
- acc_ptr_new= new_acc;
- offset_old= 0;
- offset_new= 0;
- size= tail->acc_length;
- while (size)
- {
-assert (acc_ptr_new);
- if (offset_new == acc_ptr_new->acc_length)
- {
- offset_new= 0;
- acc_ptr_new= acc_ptr_new->acc_next;
- continue;
- }
-assert (offset_new < acc_ptr_new->acc_length);
-assert (offset_old < tail->acc_length);
- block_size_old= tail->acc_length - offset_old;
- block_size= acc_ptr_new->acc_length - offset_new;
- if (block_size > block_size_old)
- block_size= block_size_old;
- memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
- ptr2acc_data(tail)+offset_old, block_size);
- offset_new += block_size;
- offset_old += block_size;
- size -= block_size;
- }
- offset_old= 0;
- size= data_second->acc_length;
- while (size)
- {
-assert (acc_ptr_new);
- if (offset_new == acc_ptr_new->acc_length)
- {
- offset_new= 0;
- acc_ptr_new= acc_ptr_new->acc_next;
- continue;
- }
-assert (offset_new < acc_ptr_new->acc_length);
-assert (offset_old < data_second->acc_length);
- block_size_old= data_second->acc_length - offset_old;
- block_size= acc_ptr_new->acc_length - offset_new;
- if (block_size > block_size_old)
- block_size= block_size_old;
- memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
- ptr2acc_data(data_second)+offset_old, block_size);
- offset_new += block_size;
- offset_old += block_size;
- size -= block_size;
- }
- tmp_acc= *tail;
- *tail= *new_acc;
- *new_acc= tmp_acc;
-
- bf_afree(new_acc);
- while (tail->acc_next)
- tail= tail->acc_next;
-
- tail->acc_next= data_second->acc_next;
- if (data_second->acc_next)
- data_second->acc_next->acc_linkC++;
- bf_afree(data_second);
- return head;
-}
-
-#if BUF512_NR
-static void bf_512free(acc)
-acc_t *acc;
-{
-#ifdef BUF_CONSISTENCY_CHECK
- if (inet_buf_debug)
- memset(acc->acc_buffer->buf_data_p, 0xa5, 512);
-#endif
- acc->acc_next= buf512_freelist;
- buf512_freelist= acc;
-}
-#endif
-#if BUF2K_NR
-static void bf_2Kfree(acc)
-acc_t *acc;
-{
-#ifdef BUF_CONSISTENCY_CHECK
- if (inet_buf_debug)
- memset(acc->acc_buffer->buf_data_p, 0xa5, 2*1024);
-#endif
- acc->acc_next= buf2K_freelist;
- buf2K_freelist= acc;
-}
-#endif
-#if BUF32K_NR
-static void bf_32Kfree(acc)
-acc_t *acc;
-{
-#ifdef BUF_CONSISTENCY_CHECK
- if (inet_buf_debug)
- memset(acc->acc_buffer->buf_data_p, 0xa5, 32*1024);
-#endif
- acc->acc_next= buf32K_freelist;
- buf32K_freelist= acc;
-}
-#endif
-
-#ifdef BUF_CONSISTENCY_CHECK
-int bf_consistency_check()
-{
- acc_t *acc;
- int silent;
- int error;
- int i;
-
- buf_generation++;
-
- for (i=0; i<CLIENT_NR; i++)
- {
- if (checkreq[i])
- (*checkreq[i])();
- }
-
- /* Add information about free accessors */
- for(acc= acc_freelist; acc; acc= acc->acc_next)
- {
- if (acc->acc_generation == buf_generation-1)
- {
- acc->acc_generation= buf_generation;
- acc->acc_check_linkC= 0;
- }
- else
- {
- assert(acc->acc_generation == buf_generation &&
- acc->acc_check_linkC > 0);
- acc->acc_check_linkC= -acc->acc_check_linkC;
- }
- }
-
-#if BUF512_NR
- count_free_bufs(buf512_freelist);
-#endif
-#if BUF2K_NR
- count_free_bufs(buf2K_freelist);
-#endif
-#if BUF32K_NR
- count_free_bufs(buf32K_freelist);
-#endif
-
- error= 0;
-
- /* Report about accessors */
- silent= 0;
- for (i=0, acc= accessors; i<ACC_NR; i++, acc++)
- {
- if (acc->acc_generation != buf_generation)
- {
- error++;
- assert(acc->acc_generation == buf_generation-1);
- acc->acc_generation= buf_generation;
- if (!silent)
- {
- printf(
-"acc[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
- i, acc, acc->acc_linkC, acc->acc_alloc_file, acc->acc_alloc_line);
-#if 0
- silent= 1;
-#endif
- }
- continue;
- }
- if (acc->acc_check_linkC == acc->acc_linkC)
- continue;
- error++;
- if (acc->acc_check_linkC < 0)
- {
- if (!silent)
- {
- printf(
-"acc[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
- i, acc->acc_alloc_file, acc->acc_alloc_line,
- acc->acc_free_file, acc->acc_free_line);
- }
- acc->acc_check_linkC= -acc->acc_check_linkC;
- if (acc->acc_check_linkC == acc->acc_linkC)
- {
- silent= 1;
- continue;
- }
- }
- if (!silent)
- {
- printf(
-"# of tracked links (%d) for acc[%d] don't match with stored link count %d\n",
- acc->acc_check_linkC, i, acc->acc_linkC);
- printf("acc[%d] was allocated at %s, %d\n",
- i, acc->acc_alloc_file, acc->acc_alloc_line);
- silent=1;
- }
- }
-
- /* Report about buffers */
-#if BUF512_NR
- {
- for (i= 0; i<BUF512_NR; i++)
- {
- error |= report_buffer(&buffers512[i].buf_header,
- "512-buffer", i);
- }
- }
-#endif
-#if BUF2K_NR
- {
- for (i= 0; i<BUF2K_NR; i++)
- {
- error |= report_buffer(&buffers2K[i].buf_header,
- "2K-buffer", i);
- }
- }
-#endif
-#if BUF32K_NR
- {
- for (i= 0; i<BUF32K_NR; i++)
- {
- error |= report_buffer(&buffers32K[i].buf_header,
- "32K-buffer", i);
- }
- }
-#endif
-
- return !error;
-}
-
-static void count_free_bufs(list)
-acc_t *list;
-{
- acc_t *acc;
- buf_t *buf;
-
- for(acc= list; acc; acc= acc->acc_next)
- {
- if (acc->acc_generation != buf_generation-1)
- {
- assert(acc->acc_generation == buf_generation &&
- acc->acc_check_linkC > 0);
- acc->acc_check_linkC= -acc->acc_check_linkC;
- continue;
- }
- acc->acc_generation= buf_generation;
- acc->acc_check_linkC= 0;
-
- buf= acc->acc_buffer;
- if (buf->buf_generation == buf_generation-1)
- {
- buf->buf_generation= buf_generation;
- buf->buf_check_linkC= 0;
- continue;
- }
- assert(buf->buf_generation == buf_generation &&
- buf->buf_check_linkC > 0);
- buf->buf_check_linkC= -buf->buf_check_linkC;
- }
-}
-
-static int report_buffer(buf, label, i)
-buf_t *buf;
-char *label;
-int i;
-{
- if (buf->buf_generation != buf_generation)
- {
- assert(buf->buf_generation == buf_generation-1);
- buf->buf_generation= buf_generation;
- printf(
-"%s[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
- label, i, buf,
- buf->buf_linkC, buf->buf_alloc_file,
- buf->buf_alloc_line);
- return 1;
- }
- if (buf->buf_check_linkC == buf->buf_linkC)
- return 0;
- if (buf->buf_check_linkC < 0)
- {
- printf(
-"%s[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
- label, i, buf->buf_alloc_file, buf->buf_alloc_line,
- buf->buf_free_file, buf->buf_free_line);
- buf->buf_check_linkC= -buf->buf_check_linkC;
- if (buf->buf_check_linkC == buf->buf_linkC)
- return 1;
- }
- printf(
-"# of tracked links (%d) for %s[%d] don't match with stored link count %d\n",
- buf->buf_check_linkC, label, i, buf->buf_linkC);
- printf("%s[%d] was allocated at %s, %d\n",
- label, i, buf->buf_alloc_file, buf->buf_alloc_line);
- return 1;
-}
-
-void bf_check_acc(acc)
-acc_t *acc;
-{
- buf_t *buf;
-
- while(acc != NULL)
- {
- if (acc->acc_generation == buf_generation)
- {
- assert(acc->acc_check_linkC > 0);
- acc->acc_check_linkC++;
- return;
- }
- assert(acc->acc_generation == buf_generation-1);
- acc->acc_generation= buf_generation;
- acc->acc_check_linkC= 1;
-
- buf= acc->acc_buffer;
- if (buf->buf_generation == buf_generation)
- {
- assert(buf->buf_check_linkC > 0);
- buf->buf_check_linkC++;
- }
- else
- {
- assert(buf->buf_generation == buf_generation-1);
- buf->buf_generation= buf_generation;
- buf->buf_check_linkC= 1;
- }
-
- acc= acc->acc_next;
- }
-}
-
-void _bf_mark_1acc(clnt_file, clnt_line, acc)
-char *clnt_file;
-int clnt_line;
-acc_t *acc;
-{
- acc->acc_alloc_file= clnt_file;
- acc->acc_alloc_line= clnt_line;
-}
-
-void _bf_mark_acc(clnt_file, clnt_line, acc)
-char *clnt_file;
-int clnt_line;
-acc_t *acc;
-{
- buf_t *buf;
-
- for (; acc; acc= acc->acc_next)
- {
- acc->acc_alloc_file= clnt_file;
- acc->acc_alloc_line= clnt_line;
- buf= acc->acc_buffer;
- buf->buf_alloc_file= clnt_file;
- buf->buf_alloc_line= clnt_line;
- }
-}
-#endif
-
-int bf_linkcheck(acc)
-acc_t *acc;
-{
- int i;
-
- buf_t *buffer;
- for (i= 0; i<ACC_NR && acc; i++, acc= acc->acc_next)
- {
- if (acc->acc_linkC <= 0)
- {
- printf("wrong acc_linkC (%d) for acc %p\n",
- acc->acc_linkC, acc);
- return 0;
- }
- if (acc->acc_offset < 0)
- {
- printf("wrong acc_offset (%d) for acc %p\n",
- acc->acc_offset, acc);
- return 0;
- }
- if (acc->acc_length < 0)
- {
- printf("wrong acc_length (%d) for acc %p\n",
- acc->acc_length, acc);
- return 0;
- }
- buffer= acc->acc_buffer;
- if (buffer == NULL)
- {
- printf("no buffer for acc %p\n", acc);
- return 0;
- }
- if (buffer->buf_linkC <= 0)
- {
- printf(
- "wrong buf_linkC (%d) for buffer %p, from acc %p\n",
- buffer->buf_linkC, buffer, acc);
- return 0;
- }
- if (acc->acc_offset + acc->acc_length > buffer->buf_size)
- {
- printf("%d + %d > %zu for buffer %p, and acc %p\n",
- acc->acc_offset, acc->acc_length,
- buffer->buf_size, buffer, acc);
- return 0;
- }
- }
- if (acc != NULL)
- {
- printf("loop\n");
- return 0;
- }
- return 1;
-}
-
-static void free_accs()
-{
- int i, j;
-
- DBLOCK(1, printf("free_accs\n"));
-
-assert(bf_linkcheck(bf_linkcheck_acc));
- for (i=0; !acc_freelist && i<MAX_BUFREQ_PRI; i++)
- {
- for (j=0; j<CLIENT_NR; j++)
- {
- bf_free_bufsize= 0;
- if (freereq[j])
- {
- (*freereq[j])(i);
- assert(bf_linkcheck(bf_linkcheck_acc) ||
- (printf("just called %p\n",
- freereq[i]),0));
- }
- }
- }
-#if DEBUG
- printf("last level was level %d\n", i-1);
-#endif
-}
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_align(acc, size, alignment)
-#else
-acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
-char *clnt_file;
-int clnt_line;
-#endif
-acc_t *acc;
-size_t size;
-size_t alignment;
-{
- char *ptr;
- size_t buf_size;
- acc_t *head, *tail;
-
- /* Fast check if the buffer is aligned already. */
- if (acc->acc_length >= size)
- {
- ptr= ptr2acc_data(acc);
- if (((unsigned)ptr & (alignment-1)) == 0)
- return acc;
- }
- buf_size= bf_bufsize(acc);
-#ifdef bf_align
- assert((size != 0 && buf_size != 0) ||
- (printf("bf_align(..., %d, %d) from %s, %d\n",
- size, alignment, clnt_file, clnt_line),0));
-#else
- assert(size != 0 && buf_size != 0);
-#endif
- if (buf_size <= size)
- {
- acc= bf_pack(acc);
- return acc;
- }
- head= bf_cut(acc, 0, size);
- tail= bf_cut(acc, size, buf_size-size);
- bf_afree(acc);
- head= bf_pack(head);
- assert(head->acc_next == NULL);
- head->acc_next= tail;
- return head;
-}
-
-#if 0
-int chk_acc(acc)
-acc_t *acc;
-{
- int acc_nr;
-
- if (!acc)
- return 1;
- if (acc < accessors || acc >= &accessors[ACC_NR])
- return 0;
- acc_nr= acc-accessors;
- return acc == &accessors[acc_nr];
-}
-#endif
-
-/*
- * $PchId: buf.c,v 1.19 2003/09/10 08:54:23 philip Exp $
- */
+++ /dev/null
-/*
-clock.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "proto.h"
-#include "generic/assert.h"
-#include "generic/buf.h"
-#include "generic/clock.h"
-
-THIS_FILE
-
-int clck_call_expire;
-
-static clock_t curr_time;
-static clock_t prev_time;
-static minix_timer_t *timer_chain;
-static time_t next_timeout;
-
-static void clck_fast_release(minix_timer_t *timer);
-static void set_timer(void);
-
-void clck_init()
-{
- clck_call_expire= 0;
- curr_time= 0;
- prev_time= 0;
- next_timeout= 0;
- timer_chain= 0;
-}
-
-time_t get_time()
-{
- if (!curr_time)
- {
- curr_time = getticks();
- assert(curr_time >= prev_time); /* XXX */
- }
- return curr_time;
-}
-
-void set_time (tim)
-clock_t tim;
-{
- if (!curr_time && tim >= prev_time)
- {
- /* Some code assumes that no time elapses while it is
- * running.
- */
- curr_time= tim;
- }
- else if (!curr_time)
- {
- DBLOCK(0x20, printf("set_time: new time %u < prev_time %u\n",
- tim, prev_time));
- }
-}
-
-void reset_time()
-{
- prev_time= curr_time;
- curr_time= 0;
-}
-
-void clck_timer(timer, timeout, func, fd)
-minix_timer_t *timer;
-time_t timeout;
-timer_func_t func;
-int fd;
-{
- minix_timer_t *timer_index;
-
- if (timer->tim_active)
- clck_fast_release(timer);
- assert(!timer->tim_active);
-
- timer->tim_next= 0;
- timer->tim_func= func;
- timer->tim_ref= fd;
- timer->tim_time= timeout;
- timer->tim_active= 1;
-
- if (!timer_chain)
- timer_chain= timer;
- else if (timeout < timer_chain->tim_time)
- {
- timer->tim_next= timer_chain;
- timer_chain= timer;
- }
- else
- {
- timer_index= timer_chain;
- while (timer_index->tim_next &&
- timer_index->tim_next->tim_time < timeout)
- timer_index= timer_index->tim_next;
- timer->tim_next= timer_index->tim_next;
- timer_index->tim_next= timer;
- }
- if (next_timeout == 0 || timer_chain->tim_time < next_timeout)
- set_timer();
-}
-
-void clck_tick (mess)
-message *mess;
-{
- next_timeout= 0;
- set_timer();
-}
-
-static void clck_fast_release (timer)
-minix_timer_t *timer;
-{
- minix_timer_t *timer_index;
-
- if (!timer->tim_active)
- return;
-
- if (timer == timer_chain)
- timer_chain= timer_chain->tim_next;
- else
- {
- timer_index= timer_chain;
- while (timer_index && timer_index->tim_next != timer)
- timer_index= timer_index->tim_next;
- assert(timer_index);
- timer_index->tim_next= timer->tim_next;
- }
- timer->tim_active= 0;
-}
-
-static void set_timer()
-{
- time_t new_time;
- time_t now;
-
- if (!timer_chain)
- return;
-
- now= get_time();
- new_time= timer_chain->tim_time;
- if (new_time <= now)
- {
- clck_call_expire= 1;
- return;
- }
-
- if (next_timeout == 0 || new_time < next_timeout)
- {
- next_timeout= new_time;
- new_time -= now;
-
- if (sys_setalarm(new_time, 0) != OK)
- ip_panic(("can't set timer"));
- }
-}
-
-void clck_untimer (timer)
-minix_timer_t *timer;
-{
- clck_fast_release (timer);
- set_timer();
-}
-
-void clck_expire_timers()
-{
- time_t now;
- minix_timer_t *timer_index;
-
- clck_call_expire= 0;
-
- if (timer_chain == NULL)
- return;
-
- now= get_time();
- while (timer_chain && timer_chain->tim_time<=now)
- {
- assert(timer_chain->tim_active);
- timer_chain->tim_active= 0;
- timer_index= timer_chain;
- timer_chain= timer_chain->tim_next;
- (*timer_index->tim_func)(timer_index->tim_ref, timer_index);
- }
- set_timer();
-}
-
-/*
- * $PchId: clock.c,v 1.10 2005/06/28 14:23:40 philip Exp $
- */
+++ /dev/null
-/*
-inet/const.h
-
-Created: Dec 30, 1991 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__CONST_H
-#define INET__CONST_H
-
-#ifndef DEBUG
-#define DEBUG 0
-#endif
-
-#ifndef NDEBUG
-#define NDEBUG 0
-#endif
-
-#define CLOCK_GRAN 1 /* in HZ */
-
-#define where() printf("%s, %d: ", __FILE__, __LINE__)
-
-#define NW_SUSPEND SUSPEND
-#define NW_WOULDBLOCK EWOULDBLOCK
-#define NW_OK OK
-
-#define BUF_S 512
-
-#endif /* INET__CONST_H */
-
-/*
- * $PchId: const.h,v 1.7 2000/08/12 09:21:44 philip Exp $
- */
+++ /dev/null
-/*
-arp.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "type.h"
-
-#include "arp.h"
-#include "assert.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "eth.h"
-#include "io.h"
-
-THIS_FILE
-
-#define ARP_CACHE_NR 256
-#define AP_REQ_NR 32
-
-#define ARP_HASH_NR 256
-#define ARP_HASH_MASK 0xff
-#define ARP_HASH_WIDTH 4
-
-#define MAX_ARP_RETRIES 5
-#define ARP_TIMEOUT (HZ/2+1) /* .5 seconds */
-#ifndef ARP_EXP_TIME
-#define ARP_EXP_TIME (20L*60L*HZ) /* 20 minutes */
-#endif
-#define ARP_NOTRCH_EXP_TIME (30*HZ) /* 30 seconds */
-#define ARP_INUSE_OFFSET (60*HZ) /* an entry in the cache can be deleted
- if its not used for 1 minute */
-
-typedef struct arp46
-{
- ether_addr_t a46_dstaddr;
- ether_addr_t a46_srcaddr;
- ether_type_t a46_ethtype;
- union ixfer_arp46_u
- {
- struct
- {
- u16_t a_hdr, a_pro;
- u8_t a_hln, a_pln;
- u16_t a_op;
- ether_addr_t a_sha;
- u8_t a_spa[4];
- ether_addr_t a_tha;
- u8_t a_tpa[4];
- } a46_data;
- char a46_dummy[ETH_MIN_PACK_SIZE-ETH_HDR_SIZE];
- } a46_data;
-} arp46_t;
-
-#define a46_hdr a46_data.a46_data.a_hdr
-#define a46_pro a46_data.a46_data.a_pro
-#define a46_hln a46_data.a46_data.a_hln
-#define a46_pln a46_data.a46_data.a_pln
-#define a46_op a46_data.a46_data.a_op
-#define a46_sha a46_data.a46_data.a_sha
-#define a46_spa a46_data.a46_data.a_spa
-#define a46_tha a46_data.a46_data.a_tha
-#define a46_tpa a46_data.a46_data.a_tpa
-
-typedef struct arp_port
-{
- int ap_flags;
- int ap_state;
- int ap_eth_port;
- int ap_ip_port;
- int ap_eth_fd;
-
- ether_addr_t ap_ethaddr; /* Ethernet address of this port */
- ipaddr_t ap_ipaddr; /* IP address of this port */
-
- struct arp_req
- {
- minix_timer_t ar_timer;
- int ar_entry;
- int ar_req_count;
- } ap_req[AP_REQ_NR];
-
- arp_func_t ap_arp_func;
-
- acc_t *ap_sendpkt;
- acc_t *ap_sendlist;
- acc_t *ap_reclist;
- event_t ap_event;
-} arp_port_t;
-
-#define APF_EMPTY 0x00
-#define APF_ARP_RD_IP 0x01
-#define APF_ARP_RD_SP 0x02
-#define APF_ARP_WR_IP 0x04
-#define APF_ARP_WR_SP 0x08
-#define APF_INADDR_SET 0x10
-#define APF_SUSPEND 0x20
-
-#define APS_INITIAL 1
-#define APS_GETADDR 2
-#define APS_ARPSTART 3
-#define APS_ARPPROTO 4
-#define APS_ARPMAIN 5
-#define APS_ERROR 6
-
-typedef struct arp_cache
-{
- int ac_flags;
- int ac_state;
- ether_addr_t ac_ethaddr;
- ipaddr_t ac_ipaddr;
- arp_port_t *ac_port;
- time_t ac_expire;
- time_t ac_lastuse;
-} arp_cache_t;
-
-#define ACF_EMPTY 0
-#define ACF_PERM 1
-#define ACF_PUB 2
-
-#define ACS_UNUSED 0
-#define ACS_INCOMPLETE 1
-#define ACS_VALID 2
-#define ACS_UNREACHABLE 3
-
-static struct arp_hash_ent
-{
- arp_cache_t *ahe_row[ARP_HASH_WIDTH];
-} arp_hash[ARP_HASH_NR];
-
-static arp_port_t *arp_port_table;
-static arp_cache_t *arp_cache;
-static int arp_cache_nr;
-
-static acc_t *arp_getdata ARGS(( int fd, size_t offset,
- size_t count, int for_ioctl ));
-static int arp_putdata ARGS(( int fd, size_t offset,
- acc_t *data, int for_ioctl ));
-static void arp_main ARGS(( arp_port_t *arp_port ));
-static void arp_timeout ARGS(( int ref, minix_timer_t *timer ));
-static void setup_write ARGS(( arp_port_t *arp_port ));
-static void setup_read ARGS(( arp_port_t *arp_port ));
-static void do_reclist ARGS(( event_t *ev, ev_arg_t ev_arg ));
-static void process_arp_pkt ARGS(( arp_port_t *arp_port, acc_t *data ));
-static void client_reply ARGS(( arp_port_t *arp_port,
- ipaddr_t ipaddr, ether_addr_t *ethaddr ));
-static arp_cache_t *find_cache_ent ARGS(( arp_port_t *arp_port,
- ipaddr_t ipaddr ));
-static arp_cache_t *alloc_cache_ent ARGS(( int flags ));
-static void arp_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void arp_bufcheck ARGS(( void ));
-#endif
-
-void arp_prep()
-{
- arp_port_table= alloc(eth_conf_nr * sizeof(arp_port_table[0]));
-
- arp_cache_nr= ARP_CACHE_NR;
- if (arp_cache_nr < (eth_conf_nr+1)*AP_REQ_NR)
- {
- arp_cache_nr= (eth_conf_nr+1)*AP_REQ_NR;
- printf("arp: using %d cache entries instead of %d\n",
- arp_cache_nr, ARP_CACHE_NR);
- }
- arp_cache= alloc(arp_cache_nr * sizeof(arp_cache[0]));
-}
-
-void arp_init()
-{
- arp_port_t *arp_port;
- arp_cache_t *cache;
- int i;
-
- assert (BUF_S >= sizeof(struct nwio_ethstat));
- assert (BUF_S >= sizeof(struct nwio_ethopt));
- assert (BUF_S >= sizeof(arp46_t));
-
- for (i=0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
- {
- arp_port->ap_state= APS_ERROR; /* Mark all ports as
- * unavailable */
- }
-
- cache= arp_cache;
- for (i=0; i<arp_cache_nr; i++, cache++)
- {
- cache->ac_state= ACS_UNUSED;
- cache->ac_flags= ACF_EMPTY;
- cache->ac_expire= 0;
- cache->ac_lastuse= 0;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(arp_buffree);
-#else
- bf_logon(arp_buffree, arp_bufcheck);
-#endif
-}
-
-static void arp_main(arp_port)
-arp_port_t *arp_port;
-{
- int result;
-
- switch (arp_port->ap_state)
- {
- case APS_INITIAL:
- arp_port->ap_eth_fd= eth_open(arp_port->ap_eth_port,
- arp_port->ap_eth_port, arp_getdata, arp_putdata,
- 0 /* no put_pkt */, 0 /* no select_res */);
-
- if (arp_port->ap_eth_fd<0)
- {
- DBLOCK(1, printf("arp[%d]: unable to open eth[%d]\n",
- arp_port-arp_port_table,
- arp_port->ap_eth_port));
- return;
- }
-
- arp_port->ap_state= APS_GETADDR;
-
- result= eth_ioctl (arp_port->ap_eth_fd, NWIOGETHSTAT);
-
- if ( result == NW_SUSPEND)
- {
- arp_port->ap_flags |= APF_SUSPEND;
- return;
- }
- assert(result == NW_OK);
-
- /* fall through */
- case APS_GETADDR:
- /* Wait for IP address */
- if (!(arp_port->ap_flags & APF_INADDR_SET))
- return;
-
- /* fall through */
- case APS_ARPSTART:
- arp_port->ap_state= APS_ARPPROTO;
-
- result= eth_ioctl (arp_port->ap_eth_fd, NWIOSETHOPT);
-
- if (result==NW_SUSPEND)
- {
- arp_port->ap_flags |= APF_SUSPEND;
- return;
- }
- assert(result == NW_OK);
-
- /* fall through */
- case APS_ARPPROTO:
- arp_port->ap_state= APS_ARPMAIN;
- setup_write(arp_port);
- setup_read(arp_port);
- return;
-
- default:
- ip_panic((
- "arp_main(&arp_port_table[%d]) called but ap_state=0x%x\n",
- arp_port->ap_eth_port, arp_port->ap_state ));
- }
-}
-
-static acc_t *arp_getdata (fd, offset, count, for_ioctl)
-int fd;
-size_t offset;
-size_t count;
-int for_ioctl;
-{
- arp_port_t *arp_port;
- acc_t *data;
- int result;
-
- arp_port= &arp_port_table[fd];
-
- switch (arp_port->ap_state)
- {
- case APS_ARPPROTO:
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- {
- arp_port->ap_state= APS_ERROR;
- break;
- }
- if (arp_port->ap_flags & APF_SUSPEND)
- {
- arp_port->ap_flags &= ~APF_SUSPEND;
- arp_main(arp_port);
- }
- return NW_OK;
- }
- assert ((!offset) && (count == sizeof(struct nwio_ethopt)));
- {
- struct nwio_ethopt *ethopt;
- acc_t *acc;
-
- acc= bf_memreq(sizeof(*ethopt));
- ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);
- ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|
- NWEO_TYPESPEC;
- ethopt->nweo_type= HTONS(ETH_ARP_PROTO);
- return acc;
- }
- case APS_ARPMAIN:
- assert (arp_port->ap_flags & APF_ARP_WR_IP);
- if (!count)
- {
- data= arp_port->ap_sendpkt;
- arp_port->ap_sendpkt= NULL;
- assert(data);
- bf_afree(data); data= NULL;
-
- result= (int)offset;
- if (result<0)
- {
- DIFBLOCK(1, (result != NW_SUSPEND),
- printf(
- "arp[%d]: write error on port %d: error %d\n",
- fd, arp_port->ap_eth_fd, result));
-
- arp_port->ap_state= APS_ERROR;
- break;
- }
- arp_port->ap_flags &= ~APF_ARP_WR_IP;
- if (arp_port->ap_flags & APF_ARP_WR_SP)
- setup_write(arp_port);
- return NW_OK;
- }
- assert (offset+count <= sizeof(arp46_t));
- data= arp_port->ap_sendpkt;
- assert(data);
- data= bf_cut(data, offset, count);
-
- return data;
- default:
- printf("arp_getdata(%d, 0x%d, 0x%d) called but ap_state=0x%x\n",
- fd, offset, count, arp_port->ap_state);
- break;
- }
- return 0;
-}
-
-static int arp_putdata (fd, offset, data, for_ioctl)
-int fd;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- arp_port_t *arp_port;
- int result;
- struct nwio_ethstat *ethstat;
- ev_arg_t ev_arg;
- acc_t *tmpacc;
-
- arp_port= &arp_port_table[fd];
-
- if (arp_port->ap_flags & APF_ARP_RD_IP)
- {
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- DIFBLOCK(1, (result != NW_SUSPEND), printf(
- "arp[%d]: read error on port %d: error %d\n",
- fd, arp_port->ap_eth_fd, result));
-
- return NW_OK;
- }
- if (arp_port->ap_flags & APF_ARP_RD_SP)
- {
- arp_port->ap_flags &= ~(APF_ARP_RD_IP|
- APF_ARP_RD_SP);
- setup_read(arp_port);
- }
- else
- arp_port->ap_flags &= ~(APF_ARP_RD_IP|
- APF_ARP_RD_SP);
- return NW_OK;
- }
- assert (!offset);
- /* Warning: the above assertion is illegal; puts and gets of
- data can be brokenup in any piece the server likes. However
- we assume that the server is eth.c and it transfers only
- whole packets.
- */
- data= bf_packIffLess(data, sizeof(arp46_t));
- if (data->acc_length >= sizeof(arp46_t))
- {
- if (!arp_port->ap_reclist)
- {
- ev_arg.ev_ptr= arp_port;
- ev_enqueue(&arp_port->ap_event, do_reclist,
- ev_arg);
- }
- if (data->acc_linkC != 1)
- {
- tmpacc= bf_dupacc(data);
- bf_afree(data);
- data= tmpacc;
- tmpacc= NULL;
- }
- data->acc_ext_link= arp_port->ap_reclist;
- arp_port->ap_reclist= data;
- }
- else
- bf_afree(data);
- return NW_OK;
- }
- switch (arp_port->ap_state)
- {
- case APS_GETADDR:
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- arp_port->ap_state= APS_ERROR;
- break;
- }
- if (arp_port->ap_flags & APF_SUSPEND)
- {
- arp_port->ap_flags &= ~APF_SUSPEND;
- arp_main(arp_port);
- }
- return NW_OK;
- }
- compare (bf_bufsize(data), ==, sizeof(*ethstat));
- data= bf_packIffLess(data, sizeof(*ethstat));
- compare (data->acc_length, ==, sizeof(*ethstat));
- ethstat= (struct nwio_ethstat *)ptr2acc_data(data);
- arp_port->ap_ethaddr= ethstat->nwes_addr;
- bf_afree(data);
- return NW_OK;
- default:
- printf("arp_putdata(%d, 0x%d, 0x%lx) called but ap_state=0x%x\n",
- fd, offset, (unsigned long)data, arp_port->ap_state);
- break;
- }
- return EGENERIC;
-}
-
-static void setup_read(arp_port)
-arp_port_t *arp_port;
-{
- int result;
-
- while (!(arp_port->ap_flags & APF_ARP_RD_IP))
- {
- arp_port->ap_flags |= APF_ARP_RD_IP;
- result= eth_read (arp_port->ap_eth_fd, ETH_MAX_PACK_SIZE);
- if (result == NW_SUSPEND)
- {
- arp_port->ap_flags |= APF_ARP_RD_SP;
- return;
- }
- DIFBLOCK(1, (result != NW_OK),
- printf("arp[%d]: eth_read(..,%d)=%d\n",
- arp_port-arp_port_table, ETH_MAX_PACK_SIZE, result));
- }
-}
-
-static void setup_write(arp_port)
-arp_port_t *arp_port;
-{
- int result;
- acc_t *data;
-
- for(;;)
- {
- data= arp_port->ap_sendlist;
- if (!data)
- break;
- arp_port->ap_sendlist= data->acc_ext_link;
-
- if (arp_port->ap_ipaddr == HTONL(0x00000000))
- {
- /* Interface is down */
- printf(
- "arp[%d]: not sending ARP packet, interface is down\n",
- arp_port-arp_port_table);
- bf_afree(data); data= NULL;
- continue;
- }
-
- assert(!arp_port->ap_sendpkt);
- arp_port->ap_sendpkt= data; data= NULL;
-
- arp_port->ap_flags= (arp_port->ap_flags & ~APF_ARP_WR_SP) |
- APF_ARP_WR_IP;
- result= eth_write(arp_port->ap_eth_fd, sizeof(arp46_t));
- if (result == NW_SUSPEND)
- {
- arp_port->ap_flags |= APF_ARP_WR_SP;
- break;
- }
- if (result<0)
- {
- DIFBLOCK(1, (result != NW_SUSPEND),
- printf("arp[%d]: eth_write(..,%d)=%d\n",
- arp_port-arp_port_table, sizeof(arp46_t),
- result));
- return;
- }
- }
-}
-
-static void do_reclist(ev, ev_arg)
-event_t *ev;
-ev_arg_t ev_arg;
-{
- arp_port_t *arp_port;
- acc_t *data;
-
- arp_port= ev_arg.ev_ptr;
- assert(ev == &arp_port->ap_event);
-
- while (data= arp_port->ap_reclist, data != NULL)
- {
- arp_port->ap_reclist= data->acc_ext_link;
- process_arp_pkt(arp_port, data);
- bf_afree(data);
- }
-}
-
-static void process_arp_pkt (arp_port, data)
-arp_port_t *arp_port;
-acc_t *data;
-{
- int i, entry, do_reply;
- arp46_t *arp;
- u16_t *p;
- arp_cache_t *ce, *cache;
- struct arp_req *reqp;
- time_t curr_time;
- ipaddr_t spa, tpa;
-
- curr_time= get_time();
-
- arp= (arp46_t *)ptr2acc_data(data);
- memcpy(&spa, arp->a46_spa, sizeof(ipaddr_t));
- memcpy(&tpa, arp->a46_tpa, sizeof(ipaddr_t));
-
- if (arp->a46_hdr != HTONS(ARP_ETHERNET) ||
- arp->a46_hln != 6 ||
- arp->a46_pro != HTONS(ETH_IP_PROTO) ||
- arp->a46_pln != 4)
- return;
- if (arp_port->ap_ipaddr == HTONL(0x00000000))
- {
- /* Interface is down */
-#if DEBUG
- printf("arp[%d]: dropping ARP packet, interface is down\n",
- arp_port-arp_port_table);
-#endif
- return;
- }
-
- ce= find_cache_ent(arp_port, spa);
- cache= NULL; /* lint */
-
- do_reply= 0;
- if (arp->a46_op != HTONS(ARP_REQUEST))
- ; /* No need to reply */
- else if (tpa == arp_port->ap_ipaddr)
- do_reply= 1;
- else
- {
- /* Look for a published entry */
- cache= find_cache_ent(arp_port, tpa);
- if (cache)
- {
- if (cache->ac_flags & ACF_PUB)
- {
- /* Published entry */
- do_reply= 1;
- }
- else
- {
- /* Nothing to do */
- cache= NULL;
- }
- }
- }
-
- if (ce == NULL)
- {
- if (!do_reply)
- return;
-
- DBLOCK(0x10, printf("arp[%d]: allocating entry for ",
- arp_port-arp_port_table);
- writeIpAddr(spa); printf("\n"));
-
- ce= alloc_cache_ent(ACF_EMPTY);
- ce->ac_flags= ACF_EMPTY;
- ce->ac_state= ACS_VALID;
- ce->ac_ethaddr= arp->a46_sha;
- ce->ac_ipaddr= spa;
- ce->ac_port= arp_port;
- ce->ac_expire= curr_time+ARP_EXP_TIME;
- ce->ac_lastuse= curr_time-ARP_INUSE_OFFSET; /* never used */
- }
-
- if (ce->ac_state == ACS_INCOMPLETE || ce->ac_state == ACS_UNREACHABLE)
- {
- ce->ac_ethaddr= arp->a46_sha;
- if (ce->ac_state == ACS_INCOMPLETE)
- {
- /* Find request entry */
- entry= ce-arp_cache;
- for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR;
- i++, reqp++)
- {
- if (reqp->ar_entry == entry)
- break;
- }
- assert(i < AP_REQ_NR);
- clck_untimer(&reqp->ar_timer);
- reqp->ar_entry= -1;
-
- ce->ac_state= ACS_VALID;
- client_reply(arp_port, spa, &arp->a46_sha);
- }
- else
- ce->ac_state= ACS_VALID;
- }
-
- /* Update fields in the arp cache. */
- if (memcmp(&ce->ac_ethaddr, &arp->a46_sha,
- sizeof(ce->ac_ethaddr)) != 0)
- {
- printf("arp[%d]: ethernet address for IP address ",
- arp_port-arp_port_table);
- writeIpAddr(spa);
- printf(" changed from ");
- writeEtherAddr(&ce->ac_ethaddr);
- printf(" to ");
- writeEtherAddr(&arp->a46_sha);
- printf("\n");
- ce->ac_ethaddr= arp->a46_sha;
- }
- ce->ac_expire= curr_time+ARP_EXP_TIME;
-
- if (do_reply)
- {
- data= bf_memreq(sizeof(arp46_t));
- arp= (arp46_t *)ptr2acc_data(data);
-
- /* Clear padding */
- assert(sizeof(arp->a46_data.a46_dummy) % sizeof(*p) == 0);
- for (i= 0, p= (u16_t *)arp->a46_data.a46_dummy;
- i < sizeof(arp->a46_data.a46_dummy)/sizeof(*p);
- i++, p++)
- {
- *p= 0xdead;
- }
-
- arp->a46_dstaddr= ce->ac_ethaddr;
- arp->a46_hdr= HTONS(ARP_ETHERNET);
- arp->a46_pro= HTONS(ETH_IP_PROTO);
- arp->a46_hln= 6;
- arp->a46_pln= 4;
-
- arp->a46_op= htons(ARP_REPLY);
- if (tpa == arp_port->ap_ipaddr)
- {
- arp->a46_sha= arp_port->ap_ethaddr;
- }
- else
- {
- assert(cache);
- arp->a46_sha= cache->ac_ethaddr;
- }
- memcpy (arp->a46_spa, &tpa, sizeof(ipaddr_t));
- arp->a46_tha= ce->ac_ethaddr;
- memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));
-
- assert(data->acc_linkC == 1);
- data->acc_ext_link= arp_port->ap_sendlist;
- arp_port->ap_sendlist= data; data= NULL;
-
- if (!(arp_port->ap_flags & APF_ARP_WR_IP))
- setup_write(arp_port);
- }
-}
-
-static void client_reply (arp_port, ipaddr, ethaddr)
-arp_port_t *arp_port;
-ipaddr_t ipaddr;
-ether_addr_t *ethaddr;
-{
- (*arp_port->ap_arp_func)(arp_port->ap_ip_port, ipaddr, ethaddr);
-}
-
-static arp_cache_t *find_cache_ent (arp_port, ipaddr)
-arp_port_t *arp_port;
-ipaddr_t ipaddr;
-{
- arp_cache_t *ce;
- int i;
- unsigned hash;
-
- hash= (ipaddr >> 24) ^ (ipaddr >> 16) ^ (ipaddr >> 8) ^ ipaddr;
- hash &= ARP_HASH_MASK;
-
- ce= arp_hash[hash].ahe_row[0];
- if (ce && ce->ac_ipaddr == ipaddr && ce->ac_port == arp_port &&
- ce->ac_state != ACS_UNUSED)
- {
- return ce;
- }
- for (i= 1; i<ARP_HASH_WIDTH; i++)
- {
- ce= arp_hash[hash].ahe_row[i];
- if (!ce || ce->ac_ipaddr != ipaddr || ce->ac_port != arp_port
- || ce->ac_state == ACS_UNUSED)
- {
- continue;
- }
- arp_hash[hash].ahe_row[i]= arp_hash[hash].ahe_row[0];
- arp_hash[hash].ahe_row[0]= ce;
- return ce;
- }
-
- for (i=0, ce= arp_cache; i<arp_cache_nr; i++, ce++)
- {
- if (ce->ac_state != ACS_UNUSED &&
- ce->ac_port == arp_port &&
- ce->ac_ipaddr == ipaddr)
- {
- for (i= ARP_HASH_WIDTH-1; i>0; i--)
- {
- arp_hash[hash].ahe_row[i]=
- arp_hash[hash].ahe_row[i-1];
- }
- assert(i == 0);
- arp_hash[hash].ahe_row[0]= ce;
- return ce;
- }
- }
- return NULL;
-}
-
-static arp_cache_t *alloc_cache_ent(flags)
-int flags;
-{
- arp_cache_t *cache, *old;
- int i;
-
- old= NULL;
- for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
- {
- if (cache->ac_state == ACS_UNUSED)
- {
- old= cache;
- break;
- }
- if (cache->ac_state == ACS_INCOMPLETE)
- continue;
- if (cache->ac_flags & ACF_PERM)
- continue;
- if (!old || cache->ac_lastuse < old->ac_lastuse)
- old= cache;
- }
- assert(old);
-
- if (!flags)
- return old;
-
- /* Get next permanent entry */
- for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
- {
- if (cache->ac_state == ACS_UNUSED)
- break;
- if (cache->ac_flags & ACF_PERM)
- continue;
- break;
- }
- if (i >= arp_cache_nr/2)
- return NULL; /* Too many entries */
- if (cache != old)
- {
- assert(old > cache);
- *old= *cache;
- old= cache;
- }
-
- if (!(flags & ACF_PUB))
- return old;
-
- /* Get first nonpublished entry */
- for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
- {
- if (cache->ac_state == ACS_UNUSED)
- break;
- if (cache->ac_flags & ACF_PUB)
- continue;
- break;
- }
- if (cache != old)
- {
- assert(old > cache);
- *old= *cache;
- old= cache;
- }
- return old;
-}
-
-void arp_set_ipaddr (eth_port, ipaddr)
-int eth_port;
-ipaddr_t ipaddr;
-{
- arp_port_t *arp_port;
-
- if (eth_port < 0 || eth_port >= eth_conf_nr)
- return;
- arp_port= &arp_port_table[eth_port];
-
- arp_port->ap_ipaddr= ipaddr;
- arp_port->ap_flags |= APF_INADDR_SET;
- arp_port->ap_flags &= ~APF_SUSPEND;
- if (arp_port->ap_state == APS_GETADDR)
- arp_main(arp_port);
-}
-
-int arp_set_cb(eth_port, ip_port, arp_func)
-int eth_port;
-int ip_port;
-arp_func_t arp_func;
-{
- int i;
- arp_port_t *arp_port;
-
- assert(eth_port >= 0);
- if (eth_port >= eth_conf_nr)
- return ENXIO;
-
- arp_port= &arp_port_table[eth_port];
- arp_port->ap_eth_port= eth_port;
- arp_port->ap_ip_port= ip_port;
- arp_port->ap_state= APS_INITIAL;
- arp_port->ap_flags= APF_EMPTY;
- arp_port->ap_arp_func= arp_func;
- arp_port->ap_sendpkt= NULL;
- arp_port->ap_sendlist= NULL;
- arp_port->ap_reclist= NULL;
- for (i= 0; i<AP_REQ_NR; i++) {
- arp_port->ap_req[i].ar_entry= -1;
- arp_port->ap_req[i].ar_timer.tim_active= 0;
- }
-
- ev_init(&arp_port->ap_event);
-
- arp_main(arp_port);
-
- return NW_OK;
-}
-
-int arp_ip_eth (eth_port, ipaddr, ethaddr)
-int eth_port;
-ipaddr_t ipaddr;
-ether_addr_t *ethaddr;
-{
- int i, ref;
- arp_port_t *arp_port;
- struct arp_req *reqp;
- arp_cache_t *ce;
- time_t curr_time;
-
- assert(eth_port >= 0 && eth_port < eth_conf_nr);
- arp_port= &arp_port_table[eth_port];
- assert(arp_port->ap_state == APS_ARPMAIN ||
- (printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,
- arp_port->ap_state), 0));
-
- curr_time= get_time();
-
- ce= find_cache_ent (arp_port, ipaddr);
- if (ce && ce->ac_expire < curr_time)
- {
- assert(ce->ac_state != ACS_INCOMPLETE);
-
- /* Check whether there is enough space for an ARP
- * request or not.
- */
- for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)
- {
- if (reqp->ar_entry < 0)
- break;
- }
- if (i < AP_REQ_NR)
- {
- /* Okay, expire this entry. */
- ce->ac_state= ACS_UNUSED;
- ce= NULL;
- }
- else
- {
- /* Continue using this entry for a while */
- printf("arp[%d]: Overloaded! Keeping entry for ",
- arp_port-arp_port_table);
- writeIpAddr(ipaddr);
- printf("\n");
- ce->ac_expire= curr_time+ARP_NOTRCH_EXP_TIME;
- }
- }
- if (ce)
- {
- /* Found an entry. This entry should be valid, unreachable
- * or incomplete.
- */
- ce->ac_lastuse= curr_time;
- if (ce->ac_state == ACS_VALID)
- {
- *ethaddr= ce->ac_ethaddr;
- return NW_OK;
- }
- if (ce->ac_state == ACS_UNREACHABLE)
- return EHOSTUNREACH;
- assert(ce->ac_state == ACS_INCOMPLETE);
-
- return NW_SUSPEND;
- }
-
- /* Find an empty slot for an ARP request */
- for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)
- {
- if (reqp->ar_entry < 0)
- break;
- }
- if (i >= AP_REQ_NR)
- {
- /* We should be able to report that this ARP request
- * cannot be accepted. At the moment we just return SUSPEND.
- */
- return NW_SUSPEND;
- }
- ref= (eth_port*AP_REQ_NR + i);
-
- ce= alloc_cache_ent(ACF_EMPTY);
- ce->ac_flags= 0;
- ce->ac_state= ACS_INCOMPLETE;
- ce->ac_ipaddr= ipaddr;
- ce->ac_port= arp_port;
- ce->ac_expire= curr_time+ARP_EXP_TIME;
- ce->ac_lastuse= curr_time;
-
- reqp->ar_entry= ce-arp_cache;
- reqp->ar_req_count= -1;
-
- /* Send the first packet by expiring the timer */
- clck_timer(&reqp->ar_timer, 1, arp_timeout, ref);
-
- return NW_SUSPEND;
-}
-
-int arp_ioctl (eth_port, fd, req, get_userdata, put_userdata)
-int eth_port;
-int fd;
-ioreq_t req;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-{
- arp_port_t *arp_port;
- arp_cache_t *ce, *cache;
- acc_t *data;
- nwio_arp_t *arp_iop;
- int entno, result, ac_flags;
- u32_t flags;
- ipaddr_t ipaddr;
- time_t curr_time;
-
- assert(eth_port >= 0 && eth_port < eth_conf_nr);
- arp_port= &arp_port_table[eth_port];
- assert(arp_port->ap_state == APS_ARPMAIN ||
- (printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,
- arp_port->ap_state), 0));
-
- switch(req)
- {
- case NWIOARPGIP:
- data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
- if (data == NULL)
- return EFAULT;
- data= bf_packIffLess(data, sizeof(*arp_iop));
- arp_iop= (nwio_arp_t *)ptr2acc_data(data);
- ipaddr= arp_iop->nwa_ipaddr;
- ce= NULL; /* lint */
- for (entno= 0; entno < arp_cache_nr; entno++)
- {
- ce= &arp_cache[entno];
- if (ce->ac_state == ACS_UNUSED ||
- ce->ac_port != arp_port)
- {
- continue;
- }
- if (ce->ac_ipaddr == ipaddr)
- break;
- }
- if (entno == arp_cache_nr)
- {
- /* Also report the address of this interface */
- if (ipaddr != arp_port->ap_ipaddr)
- {
- bf_afree(data);
- return ENOENT;
- }
- arp_iop->nwa_entno= arp_cache_nr;
- arp_iop->nwa_ipaddr= ipaddr;
- arp_iop->nwa_ethaddr= arp_port->ap_ethaddr;
- arp_iop->nwa_flags= NWAF_PERM | NWAF_PUB;
- }
- else
- {
- arp_iop->nwa_entno= entno+1;
- arp_iop->nwa_ipaddr= ce->ac_ipaddr;
- arp_iop->nwa_ethaddr= ce->ac_ethaddr;
- arp_iop->nwa_flags= 0;
- if (ce->ac_state == ACS_INCOMPLETE)
- arp_iop->nwa_flags |= NWAF_INCOMPLETE;
- if (ce->ac_state == ACS_UNREACHABLE)
- arp_iop->nwa_flags |= NWAF_DEAD;
- if (ce->ac_flags & ACF_PERM)
- arp_iop->nwa_flags |= NWAF_PERM;
- if (ce->ac_flags & ACF_PUB)
- arp_iop->nwa_flags |= NWAF_PUB;
- }
-
- result= (*put_userdata)(fd, 0, data, TRUE);
- return result;
-
- case NWIOARPGNEXT:
- data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
- if (data == NULL)
- return EFAULT;
- data= bf_packIffLess(data, sizeof(*arp_iop));
- arp_iop= (nwio_arp_t *)ptr2acc_data(data);
- entno= arp_iop->nwa_entno;
- if (entno < 0)
- entno= 0;
- ce= NULL; /* lint */
- for (; entno < arp_cache_nr; entno++)
- {
- ce= &arp_cache[entno];
- if (ce->ac_state == ACS_UNUSED ||
- ce->ac_port != arp_port)
- {
- continue;
- }
- break;
- }
- if (entno == arp_cache_nr)
- {
- bf_afree(data);
- return ENOENT;
- }
- arp_iop->nwa_entno= entno+1;
- arp_iop->nwa_ipaddr= ce->ac_ipaddr;
- arp_iop->nwa_ethaddr= ce->ac_ethaddr;
- arp_iop->nwa_flags= 0;
- if (ce->ac_state == ACS_INCOMPLETE)
- arp_iop->nwa_flags |= NWAF_INCOMPLETE;
- if (ce->ac_state == ACS_UNREACHABLE)
- arp_iop->nwa_flags |= NWAF_DEAD;
- if (ce->ac_flags & ACF_PERM)
- arp_iop->nwa_flags |= NWAF_PERM;
- if (ce->ac_flags & ACF_PUB)
- arp_iop->nwa_flags |= NWAF_PUB;
-
- result= (*put_userdata)(fd, 0, data, TRUE);
- return result;
-
- case NWIOARPSIP:
- data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
- if (data == NULL)
- return EFAULT;
- data= bf_packIffLess(data, sizeof(*arp_iop));
- arp_iop= (nwio_arp_t *)ptr2acc_data(data);
- ipaddr= arp_iop->nwa_ipaddr;
- if (find_cache_ent(arp_port, ipaddr))
- {
- bf_afree(data);
- return EEXIST;
- }
-
- flags= arp_iop->nwa_flags;
- ac_flags= ACF_EMPTY;
- if (flags & NWAF_PERM)
- ac_flags |= ACF_PERM;
- if (flags & NWAF_PUB)
- ac_flags |= ACF_PUB|ACF_PERM;
-
- /* Allocate a cache entry */
- ce= alloc_cache_ent(ac_flags);
- if (ce == NULL)
- {
- bf_afree(data);
- return ENOMEM;
- }
-
- ce->ac_flags= ac_flags;
- ce->ac_state= ACS_VALID;
- ce->ac_ethaddr= arp_iop->nwa_ethaddr;
- ce->ac_ipaddr= arp_iop->nwa_ipaddr;
- ce->ac_port= arp_port;
-
- curr_time= get_time();
- ce->ac_expire= curr_time+ARP_EXP_TIME;
- ce->ac_lastuse= curr_time;
-
- bf_afree(data);
- return 0;
-
- case NWIOARPDIP:
- data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
- if (data == NULL)
- return EFAULT;
- data= bf_packIffLess(data, sizeof(*arp_iop));
- arp_iop= (nwio_arp_t *)ptr2acc_data(data);
- ipaddr= arp_iop->nwa_ipaddr;
- bf_afree(data); data= NULL;
- ce= find_cache_ent(arp_port, ipaddr);
- if (!ce)
- return ENOENT;
- if (ce->ac_state == ACS_INCOMPLETE)
- return EINVAL;
-
- ac_flags= ce->ac_flags;
- if (ac_flags & ACF_PUB)
- {
- /* Make sure entry is at the end of published
- * entries.
- */
- for (entno= 0, cache= arp_cache;
- entno<arp_cache_nr; entno++, cache++)
- {
- if (cache->ac_state == ACS_UNUSED)
- break;
- if (cache->ac_flags & ACF_PUB)
- continue;
- break;
- }
- assert(cache > arp_cache);
- cache--;
- if (cache != ce)
- {
- assert(cache > ce);
- *ce= *cache;
- ce= cache;
- }
- }
- if (ac_flags & ACF_PERM)
- {
- /* Make sure entry is at the end of permanent
- * entries.
- */
- for (entno= 0, cache= arp_cache;
- entno<arp_cache_nr; entno++, cache++)
- {
- if (cache->ac_state == ACS_UNUSED)
- break;
- if (cache->ac_flags & ACF_PERM)
- continue;
- break;
- }
- assert(cache > arp_cache);
- cache--;
- if (cache != ce)
- {
- assert(cache > ce);
- *ce= *cache;
- ce= cache;
- }
- }
-
- /* Clear entry */
- ce->ac_state= ACS_UNUSED;
-
- return 0;
-
- default:
- ip_panic(("arp_ioctl: unknown request 0x%lx",
- (unsigned long)req));
- }
- return 0;
-}
-
-static void arp_timeout (ref, timer)
-int ref;
-minix_timer_t *timer;
-{
- int i, port, reqind, acind;
- arp_port_t *arp_port;
- arp_cache_t *ce;
- struct arp_req *reqp;
- time_t curr_time;
- acc_t *data;
- arp46_t *arp;
- u16_t *p;
-
- port= ref / AP_REQ_NR;
- reqind= ref % AP_REQ_NR;
-
- assert(port >= 0 && port <eth_conf_nr);
- arp_port= &arp_port_table[port];
-
- reqp= &arp_port->ap_req[reqind];
- assert (timer == &reqp->ar_timer);
-
- acind= reqp->ar_entry;
-
- assert(acind >= 0 && acind < arp_cache_nr);
- ce= &arp_cache[acind];
-
- assert(ce->ac_port == arp_port);
- assert(ce->ac_state == ACS_INCOMPLETE);
-
- if (++reqp->ar_req_count >= MAX_ARP_RETRIES)
- {
- curr_time= get_time();
- ce->ac_state= ACS_UNREACHABLE;
- ce->ac_expire= curr_time+ ARP_NOTRCH_EXP_TIME;
- ce->ac_lastuse= curr_time;
-
- clck_untimer(&reqp->ar_timer);
- reqp->ar_entry= -1;
- client_reply(arp_port, ce->ac_ipaddr, NULL);
- return;
- }
-
- data= bf_memreq(sizeof(arp46_t));
- arp= (arp46_t *)ptr2acc_data(data);
-
- /* Clear padding */
- assert(sizeof(arp->a46_data.a46_dummy) % sizeof(*p) == 0);
- for (i= 0, p= (u16_t *)arp->a46_data.a46_dummy;
- i < sizeof(arp->a46_data.a46_dummy)/sizeof(*p);
- i++, p++)
- {
- *p= 0xdead;
- }
-
- arp->a46_dstaddr.ea_addr[0]= 0xff;
- arp->a46_dstaddr.ea_addr[1]= 0xff;
- arp->a46_dstaddr.ea_addr[2]= 0xff;
- arp->a46_dstaddr.ea_addr[3]= 0xff;
- arp->a46_dstaddr.ea_addr[4]= 0xff;
- arp->a46_dstaddr.ea_addr[5]= 0xff;
- arp->a46_hdr= HTONS(ARP_ETHERNET);
- arp->a46_pro= HTONS(ETH_IP_PROTO);
- arp->a46_hln= 6;
- arp->a46_pln= 4;
- arp->a46_op= HTONS(ARP_REQUEST);
- arp->a46_sha= arp_port->ap_ethaddr;
- memcpy (arp->a46_spa, &arp_port->ap_ipaddr, sizeof(ipaddr_t));
- memset(&arp->a46_tha, '\0', sizeof(ether_addr_t));
- memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));
-
- assert(data->acc_linkC == 1);
- data->acc_ext_link= arp_port->ap_sendlist;
- arp_port->ap_sendlist= data; data= NULL;
-
- if (!(arp_port->ap_flags & APF_ARP_WR_IP))
- setup_write(arp_port);
-
- clck_timer(&reqp->ar_timer, get_time() + ARP_TIMEOUT,
- arp_timeout, ref);
-}
-
-static void arp_buffree(priority)
-int priority;
-{
- int i;
- acc_t *pack, *next_pack;
- arp_port_t *arp_port;
-
- for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
- {
- if (priority == ARP_PRI_REC)
- {
- next_pack= arp_port->ap_reclist;
- while(next_pack && next_pack->acc_ext_link)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- if (next_pack)
- {
- if (ev_in_queue(&arp_port->ap_event))
- {
- DBLOCK(1, printf(
- "not freeing ap_reclist, ap_event enqueued\n"));
- }
- else
- {
- bf_afree(next_pack);
- next_pack= NULL;
- }
- }
- arp_port->ap_reclist= next_pack;
- }
- if (priority == ARP_PRI_SEND)
- {
- next_pack= arp_port->ap_sendlist;
- while(next_pack && next_pack->acc_ext_link)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- if (next_pack)
- {
- if (ev_in_queue(&arp_port->ap_event))
- {
- DBLOCK(1, printf(
- "not freeing ap_sendlist, ap_event enqueued\n"));
- }
- else
- {
- bf_afree(next_pack);
- next_pack= NULL;
- }
- }
- arp_port->ap_sendlist= next_pack;
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void arp_bufcheck()
-{
- int i;
- arp_port_t *arp_port;
- acc_t *pack;
-
- for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
- {
- for (pack= arp_port->ap_reclist; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- for (pack= arp_port->ap_sendlist; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
-}
-#endif /* BUF_CONSISTENCY_CHECK */
-
-/*
- * $PchId: arp.c,v 1.22 2005/06/28 14:15:06 philip Exp $
- */
+++ /dev/null
-/*
-arp.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef ARP_H
-#define ARP_H
-
-#define ARP_ETHERNET 1
-
-#define ARP_REQUEST 1
-#define ARP_REPLY 2
-
-/* Prototypes */
-typedef void (*arp_func_t) ARGS(( int fd, ipaddr_t ipaddr,
- ether_addr_t *ethaddr ));
-
-void arp_prep ARGS(( void ));
-void arp_init ARGS(( void ));
-void arp_set_ipaddr ARGS(( int eth_port, ipaddr_t ipaddr ));
-int arp_set_cb ARGS(( int eth_port, int ip_port, arp_func_t arp_func ));
-int arp_ip_eth ARGS(( int eth_port, ipaddr_t ipaddr, ether_addr_t *ethaddr ));
-
-int arp_ioctl ARGS(( int eth_port, int fd, ioreq_t req,
- get_userdata_t get_userdata, put_userdata_t put_userdata ));
-
-#endif /* ARP_H */
-
-/*
- * $PchId: arp.h,v 1.7 2001/04/19 18:58:17 philip Exp $
- */
+++ /dev/null
-
-#include <assert.h>
-
-/*
-assert.h
-
-Copyright 1995 Philip Homburg
-*/
-#ifndef INET_ASSERT_H
-#define INET_ASSERT_H
-
-#if !NDEBUG
-
-void bad_assertion(char *file, int line, char *what) _NORETURN;
-void bad_compare(char *file, int line, int lhs, char *what, int rhs) _NORETURN;
-
-#define compare(a,t,b) assert((a) t (b))
-
-#else /* NDEBUG */
-
-#define compare(a,t,b) 0
-
-#endif /* NDEBUG */
-
-#endif /* INET_ASSERT_H */
-
-
-/*
- * $PchId: assert.h,v 1.8 2002/03/18 21:50:32 philip Exp $
- */
+++ /dev/null
-/*
-buf.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef BUF_H
-#define BUF_H
-
-/* Note: BUF_S should be defined in const.h */
-
-#define MAX_BUFREQ_PRI 10
-
-#define ARP_PRI_REC 3
-#define ARP_PRI_SEND 3
-
-#define ETH_PRI_PORTBUFS 3
-#define ETH_PRI_FDBUFS_EXTRA 5
-#define ETH_PRI_FDBUFS 6
-
-#define IP_PRI_PORTBUFS 3
-#define IP_PRI_ASSBUFS 4
-#define IP_PRI_FDBUFS_EXTRA 5
-#define IP_PRI_FDBUFS 6
-
-#define ICMP_PRI_QUEUE 1
-
-#define TCP_PRI_FRAG2SEND 4
-#define TCP_PRI_CONN_EXTRA 5
-#define TCP_PRI_CONNwoUSER 7
-#define TCP_PRI_CONN_INUSE 9
-
-#define UDP_PRI_FDBUFS_EXTRA 5
-#define UDP_PRI_FDBUFS 6
-
-#define PSIP_PRI_EXP_PROMISC 2
-
-struct acc;
-typedef void (*buffree_t) ARGS(( struct acc *acc ));
-typedef void (*bf_freereq_t) ARGS(( int priority ));
-
-#ifdef BUF_CONSISTENCY_CHECK
-typedef void (*bf_checkreq_t) ARGS(( void ));
-#endif
-
-typedef struct buf
-{
- int buf_linkC;
- buffree_t buf_free;
- size_t buf_size;
- char *buf_data_p;
-
-#ifdef BUF_TRACK_ALLOC_FREE
- char *buf_alloc_file;
- int buf_alloc_line;
- char *buf_free_file;
- int buf_free_line;
-#endif
-#ifdef BUF_CONSISTENCY_CHECK
- unsigned buf_generation;
- int buf_check_linkC;
-#endif
-} buf_t;
-
-typedef struct acc
-{
- int acc_linkC;
- int acc_offset, acc_length;
- buf_t *acc_buffer;
- struct acc *acc_next, *acc_ext_link;
-
-#ifdef BUF_TRACK_ALLOC_FREE
- char *acc_alloc_file;
- int acc_alloc_line;
- char *acc_free_file;
- int acc_free_line;
-#endif
-#ifdef BUF_CONSISTENCY_CHECK
- unsigned acc_generation;
- int acc_check_linkC;
-#endif
-} acc_t;
-
-extern acc_t *bf_temporary_acc;
-extern acc_t *bf_linkcheck_acc;
-
-/* For debugging... */
-
-#ifdef BUF_TRACK_ALLOC_FREE
-
-#ifndef BUF_IMPLEMENTATION
-
-#define bf_memreq(a) _bf_memreq(this_file, __LINE__, a)
-#define bf_cut(a,b,c) _bf_cut(this_file, __LINE__, a, b, c)
-#define bf_delhead(a,b) _bf_delhead(this_file, __LINE__, a, b)
-#define bf_packIffLess(a,b) _bf_packIffLess(this_file, __LINE__, \
- a, b)
-#define bf_afree(a) _bf_afree(this_file, __LINE__, a)
-#define bf_pack(a) _bf_pack(this_file, __LINE__, a)
-#define bf_append(a,b) _bf_append(this_file, __LINE__, a, b)
-#define bf_dupacc(a) _bf_dupacc(this_file, __LINE__, a)
-#if 0
-#define bf_mark_1acc(a) _bf_mark_1acc(this_file, __LINE__, a)
-#define bf_mark_acc(a) _bf_mark_acc(this_file, __LINE__, a)
-#endif
-#define bf_align(a,s,al) _bf_align(this_file, __LINE__, a, s, al)
-
-#else /* BUF_IMPLEMENTATION */
-
-#define bf_afree(a) _bf_afree(clnt_file, clnt_line, a)
-#define bf_pack(a) _bf_pack(clnt_file, clnt_line, a)
-#define bf_memreq(a) _bf_memreq(clnt_file, clnt_line, a)
-#define bf_dupacc(a) _bf_dupacc(clnt_file, clnt_line, a)
-#define bf_cut(a,b,c) _bf_cut(clnt_file, clnt_line, a, b, c)
-#define bf_delhead(a,b) _bf_delhead(clnt_file, clnt_line, a, b)
-#define bf_align(a,s,al) _bf_align(clnt_file, clnt_line, a, s, al)
-
-#endif /* !BUF_IMPLEMENTATION */
-
-#else
-
-#define bf_mark_1acc(acc) ((void)0)
-#define bf_mark_acc(acc) ((void)0)
-
-#endif /* BUF_TRACK_ALLOC_FREE */
-
-/* Prototypes */
-
-void bf_init ARGS(( void ));
-#ifndef BUF_CONSISTENCY_CHECK
-void bf_logon ARGS(( bf_freereq_t func ));
-#else
-void bf_logon ARGS(( bf_freereq_t func, bf_checkreq_t checkfunc ));
-#endif
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_memreq ARGS(( size_t size));
-#else
-acc_t *_bf_memreq ARGS(( char *clnt_file, int clnt_line,
- size_t size));
-#endif
-/* the result is an acc with linkC == 1 */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_dupacc ARGS(( acc_t *acc ));
-#else
-acc_t *_bf_dupacc ARGS(( char *clnt_file, int clnt_line,
- acc_t *acc ));
-#endif
-/* the result is an acc with linkC == 1 identical to the given one */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-void bf_afree ARGS(( acc_t *acc));
-#else
-void _bf_afree ARGS(( char *clnt_file, int clnt_line,
- acc_t *acc));
-#endif
-/* this reduces the linkC off the given acc with one */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_pack ARGS(( acc_t *pack));
-#else
-acc_t *_bf_pack ARGS(( char *clnt_file, int clnt_line,
- acc_t *pack));
-#endif
-/* this gives a packed copy of the given acc, the linkC of the given acc is
- reduced by one, the linkC of the result == 1 */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_packIffLess ARGS(( acc_t *pack, int min_len ));
-#else
-acc_t *_bf_packIffLess ARGS(( char *clnt_file, int clnt_line,
- acc_t *pack, int min_len ));
-#endif
-/* this performs a bf_pack iff pack->acc_length<min_len */
-
-size_t bf_bufsize ARGS(( acc_t *pack));
-/* this gives the length of the buffer specified by the given acc. The linkC
- of the given acc remains the same */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_cut ARGS(( acc_t *data, unsigned offset, unsigned length ));
-#else
-acc_t *_bf_cut ARGS(( char *clnt_file, int clnt_line,
- acc_t *data, unsigned offset, unsigned length ));
-#endif
-/* the result is a cut of the buffer from offset with length length.
- The linkC of the result == 1, the linkC of the given acc remains the
- same. */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_delhead ARGS(( acc_t *data, unsigned offset ));
-#else
-acc_t *_bf_delhead ARGS(( char *clnt_file, int clnt_line,
- acc_t *data, unsigned offset ));
-#endif
-/* the result is a cut of the buffer from offset until the end.
- The linkC of the result == 1, the linkC of the given acc is
- decremented. */
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_append ARGS(( acc_t *data_first, acc_t *data_second ));
-#else
-acc_t *_bf_append ARGS(( char *clnt_file, int clnt_line,
- acc_t *data_first, acc_t *data_second ));
-#endif
-/* data_second is appended after data_first, a link is returned to the
- result and the linkCs of data_first and data_second are reduced.
- further more, if the contents of the last part of data_first and
- the first part of data_second fit in a buffer, both parts are
- copied into a (possibly fresh) buffer
-*/
-
-#ifndef BUF_TRACK_ALLOC_FREE
-acc_t *bf_align ARGS(( acc_t *acc, size_t size, size_t alignment ));
-#else
-acc_t *_bf_align ARGS(( char *clnt_file, int clnt_line,
- acc_t *acc, size_t size, size_t alignment ));
-#endif
-/* size bytes of acc (or all bytes of acc if the size buffer is smaller
- than size) are aligned on an address that is multiple of alignment.
- Size must be less than or equal to BUF_S.
-*/
-
-int bf_linkcheck ARGS(( acc_t *acc ));
-/* check if all link count are positive, and offsets and sizes are within
- * the underlying buffer.
- */
-
-#define ptr2acc_data(/* acc_t * */ a) (&((acc_t *)(a))->acc_buffer-> \
- buf_data_p[((acc_t *)(a))->acc_offset])
-
-#define bf_chkbuf(buf) ((buf)? (compare((buf)->acc_linkC,>,0), \
- compare((buf)->acc_buffer, !=, 0), \
- compare((buf)->acc_buffer->buf_linkC,>,0)) : (void)0)
-
-#ifdef BUF_CONSISTENCY_CHECK
-int bf_consistency_check ARGS(( void ));
-void bf_check_acc ARGS(( acc_t *acc ));
-void _bf_mark_1acc ARGS(( char *clnt_file, int clnt_line, acc_t *acc ));
-void _bf_mark_acc ARGS(( char *clnt_file, int clnt_line, acc_t *acc ));
-#endif
-
-#endif /* BUF_H */
-
-/*
- * $PchId: buf.h,v 1.13 2003/09/10 08:52:09 philip Exp $
- */
+++ /dev/null
-/*
-clock.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef CLOCK_H
-#define CLOCK_H
-
-struct minix_timer;
-
-typedef void (*timer_func_t) ARGS(( int fd, struct minix_timer *timer ));
-
-typedef struct minix_timer
-{
- struct minix_timer *tim_next;
- timer_func_t tim_func;
- int tim_ref;
- time_t tim_time;
- int tim_active;
-} minix_timer_t;
-
-extern int clck_call_expire; /* Call clck_expire_timer from the mainloop */
-
-void clck_init ARGS(( void ));
-void set_time ARGS(( clock_t time ));
-time_t get_time ARGS(( void ));
-void reset_time ARGS(( void ));
-/* set a timer to go off at the time specified by timeout */
-void clck_timer ARGS(( minix_timer_t *timer, time_t timeout, timer_func_t func,
- int fd ));
-void clck_untimer ARGS(( minix_timer_t *timer ));
-void clck_expire_timers ARGS(( void ));
-
-#endif /* CLOCK_H */
-
-/*
- * $PchId: clock.h,v 1.5 1995/11/21 06:45:27 philip Exp $
- */
+++ /dev/null
-/*
-eth.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "osdep_eth.h"
-#include "type.h"
-
-#include "assert.h"
-#include "buf.h"
-#include "eth.h"
-#include "eth_int.h"
-#include "sr.h"
-
-THIS_FILE
-
-#define ETH_FD_NR (4*IP_PORT_MAX)
-#define EXPIRE_TIME 60*HZ /* seconds */
-
-typedef struct eth_fd
-{
- int ef_flags;
- nwio_ethopt_t ef_ethopt;
- eth_port_t *ef_port;
- struct eth_fd *ef_type_next;
- struct eth_fd *ef_send_next;
- int ef_srfd;
- acc_t *ef_rdbuf_head;
- acc_t *ef_rdbuf_tail;
- get_userdata_t ef_get_userdata;
- put_userdata_t ef_put_userdata;
- put_pkt_t ef_put_pkt;
- select_res_t ef_select_res;
- time_t ef_exp_time;
- size_t ef_write_count;
- ioreq_t ef_ioctl_req;
-} eth_fd_t;
-
-#define EFF_FLAGS 0xf
-# define EFF_EMPTY 0x0
-# define EFF_INUSE 0x1
-# define EFF_BUSY 0xE
-# define EFF_READ_IP 0x2
-# define EFF_WRITE_IP 0x4
-# define EFF_IOCTL_IP 0x8
-# define EFF_OPTSET 0x10
-# define EFF_SEL_READ 0x20
-
-/* Note that the vh_type field is normally considered part of the ethernet
- * header.
- */
-typedef struct
-{
- u16_t vh_type;
- u16_t vh_vlan;
-} vlan_hdr_t;
-
-static int eth_checkopt ARGS(( eth_fd_t *eth_fd ));
-static void hash_fd ARGS(( eth_fd_t *eth_fd ));
-static void unhash_fd ARGS(( eth_fd_t *eth_fd ));
-static void eth_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void eth_bufcheck ARGS(( void ));
-#endif
-static int eth_sel_read ARGS(( eth_fd_t * ));
-static void packet2user ARGS(( eth_fd_t *fd, acc_t *pack, time_t exp_time ));
-static void reply_thr_get ARGS(( eth_fd_t *eth_fd,
- size_t result, int for_ioctl ));
-static void reply_thr_put ARGS(( eth_fd_t *eth_fd,
- size_t result, int for_ioctl ));
-static void do_rec_conf ARGS(( eth_port_t *eth_port ));
-static u32_t compute_rec_conf ARGS(( eth_port_t *eth_port ));
-static acc_t *insert_vlan_hdr ARGS(( eth_port_t *eth_port, acc_t *pack ));
-
-eth_port_t *eth_port_table;
-int no_ethWritePort= 0;
-
-static eth_fd_t eth_fd_table[ETH_FD_NR];
-static ether_addr_t broadcast= { { 255, 255, 255, 255, 255, 255 } };
-
-void eth_prep()
-{
- eth_port_table= alloc(eth_conf_nr * sizeof(eth_port_table[0]));
-}
-
-void eth_init()
-{
- int i, j;
-
- assert (BUF_S >= sizeof(nwio_ethopt_t));
- assert (BUF_S >= ETH_HDR_SIZE); /* these are in fact static assertions,
- thus a good compiler doesn't
- generate any code for this */
-
-
- for (i=0; i<ETH_FD_NR; i++)
- eth_fd_table[i].ef_flags= EFF_EMPTY;
- for (i=0; i<eth_conf_nr; i++)
- {
- eth_port_table[i].etp_flags= EPF_EMPTY;
- eth_port_table[i].etp_getstat= NULL;
- eth_port_table[i].etp_sendq_head= NULL;
- eth_port_table[i].etp_sendq_tail= NULL;
- eth_port_table[i].etp_type_any= NULL;
- ev_init(ð_port_table[i].etp_sendev);
- for (j= 0; j<ETH_TYPE_HASH_NR; j++)
- eth_port_table[i].etp_type[j]= NULL;
- for (j= 0; j<ETH_VLAN_HASH_NR; j++)
- eth_port_table[i].etp_vlan_tab[j]= NULL;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(eth_buffree);
-#else
- bf_logon(eth_buffree, eth_bufcheck);
-#endif
-
- osdep_eth_init();
-}
-
-int eth_open(port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port, srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- int i;
- eth_port_t *eth_port;
- eth_fd_t *eth_fd;
-
- DBLOCK(0x20, printf("eth_open (%d, %d, %lx, %lx)\n", port, srfd,
- (unsigned long)get_userdata, (unsigned long)put_userdata));
- eth_port= ð_port_table[port];
- if (!(eth_port->etp_flags & EPF_ENABLED))
- return EGENERIC;
-
- for (i=0; i<ETH_FD_NR && (eth_fd_table[i].ef_flags & EFF_INUSE);
- i++);
-
- if (i>=ETH_FD_NR)
- {
- DBLOCK(1, printf("out of fds\n"));
- return EAGAIN;
- }
-
- eth_fd= ð_fd_table[i];
-
- eth_fd->ef_flags= EFF_INUSE;
- eth_fd->ef_ethopt.nweo_flags=NWEO_DEFAULT;
- eth_fd->ef_port= eth_port;
- eth_fd->ef_srfd= srfd;
- assert(eth_fd->ef_rdbuf_head == NULL);
- eth_fd->ef_get_userdata= get_userdata;
- eth_fd->ef_put_userdata= put_userdata;
- eth_fd->ef_put_pkt= put_pkt;
- eth_fd->ef_select_res= select_res;
-
- return i;
-}
-
-int eth_ioctl(fd, req)
-int fd;
-ioreq_t req;
-{
- acc_t *data;
- eth_fd_t *eth_fd;
- eth_port_t *eth_port;
-
- DBLOCK(0x20, printf("eth_ioctl (%d, 0x%lx)\n", fd, (unsigned long)req));
- eth_fd= ð_fd_table[fd];
- eth_port= eth_fd->ef_port;
-
- assert (eth_fd->ef_flags & EFF_INUSE);
-
- switch (req)
- {
- case NWIOSETHOPT:
- {
- nwio_ethopt_t *ethopt;
- nwio_ethopt_t oldopt, newopt;
- int result;
- u32_t new_en_flags, new_di_flags,
- old_en_flags, old_di_flags;
-
- data= (*eth_fd->ef_get_userdata)(eth_fd->
- ef_srfd, 0, sizeof(nwio_ethopt_t), TRUE);
-
- ethopt= (nwio_ethopt_t *)ptr2acc_data(data);
- oldopt= eth_fd->ef_ethopt;
- newopt= *ethopt;
-
- old_en_flags= oldopt.nweo_flags & 0xffff;
- old_di_flags= (oldopt.nweo_flags >> 16) & 0xffff;
- new_en_flags= newopt.nweo_flags & 0xffff;
- new_di_flags= (newopt.nweo_flags >> 16) & 0xffff;
- if (new_en_flags & new_di_flags)
- {
- bf_afree(data);
- reply_thr_get (eth_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- /* NWEO_ACC_MASK */
- if (new_di_flags & NWEO_ACC_MASK)
- {
- bf_afree(data);
- reply_thr_get (eth_fd, EBADMODE, TRUE);
- return NW_OK;
- }
- /* you can't disable access modes */
-
- if (!(new_en_flags & NWEO_ACC_MASK))
- new_en_flags |= (old_en_flags & NWEO_ACC_MASK);
-
-
- /* NWEO_LOC_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_LOC_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_LOC_MASK);
- new_di_flags |= (old_di_flags & NWEO_LOC_MASK);
- }
-
- /* NWEO_BROAD_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_BROAD_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_BROAD_MASK);
- new_di_flags |= (old_di_flags & NWEO_BROAD_MASK);
- }
-
- /* NWEO_MULTI_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_MULTI_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_MULTI_MASK);
- new_di_flags |= (old_di_flags & NWEO_MULTI_MASK);
- newopt.nweo_multi= oldopt.nweo_multi;
- }
-
- /* NWEO_PROMISC_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_PROMISC_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_PROMISC_MASK);
- new_di_flags |= (old_di_flags & NWEO_PROMISC_MASK);
- }
-
- /* NWEO_REM_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_REM_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_REM_MASK);
- new_di_flags |= (old_di_flags & NWEO_REM_MASK);
- newopt.nweo_rem= oldopt.nweo_rem;
- }
-
- /* NWEO_TYPE_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_TYPE_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_TYPE_MASK);
- new_di_flags |= (old_di_flags & NWEO_TYPE_MASK);
- newopt.nweo_type= oldopt.nweo_type;
- }
-
- /* NWEO_RW_MASK */
- if (!((new_en_flags | new_di_flags) & NWEO_RW_MASK))
- {
- new_en_flags |= (old_en_flags & NWEO_RW_MASK);
- new_di_flags |= (old_di_flags & NWEO_RW_MASK);
- }
-
- if (eth_fd->ef_flags & EFF_OPTSET)
- unhash_fd(eth_fd);
-
- newopt.nweo_flags= ((unsigned long)new_di_flags << 16) |
- new_en_flags;
- eth_fd->ef_ethopt= newopt;
-
- result= eth_checkopt(eth_fd);
-
- if (result<0)
- eth_fd->ef_ethopt= oldopt;
- else
- {
- unsigned long opt_flags;
- unsigned changes;
- opt_flags= oldopt.nweo_flags ^
- eth_fd->ef_ethopt.nweo_flags;
- changes= ((opt_flags >> 16) | opt_flags) &
- 0xffff;
- if (changes & (NWEO_BROAD_MASK |
- NWEO_MULTI_MASK | NWEO_PROMISC_MASK))
- {
- do_rec_conf(eth_port);
- }
- }
-
- if (eth_fd->ef_flags & EFF_OPTSET)
- hash_fd(eth_fd);
-
- bf_afree(data);
- reply_thr_get (eth_fd, result, TRUE);
- return NW_OK;
- }
-
- case NWIOGETHOPT:
- {
- nwio_ethopt_t *ethopt;
- acc_t *acc;
- int result;
-
- acc= bf_memreq(sizeof(nwio_ethopt_t));
-
- ethopt= (nwio_ethopt_t *)ptr2acc_data(acc);
-
- *ethopt= eth_fd->ef_ethopt;
-
- result= (*eth_fd->ef_put_userdata)(eth_fd->
- ef_srfd, 0, acc, TRUE);
- if (result >= 0)
- reply_thr_put(eth_fd, NW_OK, TRUE);
- return result;
- }
- case NWIOGETHSTAT:
- {
- nwio_ethstat_t *ethstat;
- acc_t *acc;
- int result;
-
- assert (sizeof(nwio_ethstat_t) <= BUF_S);
-
- eth_port= eth_fd->ef_port;
- if (!(eth_port->etp_flags & EPF_ENABLED))
- {
- reply_thr_put(eth_fd, EGENERIC, TRUE);
- return NW_OK;
- }
-
- if (!(eth_port->etp_flags & EPF_GOT_ADDR))
- {
-#if 0
- printf(
- "eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
-#endif
-
- eth_fd->ef_ioctl_req= req;
- assert(!(eth_fd->ef_flags & EFF_IOCTL_IP));
- eth_fd->ef_flags |= EFF_IOCTL_IP;
- return NW_SUSPEND;
- }
-
- if (eth_port->etp_getstat)
- {
- printf(
- "eth_ioctl: pending eth_get_stat request, suspending caller\n");
- assert(!(eth_fd->ef_flags & EFF_IOCTL_IP));
- eth_fd->ef_flags |= EFF_IOCTL_IP;
- return NW_SUSPEND;
- }
-
- acc= bf_memreq(sizeof(nwio_ethstat_t));
- compare (bf_bufsize(acc), ==, sizeof(*ethstat));
-
- ethstat= (nwio_ethstat_t *)ptr2acc_data(acc);
- ethstat->nwes_addr= eth_port->etp_ethaddr;
-
- if (!eth_port->etp_vlan)
- {
- result= eth_get_stat(eth_port,
- ðstat->nwes_stat);
- if (result == SUSPEND)
- {
-#if 0
- printf(
- "eth_ioctl: eth_get_stat returned SUSPEND\n");
-#endif
- eth_fd->ef_ioctl_req= req;
- assert(!(eth_fd->ef_flags &
- EFF_IOCTL_IP));
- eth_fd->ef_flags |= EFF_IOCTL_IP;
-#if 0
-printf("eth_ioctl: setting etp_getstat in port %d to %p\n",
- eth_port-eth_port_table, acc);
-#endif
- eth_port->etp_getstat= acc;
- acc= NULL;
- return NW_SUSPEND;
- }
- if (result != NW_OK)
- {
- bf_afree(acc);
- reply_thr_put(eth_fd, result, TRUE);
- return NW_OK;
- }
- }
- else
- {
- /* No statistics */
- memset(ðstat->nwes_stat, '\0',
- sizeof(ethstat->nwes_stat));
- }
-
- result= (*eth_fd->ef_put_userdata)(eth_fd->
- ef_srfd, 0, acc, TRUE);
- if (result >= 0)
- reply_thr_put(eth_fd, NW_OK, TRUE);
- return result;
- }
- default:
- break;
- }
- reply_thr_put(eth_fd, ENOTTY, TRUE);
- return NW_OK;
-}
-
-int eth_write(fd, count)
-int fd;
-size_t count;
-{
- eth_fd_t *eth_fd;
- eth_port_t *eth_port, *rep;
- acc_t *user_data;
- int r;
-
- eth_fd= ð_fd_table[fd];
- eth_port= eth_fd->ef_port;
-
- if (!(eth_fd->ef_flags & EFF_OPTSET))
- {
- reply_thr_get (eth_fd, EBADMODE, FALSE);
- return NW_OK;
- }
-
- assert (!(eth_fd->ef_flags & EFF_WRITE_IP));
-
- eth_fd->ef_write_count= count;
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
- count += ETH_HDR_SIZE;
-
- if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
- {
- DBLOCK(1, printf("illegal packetsize (%d)\n",count));
- reply_thr_get (eth_fd, EPACKSIZE, FALSE);
- return NW_OK;
- }
- eth_fd->ef_flags |= EFF_WRITE_IP;
-
- /* Enqueue at the real ethernet port */
- rep= eth_port->etp_vlan_port;
- if (!rep)
- rep= eth_port;
- if (rep->etp_wr_pack)
- {
- eth_fd->ef_send_next= NULL;
- if (rep->etp_sendq_head)
- rep->etp_sendq_tail->ef_send_next= eth_fd;
- else
- rep->etp_sendq_head= eth_fd;
- rep->etp_sendq_tail= eth_fd;
- return NW_SUSPEND;
- }
-
- user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0,
- eth_fd->ef_write_count, FALSE);
- if (!user_data)
- {
- eth_fd->ef_flags &= ~EFF_WRITE_IP;
- reply_thr_get (eth_fd, EFAULT, FALSE);
- return NW_OK;
- }
- r= eth_send(fd, user_data, eth_fd->ef_write_count);
- assert(r == NW_OK);
-
- eth_fd->ef_flags &= ~EFF_WRITE_IP;
- reply_thr_get(eth_fd, eth_fd->ef_write_count, FALSE);
- return NW_OK;
-}
-
-int eth_send(fd, data, data_len)
-int fd;
-acc_t *data;
-size_t data_len;
-{
- eth_fd_t *eth_fd;
- eth_port_t *eth_port, *rep;
- eth_hdr_t *eth_hdr;
- acc_t *eth_pack;
- unsigned long nweo_flags;
- size_t count;
- ev_arg_t ev_arg;
-
- eth_fd= ð_fd_table[fd];
- eth_port= eth_fd->ef_port;
-
- if (!(eth_fd->ef_flags & EFF_OPTSET))
- return EBADMODE;
-
- count= data_len;
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
- count += ETH_HDR_SIZE;
-
- if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
- {
- DBLOCK(1, printf("illegal packetsize (%d)\n",count));
- return EPACKSIZE;
- }
- rep= eth_port->etp_vlan_port;
- if (!rep)
- rep= eth_port;
-
- if (rep->etp_wr_pack)
- return NW_WOULDBLOCK;
-
- nweo_flags= eth_fd->ef_ethopt.nweo_flags;
- if (nweo_flags & NWEO_RWDATONLY)
- {
- eth_pack= bf_memreq(ETH_HDR_SIZE);
- eth_pack->acc_next= data;
- }
- else
- eth_pack= bf_packIffLess(data, ETH_HDR_SIZE);
-
- eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
-
- if (nweo_flags & NWEO_REMSPEC)
- eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem;
-
- if (!(eth_port->etp_flags & EPF_GOT_ADDR))
- {
- /* No device, discard packet */
- bf_afree(eth_pack);
- return NW_OK;
- }
-
- if (!(nweo_flags & NWEO_EN_PROMISC))
- eth_hdr->eh_src= eth_port->etp_ethaddr;
-
- if (nweo_flags & NWEO_TYPESPEC)
- eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;
-
- if (eth_addrcmp(eth_hdr->eh_dst, eth_port->etp_ethaddr) == 0)
- {
- /* Local loopback. */
- eth_port->etp_wr_pack= eth_pack;
- ev_arg.ev_ptr= eth_port;
- ev_enqueue(ð_port->etp_sendev, eth_loop_ev, ev_arg);
- return NW_OK;
- }
-
- if (rep != eth_port)
- {
- eth_pack= insert_vlan_hdr(eth_port, eth_pack);
- if (!eth_pack)
- {
- /* Packet is silently discarded */
- return NW_OK;
- }
- }
-
- eth_write_port(rep, eth_pack);
- return NW_OK;
-}
-
-int eth_read (fd, count)
-int fd;
-size_t count;
-{
- eth_fd_t *eth_fd;
- acc_t *pack;
-
- eth_fd= ð_fd_table[fd];
- if (!(eth_fd->ef_flags & EFF_OPTSET))
- {
- reply_thr_put(eth_fd, EBADMODE, FALSE);
- return NW_OK;
- }
- if (count < ETH_MAX_PACK_SIZE)
- {
- reply_thr_put(eth_fd, EPACKSIZE, FALSE);
- return NW_OK;
- }
-
- assert(!(eth_fd->ef_flags & EFF_READ_IP));
- eth_fd->ef_flags |= EFF_READ_IP;
-
- while (eth_fd->ef_rdbuf_head)
- {
- pack= eth_fd->ef_rdbuf_head;
- eth_fd->ef_rdbuf_head= pack->acc_ext_link;
- if (get_time() <= eth_fd->ef_exp_time)
- {
- packet2user(eth_fd, pack, eth_fd->ef_exp_time);
- if (!(eth_fd->ef_flags & EFF_READ_IP))
- return NW_OK;
- }
- else
- bf_afree(pack);
- }
- return NW_SUSPEND;
-}
-
-int eth_cancel(fd, which_operation)
-int fd;
-int which_operation;
-{
- eth_fd_t *eth_fd, *prev, *loc_fd;
- eth_port_t *eth_port;
-
- DBLOCK(2, printf("eth_cancel (%d)\n", fd));
- eth_fd= ð_fd_table[fd];
-
- switch (which_operation)
- {
- case SR_CANCEL_READ:
- assert (eth_fd->ef_flags & EFF_READ_IP);
- eth_fd->ef_flags &= ~EFF_READ_IP;
- reply_thr_put(eth_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_WRITE:
- assert (eth_fd->ef_flags & EFF_WRITE_IP);
- eth_fd->ef_flags &= ~EFF_WRITE_IP;
-
- /* Remove fd from send queue */
- eth_port= eth_fd->ef_port;
- if (eth_port->etp_vlan_port)
- eth_port= eth_port->etp_vlan_port;
- for (prev= 0, loc_fd= eth_port->etp_sendq_head; loc_fd != NULL;
- prev= loc_fd, loc_fd= loc_fd->ef_send_next)
- {
- if (loc_fd == eth_fd)
- break;
- }
- assert(loc_fd == eth_fd);
- if (prev == NULL)
- eth_port->etp_sendq_head= loc_fd->ef_send_next;
- else
- prev->ef_send_next= loc_fd->ef_send_next;
- if (loc_fd->ef_send_next == NULL)
- eth_port->etp_sendq_tail= prev;
-
- reply_thr_get(eth_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_IOCTL:
- assert (eth_fd->ef_flags & EFF_IOCTL_IP);
- eth_fd->ef_flags &= ~EFF_IOCTL_IP;
- reply_thr_get(eth_fd, EINTR, TRUE);
- break;
- default:
- ip_panic(( "got unknown cancel request" ));
- }
- return NW_OK;
-}
-
-int eth_select(fd, operations)
-int fd;
-unsigned operations;
-{
- unsigned resops;
- eth_fd_t *eth_fd;
-
- eth_fd= ð_fd_table[fd];
- assert (eth_fd->ef_flags & EFF_INUSE);
-
- resops= 0;
-
- if (operations & SR_SELECT_READ)
- {
- if (eth_sel_read(eth_fd))
- resops |= SR_SELECT_READ;
- else if (!(operations & SR_SELECT_POLL))
- eth_fd->ef_flags |= EFF_SEL_READ;
- }
- if (operations & SR_SELECT_WRITE)
- {
- /* Should handle special case when the interface is down */
- resops |= SR_SELECT_WRITE;
- }
- if (operations & SR_SELECT_EXCEPTION)
- {
- /* Nothing */
- }
- return resops;
-}
-
-void eth_close(fd)
-int fd;
-{
- eth_fd_t *eth_fd;
- eth_port_t *eth_port;
- acc_t *pack;
-
- eth_fd= ð_fd_table[fd];
-
- assert ((eth_fd->ef_flags & EFF_INUSE) &&
- !(eth_fd->ef_flags & EFF_BUSY));
-
- if (eth_fd->ef_flags & EFF_OPTSET)
- unhash_fd(eth_fd);
- while (eth_fd->ef_rdbuf_head != NULL)
- {
- pack= eth_fd->ef_rdbuf_head;
- eth_fd->ef_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- eth_fd->ef_flags= EFF_EMPTY;
-
- eth_port= eth_fd->ef_port;
- do_rec_conf(eth_port);
-}
-
-void eth_loop_ev(ev, ev_arg)
-event_t *ev;
-ev_arg_t ev_arg;
-{
- acc_t *pack;
- eth_port_t *eth_port;
-
- eth_port= ev_arg.ev_ptr;
- assert(ev == ð_port->etp_sendev);
-
- pack= eth_port->etp_wr_pack;
-
- assert(!no_ethWritePort);
- no_ethWritePort= 1;
- eth_arrive(eth_port, pack, bf_bufsize(pack));
- assert(no_ethWritePort);
- no_ethWritePort= 0;
-
- eth_port->etp_wr_pack= NULL;
- eth_restart_write(eth_port);
-}
-
-static int eth_checkopt (eth_fd)
-eth_fd_t *eth_fd;
-{
-/* bug: we don't check access modes yet */
-
- unsigned long flags;
- unsigned int en_di_flags;
- acc_t *pack;
-
- flags= eth_fd->ef_ethopt.nweo_flags;
- en_di_flags= (flags >>16) | (flags & 0xffff);
-
- if ((en_di_flags & NWEO_ACC_MASK) &&
- (en_di_flags & NWEO_LOC_MASK) &&
- (en_di_flags & NWEO_BROAD_MASK) &&
- (en_di_flags & NWEO_MULTI_MASK) &&
- (en_di_flags & NWEO_PROMISC_MASK) &&
- (en_di_flags & NWEO_REM_MASK) &&
- (en_di_flags & NWEO_TYPE_MASK) &&
- (en_di_flags & NWEO_RW_MASK))
- {
- eth_fd->ef_flags |= EFF_OPTSET;
- }
- else
- eth_fd->ef_flags &= ~EFF_OPTSET;
-
- while (eth_fd->ef_rdbuf_head != NULL)
- {
- pack= eth_fd->ef_rdbuf_head;
- eth_fd->ef_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
-
- return NW_OK;
-}
-
-static void hash_fd(eth_fd)
-eth_fd_t *eth_fd;
-{
- eth_port_t *eth_port;
- int hash;
-
- eth_port= eth_fd->ef_port;
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
- {
- eth_fd->ef_type_next= eth_port->etp_type_any;
- eth_port->etp_type_any= eth_fd;
- }
- else
- {
- hash= eth_fd->ef_ethopt.nweo_type;
- hash ^= (hash >> 8);
- hash &= (ETH_TYPE_HASH_NR-1);
-
- eth_fd->ef_type_next= eth_port->etp_type[hash];
- eth_port->etp_type[hash]= eth_fd;
- }
-}
-
-static void unhash_fd(eth_fd)
-eth_fd_t *eth_fd;
-{
- eth_port_t *eth_port;
- eth_fd_t *prev, *curr, **eth_fd_p;
- int hash;
-
- eth_port= eth_fd->ef_port;
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
- {
- eth_fd_p= ð_port->etp_type_any;
- }
- else
- {
- hash= eth_fd->ef_ethopt.nweo_type;
- hash ^= (hash >> 8);
- hash &= (ETH_TYPE_HASH_NR-1);
-
- eth_fd_p= ð_port->etp_type[hash];
- }
- for (prev= NULL, curr= *eth_fd_p; curr;
- prev= curr, curr= curr->ef_type_next)
- {
- if (curr == eth_fd)
- break;
- }
- assert(curr);
- if (prev)
- prev->ef_type_next= curr->ef_type_next;
- else
- *eth_fd_p= curr->ef_type_next;
-}
-
-void eth_restart_write(eth_port)
-eth_port_t *eth_port;
-{
- eth_fd_t *eth_fd;
- int r;
-
- assert(eth_port->etp_wr_pack == NULL);
- while (eth_fd= eth_port->etp_sendq_head, eth_fd != NULL)
- {
- if (eth_port->etp_wr_pack)
- return;
- eth_port->etp_sendq_head= eth_fd->ef_send_next;
-
- assert(eth_fd->ef_flags & EFF_WRITE_IP);
- eth_fd->ef_flags &= ~EFF_WRITE_IP;
- r= eth_write(eth_fd-eth_fd_table, eth_fd->ef_write_count);
- assert(r == NW_OK);
- }
-}
-
-void eth_arrive (eth_port, pack, pack_size)
-eth_port_t *eth_port;
-acc_t *pack;
-size_t pack_size;
-{
-
- eth_hdr_t *eth_hdr;
- ether_addr_t *dst_addr;
- int pack_stat;
- ether_type_t type;
- eth_fd_t *eth_fd, *first_fd, *share_fd;
- int hash, i;
- u16_t vlan, temp;
- time_t exp_time;
- acc_t *vlan_pack, *hdr_acc, *tmp_acc;
- eth_port_t *vp;
- vlan_hdr_t vh;
- u32_t *p;
-
- exp_time= get_time() + EXPIRE_TIME;
-
- pack= bf_packIffLess(pack, ETH_HDR_SIZE);
-
- eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);
- dst_addr= ð_hdr->eh_dst;
-
- DIFBLOCK(0x20, dst_addr->ea_addr[0] != 0xFF &&
- (dst_addr->ea_addr[0] & 0x1),
- printf("got multicast packet\n"));
-
- if (dst_addr->ea_addr[0] & 0x1)
- {
- /* multi cast or broadcast */
- if (eth_addrcmp(*dst_addr, broadcast) == 0)
- pack_stat= NWEO_EN_BROAD;
- else
- pack_stat= NWEO_EN_MULTI;
- }
- else
- {
- assert(eth_port->etp_flags & EPF_GOT_ADDR);
- if (eth_addrcmp (*dst_addr, eth_port->etp_ethaddr) == 0)
- pack_stat= NWEO_EN_LOC;
- else
- pack_stat= NWEO_EN_PROMISC;
- }
- type= eth_hdr->eh_proto;
- hash= type;
- hash ^= (hash >> 8);
- hash &= (ETH_TYPE_HASH_NR-1);
-
- if (type == HTONS(ETH_VLAN_PROTO))
- {
- /* VLAN packet. Extract original ethernet packet */
-
- vlan_pack= pack;
- vlan_pack->acc_linkC++;
- hdr_acc= bf_cut(vlan_pack, 0, 2*sizeof(ether_addr_t));
- vlan_pack= bf_delhead(vlan_pack, 2*sizeof(ether_addr_t));
- vlan_pack= bf_packIffLess(vlan_pack, sizeof(vh));
- vh= *(vlan_hdr_t *)ptr2acc_data(vlan_pack);
- vlan_pack= bf_delhead(vlan_pack, sizeof(vh));
- hdr_acc= bf_append(hdr_acc, vlan_pack);
- vlan_pack= hdr_acc; hdr_acc= NULL;
- if (bf_bufsize(vlan_pack) < ETH_MIN_PACK_SIZE)
- {
- tmp_acc= bf_memreq(sizeof(vh));
-
- /* Clear padding */
- assert(sizeof(vh) <= sizeof(*p));
- p= (u32_t *)ptr2acc_data(tmp_acc);
- *p= 0xdeadbeef;
-
- vlan_pack= bf_append(vlan_pack, tmp_acc);
- tmp_acc= NULL;
- }
- vlan= ntohs(vh.vh_vlan);
- if (vlan & ETH_TCI_CFI)
- {
- /* No support for extended address formats */
- bf_afree(vlan_pack); vlan_pack= NULL;
- }
- vlan &= ETH_TCI_VLAN_MASK;
- }
- else
- {
- /* No VLAN processing */
- vlan_pack= NULL;
- vlan= 0; /* lint */
- }
-
- first_fd= NULL;
- for (i= 0; i<2; i++)
- {
- share_fd= NULL;
-
- eth_fd= (i == 0) ? eth_port->etp_type_any :
- eth_port->etp_type[hash];
- for (; eth_fd; eth_fd= eth_fd->ef_type_next)
- {
- if (i && eth_fd->ef_ethopt.nweo_type != type)
- continue;
- if (!(eth_fd->ef_ethopt.nweo_flags & pack_stat))
- continue;
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC &&
- eth_addrcmp(eth_hdr->eh_src,
- eth_fd->ef_ethopt.nweo_rem) != 0)
- {
- continue;
- }
- if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) ==
- NWEO_SHARED)
- {
- if (!share_fd)
- {
- share_fd= eth_fd;
- continue;
- }
- if (!eth_fd->ef_rdbuf_head)
- share_fd= eth_fd;
- continue;
- }
- if (!first_fd)
- {
- first_fd= eth_fd;
- continue;
- }
- pack->acc_linkC++;
- packet2user(eth_fd, pack, exp_time);
- }
- if (share_fd)
- {
- pack->acc_linkC++;
- packet2user(share_fd, pack, exp_time);
- }
- }
- if (first_fd)
- {
- if (first_fd->ef_put_pkt &&
- (first_fd->ef_flags & EFF_READ_IP) &&
- !(first_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY))
- {
- (*first_fd->ef_put_pkt)(first_fd->ef_srfd, pack,
- pack_size);
- }
- else
- packet2user(first_fd, pack, exp_time);
- }
- else
- {
- if (pack_stat == NWEO_EN_LOC)
- {
- DBLOCK(0x01,
- printf("eth_arrive: dropping packet for proto 0x%x\n",
- ntohs(type)));
- }
- else
- {
- DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",
- ntohs(type)));
- }
- bf_afree(pack);
- }
- if (vlan_pack)
- {
- hash= ETH_HASH_VLAN(vlan, temp);
- for (vp= eth_port->etp_vlan_tab[hash]; vp;
- vp= vp->etp_vlan_next)
- {
- if (vp->etp_vlan == vlan)
- break;
- }
- if (vp)
- {
- eth_arrive(vp, vlan_pack, pack_size-sizeof(vh));
- vlan_pack= NULL;
- }
- else
- {
- /* No device for VLAN */
- bf_afree(vlan_pack);
- vlan_pack= NULL;
- }
- }
-}
-
-void eth_reg_vlan(eth_port, vlan_port)
-eth_port_t *eth_port;
-eth_port_t *vlan_port;
-{
- u16_t t, vlan;
- int h;
-
- vlan= vlan_port->etp_vlan;
- h= ETH_HASH_VLAN(vlan, t);
- vlan_port->etp_vlan_next= eth_port->etp_vlan_tab[h];
- eth_port->etp_vlan_tab[h]= vlan_port;
-}
-
-void eth_restart_ioctl(eth_port)
-eth_port_t *eth_port;
-{
- int i, r;
- eth_fd_t *eth_fd;
- acc_t *acc;
-
-#if 0
- printf("in eth_restart_ioctl\n");
-#endif
-
- /* eth_restart_ioctl is called on too occasions: when a device
- * driver registers with inet and when a eth_get_stat call has
- * completed. We assume the second option when etp_getstat is
- * not equal to zero at the start of the call.
- */
- acc= eth_port->etp_getstat;
-
- for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
- {
- if (!(eth_fd->ef_flags & EFF_INUSE))
- continue;
- if (eth_fd->ef_port != eth_port)
- continue;
- if (!(eth_fd->ef_flags & EFF_IOCTL_IP))
- continue;
- if (eth_fd->ef_ioctl_req != NWIOGETHSTAT)
- continue;
-
-#if 0
-printf("eth_restart_ioctl: etp_getstat in port %d is %p\n",
- eth_port-eth_port_table, acc);
-#endif
-
- if (acc != NULL)
- {
-#if 0
- printf("eth_restart_ioctl: completed getstat\n");
-#endif
- acc->acc_linkC++;
- r= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, 0,
- acc, TRUE);
- if (r >= 0)
- reply_thr_put(eth_fd, NW_OK, TRUE);
- eth_fd->ef_flags &= ~EFF_IOCTL_IP;
- continue;
- }
-
- { static int count; if (++count > 5) ip_panic(("too many restarts")); }
-
- eth_fd->ef_flags &= ~EFF_IOCTL_IP;
- eth_ioctl(i, eth_fd->ef_ioctl_req);
- }
-
- if (acc != NULL)
- {
-#if 0
-printf("eth_restart_ioctl: clearing etp_getstat in port %d\n",
- eth_port-eth_port_table);
-#endif
- assert(acc == eth_port->etp_getstat);
-
- bf_afree(acc);
- eth_port->etp_getstat= NULL;
- }
-}
-
-static int eth_sel_read (eth_fd)
-eth_fd_t *eth_fd;
-{
- acc_t *tmp_acc, *next_acc;
-
- if (!(eth_fd->ef_flags & EFF_OPTSET))
- return 1; /* Read will not block */
-
- if (eth_fd->ef_rdbuf_head)
- {
- if (get_time() <= eth_fd->ef_exp_time)
- return 1;
-
- tmp_acc= eth_fd->ef_rdbuf_head;
- while (tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- eth_fd->ef_rdbuf_head= NULL;
- }
- return 0;
-}
-
-static void packet2user (eth_fd, pack, exp_time)
-eth_fd_t *eth_fd;
-acc_t *pack;
-time_t exp_time;
-{
- int result;
- acc_t *tmp_pack;
- size_t size;
-
- assert (eth_fd->ef_flags & EFF_INUSE);
- if (!(eth_fd->ef_flags & EFF_READ_IP))
- {
- if (pack->acc_linkC != 1)
- {
- tmp_pack= bf_dupacc(pack);
- bf_afree(pack);
- pack= tmp_pack;
- tmp_pack= NULL;
- }
- pack->acc_ext_link= NULL;
- if (eth_fd->ef_rdbuf_head == NULL)
- {
- eth_fd->ef_rdbuf_head= pack;
- eth_fd->ef_exp_time= exp_time;
- }
- else
- eth_fd->ef_rdbuf_tail->acc_ext_link= pack;
- eth_fd->ef_rdbuf_tail= pack;
-
- if (eth_fd->ef_flags & EFF_SEL_READ)
- {
- eth_fd->ef_flags &= ~EFF_SEL_READ;
- if (eth_fd->ef_select_res)
- eth_fd->ef_select_res(eth_fd->ef_srfd, SR_SELECT_READ);
- else
- printf("packet2user: no select_res\n");
- }
- return;
- }
-
- if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
- pack= bf_delhead(pack, ETH_HDR_SIZE);
-
- size= bf_bufsize(pack);
-
- if (eth_fd->ef_put_pkt)
- {
- (*eth_fd->ef_put_pkt)(eth_fd->ef_srfd, pack, size);
- return;
- }
-
- eth_fd->ef_flags &= ~EFF_READ_IP;
- result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,
- FALSE);
- if (result >=0)
- reply_thr_put(eth_fd, size, FALSE);
- else
- reply_thr_put(eth_fd, result, FALSE);
-}
-
-static void eth_buffree (priority)
-int priority;
-{
- int i;
- eth_fd_t *eth_fd;
- acc_t *pack;
-
- if (priority == ETH_PRI_FDBUFS_EXTRA)
- {
- for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
- {
- while (eth_fd->ef_rdbuf_head &&
- eth_fd->ef_rdbuf_head->acc_ext_link)
- {
- pack= eth_fd->ef_rdbuf_head;
- eth_fd->ef_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- }
- if (priority == ETH_PRI_FDBUFS)
- {
- for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
- {
- while (eth_fd->ef_rdbuf_head)
- {
- pack= eth_fd->ef_rdbuf_head;
- eth_fd->ef_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void eth_bufcheck()
-{
- int i;
- eth_fd_t *eth_fd;
- acc_t *pack;
-
- for (i= 0; i<eth_conf_nr; i++)
- {
- bf_check_acc(eth_port_table[i].etp_rd_pack);
- bf_check_acc(eth_port_table[i].etp_wr_pack);
- }
- for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
- {
- for (pack= eth_fd->ef_rdbuf_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
-}
-#endif
-
-static void do_rec_conf(eth_port)
-eth_port_t *eth_port;
-{
- int i;
- u32_t flags;
- eth_port_t *vp;
-
- assert(eth_port);
-
- if (eth_port->etp_vlan)
- {
- /* Configure underlying device */
- eth_port= eth_port->etp_vlan_port;
- }
- flags= compute_rec_conf(eth_port);
- for (i= 0; i<ETH_VLAN_HASH_NR; i++)
- {
- for (vp= eth_port->etp_vlan_tab[i]; vp; vp= vp->etp_vlan_next)
- flags |= compute_rec_conf(vp);
- }
- eth_set_rec_conf(eth_port, flags);
-}
-
-static u32_t compute_rec_conf(eth_port)
-eth_port_t *eth_port;
-{
- eth_fd_t *eth_fd;
- u32_t flags;
- int i;
-
- flags= NWEO_NOFLAGS;
- for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
- {
- if ((eth_fd->ef_flags & (EFF_INUSE|EFF_OPTSET)) !=
- (EFF_INUSE|EFF_OPTSET))
- {
- continue;
- }
- if (eth_fd->ef_port != eth_port)
- continue;
- flags |= eth_fd->ef_ethopt.nweo_flags;
- }
- return flags;
-}
-
-static void reply_thr_get (eth_fd, result, for_ioctl)
-eth_fd_t *eth_fd;
-size_t result;
-int for_ioctl;
-{
- acc_t *data;
-
- data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);
- assert (!data);
-}
-
-static void reply_thr_put (eth_fd, result, for_ioctl)
-eth_fd_t *eth_fd;
-size_t result;
-int for_ioctl;
-{
- int error;
-
- error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,
- for_ioctl);
- assert(error == NW_OK);
-}
-
-static acc_t *insert_vlan_hdr(eth_port, pack)
-eth_port_t *eth_port;
-acc_t *pack;
-{
- acc_t *head_acc, *vh_acc;
- u16_t type, vlan;
- vlan_hdr_t *vp;
-
- head_acc= bf_cut(pack, 0, 2*sizeof(ether_addr_t));
- pack= bf_delhead(pack, 2*sizeof(ether_addr_t));
- pack= bf_packIffLess(pack, sizeof(type));
- type= *(u16_t *)ptr2acc_data(pack);
- if (type == HTONS(ETH_VLAN_PROTO))
- {
- /* Packeted is already tagged. Should update vlan number.
- * For now, just discard packet.
- */
- printf("insert_vlan_hdr: discarding vlan packet\n");
- bf_afree(head_acc); head_acc= NULL;
- bf_afree(pack); pack= NULL;
- return NULL;
- }
- vlan= eth_port->etp_vlan; /* priority and CFI are zero */
-
- vh_acc= bf_memreq(sizeof(vlan_hdr_t));
- vp= (vlan_hdr_t *)ptr2acc_data(vh_acc);
- vp->vh_type= HTONS(ETH_VLAN_PROTO);
- vp->vh_vlan= htons(vlan);
-
- head_acc= bf_append(head_acc, vh_acc); vh_acc= NULL;
- head_acc= bf_append(head_acc, pack); pack= NULL;
- pack= head_acc; head_acc= NULL;
- return pack;
-}
-
-/*
- * $PchId: eth.c,v 1.23 2005/06/28 14:15:58 philip Exp $
- */
+++ /dev/null
-/*
-eth.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef ETH_H
-#define ETH_H
-
-#define NWEO_DEFAULT (NWEO_EN_LOC | NWEO_DI_BROAD | NWEO_DI_MULTI | \
- NWEO_DI_PROMISC | NWEO_REMANY | NWEO_RWDATALL)
-
-#define eth_addrcmp(a,b) (memcmp((void *)&a, (void *)&b, \
- sizeof(a)))
-
-/* Forward declatations */
-
-struct acc;
-
-/* prototypes */
-
-void eth_prep ARGS(( void ));
-void eth_init ARGS(( void ));
-int eth_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t sel_res ));
-int eth_ioctl ARGS(( int fd, ioreq_t req));
-int eth_read ARGS(( int port, size_t count ));
-int eth_write ARGS(( int port, size_t count ));
-int eth_cancel ARGS(( int fd, int which_operation ));
-int eth_select ARGS(( int fd, unsigned operations ));
-void eth_close ARGS(( int fd ));
-int eth_send ARGS(( int port, struct acc *data, size_t data_len ));
-
-#endif /* ETH_H */
-
-/*
- * $PchId: eth.h,v 1.8 2005/06/28 14:16:10 philip Exp $
- */
+++ /dev/null
-/*
-eth_int.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef ETH_INT_H
-#define ETH_INT_H
-
-#define ETH_TYPE_HASH_NR 16
-#define ETH_VLAN_HASH_NR 16
-
-/* Assume that the arguments are a local variable */
-#define ETH_HASH_VLAN(v,t) \
- ((t)= (((v) >> 8) ^ (v)), \
- (t)= (((t) >> 4) ^ (t)), \
- (t) & (ETH_VLAN_HASH_NR-1))
-
-typedef struct eth_port
-{
- int etp_flags;
- ether_addr_t etp_ethaddr;
- acc_t *etp_wr_pack, *etp_rd_pack;
- acc_t *etp_getstat;
- struct eth_fd *etp_sendq_head;
- struct eth_fd *etp_sendq_tail;
- struct eth_fd *etp_type_any;
- struct eth_fd *etp_type[ETH_TYPE_HASH_NR];
- event_t etp_sendev;
-
- /* VLAN support */
- u16_t etp_vlan;
- struct eth_port *etp_vlan_port;
- struct eth_port *etp_vlan_tab[ETH_VLAN_HASH_NR];
- struct eth_port *etp_vlan_next;
-
- osdep_eth_port_t etp_osdep;
-} eth_port_t;
-
-#define EPF_EMPTY 0x0
-#define EPF_ENABLED 0x1
-#define EPF_GOT_ADDR 0x2 /* Got ethernet address from device */
-#define EPF_READ_IP 0x20
-#define EPF_READ_SP 0x40
-
-extern eth_port_t *eth_port_table;
-
-extern int no_ethWritePort; /* debug, consistency check */
-
-void osdep_eth_init ARGS(( void ));
-int eth_get_stat ARGS(( eth_port_t *eth_port, eth_stat_t *eth_stat ));
-void eth_write_port ARGS(( eth_port_t *eth_port, acc_t *pack ));
-void eth_arrive ARGS(( eth_port_t *port, acc_t *pack, size_t pack_size ));
-void eth_set_rec_conf ARGS(( eth_port_t *eth_port, u32_t flags ));
-void eth_restart_write ARGS(( eth_port_t *eth_port ));
-void eth_loop_ev ARGS(( event_t *ev, ev_arg_t ev_arg ));
-void eth_reg_vlan ARGS(( eth_port_t *eth_port, eth_port_t *vlan_port ));
-void eth_restart_ioctl ARGS(( eth_port_t *eth_port ));
-
-#endif /* ETH_INT_H */
-
-/*
- * $PchId: eth_int.h,v 1.9 2001/04/23 08:04:06 philip Exp $
- */
+++ /dev/null
-/*
-inet/generic/event.c
-
-Created: April 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Implementation of an event queue.
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "assert.h"
-#include "event.h"
-
-THIS_FILE
-
-event_t *ev_head;
-static event_t *ev_tail;
-
-void ev_init(ev)
-event_t *ev;
-{
- ev->ev_func= 0;
- ev->ev_next= NULL;
-}
-
-void ev_enqueue(ev, func, ev_arg)
-event_t *ev;
-ev_func_t func;
-ev_arg_t ev_arg;
-{
- assert(ev->ev_func == 0);
- ev->ev_func= func;
- ev->ev_arg= ev_arg;
- ev->ev_next= NULL;
- if (ev_head == NULL)
- ev_head= ev;
- else
- ev_tail->ev_next= ev;
- ev_tail= ev;
-}
-
-void ev_process()
-{
- ev_func_t func;
- event_t *curr;
-
- while (ev_head)
- {
- curr= ev_head;
- ev_head= curr->ev_next;
- func= curr->ev_func;
- curr->ev_func= 0;
-
- assert(func != 0);
- func(curr, curr->ev_arg);
- }
-}
-
-int ev_in_queue(ev)
-event_t *ev;
-{
- return ev->ev_func != 0;
-}
-
-
-/*
- * $PchId: event.c,v 1.6 2004/08/03 16:23:32 philip Exp $
- */
+++ /dev/null
-/*
-inet/generic/event.h
-
-Created: April 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Header file for an event mechanism.
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__GENERIC__EVENT_H
-#define INET__GENERIC__EVENT_H
-
-struct event;
-
-typedef struct ev_arg
-{
- void *ev_ptr;
-} ev_arg_t;
-
-typedef void (*ev_func_t) ARGS(( struct event *ev, ev_arg_t eva ));
-
-typedef struct event
-{
- ev_func_t ev_func;
- ev_arg_t ev_arg;
- struct event *ev_next;
-} event_t;
-
-extern event_t *ev_head;
-
-void ev_init ARGS(( event_t *ev ));
-void ev_enqueue ARGS(( event_t *ev, ev_func_t func, ev_arg_t ev_arg ));
-void ev_process ARGS(( void ));
-int ev_in_queue ARGS(( event_t *ev ));
-
-#endif /* INET__GENERIC__EVENT_H */
-
-/*
- * $PchId: event.h,v 1.5 2004/08/03 16:23:49 philip Exp $
- */
+++ /dev/null
-/*
-icmp.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-
-#include "assert.h"
-#include "clock.h"
-#include "icmp.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "ipr.h"
-
-THIS_FILE
-
-typedef struct icmp_port
-{
- int icp_flags;
- int icp_state;
- int icp_ipport;
- int icp_ipfd;
- unsigned icp_rate_count;
- unsigned icp_rate_report;
- time_t icp_rate_lasttime;
- acc_t *icp_head_queue;
- acc_t *icp_tail_queue;
- acc_t *icp_write_pack;
- event_t icp_event;
-} icmp_port_t;
-
-#define ICPF_EMPTY 0x0
-#define ICPF_SUSPEND 0x1
-#define ICPF_READ_IP 0x2
-#define ICPF_READ_SP 0x4
-#define ICPF_WRITE_IP 0x8
-#define ICPF_WRITE_SP 0x10
-
-#define ICPS_BEGIN 0
-#define ICPS_IPOPT 1
-#define ICPS_MAIN 2
-#define ICPS_ERROR 3
-
-static icmp_port_t *icmp_port_table;
-
-static void icmp_main ARGS(( icmp_port_t *icmp_port ));
-static acc_t *icmp_getdata ARGS(( int port, size_t offset,
- size_t count, int for_ioctl ));
-static int icmp_putdata ARGS(( int port, size_t offset,
- acc_t *data, int for_ioctl ));
-static void icmp_read ARGS(( icmp_port_t *icmp_port ));
-static void process_data ARGS(( icmp_port_t *icmp_port,
- acc_t *data ));
-static u16_t icmp_pack_oneCsum ARGS(( acc_t *ip_pack ));
-static void icmp_echo_request ARGS(( icmp_port_t *icmp_port,
- acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
- acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
-static void icmp_dst_unreach ARGS(( icmp_port_t *icmp_port,
- acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
- acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
-static void icmp_time_exceeded ARGS(( icmp_port_t *icmp_port,
- acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
- acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
-static void icmp_router_advertisement ARGS(( icmp_port_t *icmp_port,
- acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
-static void icmp_redirect ARGS(( icmp_port_t *icmp_port,
- ip_hdr_t *ip_hdr, acc_t *icmp_pack, int icmp_len,
- icmp_hdr_t *icmp_hdr ));
-static acc_t *make_repl_ip ARGS(( ip_hdr_t *ip_hdr,
- int ip_len ));
-static void enqueue_pack ARGS(( icmp_port_t *icmp_port,
- acc_t *reply_ip_hdr ));
-static int icmp_rate_limit ARGS(( icmp_port_t *icmp_port,
- acc_t *reply_ip_hdr ));
-static void icmp_write ARGS(( event_t *ev, ev_arg_t ev_arg ));
-static void icmp_buffree ARGS(( int priority ));
-static acc_t *icmp_err_pack ARGS(( acc_t *pack, icmp_hdr_t **icmp_hdr_pp ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void icmp_bufcheck ARGS(( void ));
-#endif
-
-void icmp_prep()
-{
- icmp_port_table= alloc(ip_conf_nr * sizeof(icmp_port_table[0]));
-}
-
-void icmp_init()
-{
- int i;
- icmp_port_t *icmp_port;
-
- assert (BUF_S >= sizeof (nwio_ipopt_t));
-
- for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
- {
- icmp_port->icp_flags= ICPF_EMPTY;
- icmp_port->icp_state= ICPS_BEGIN;
- icmp_port->icp_ipport= i;
- icmp_port->icp_rate_count= 0;
- icmp_port->icp_rate_report= ICMP_MAX_RATE;
- icmp_port->icp_rate_lasttime= 0;
- ev_init(&icmp_port->icp_event);
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(icmp_buffree);
-#else
- bf_logon(icmp_buffree, icmp_bufcheck);
-#endif
-
- for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
- {
- icmp_main (icmp_port);
- }
-}
-
-static void icmp_main(icmp_port)
-icmp_port_t *icmp_port;
-{
- int result;
- switch (icmp_port->icp_state)
- {
- case ICPS_BEGIN:
- icmp_port->icp_head_queue= 0;
- icmp_port->icp_ipfd= ip_open(icmp_port->icp_ipport,
- icmp_port->icp_ipport, icmp_getdata, icmp_putdata,
- 0 /* no put_pkt */, 0 /* no select_res */);
- if (icmp_port->icp_ipfd<0)
- {
- DBLOCK(1, printf("unable to open ip_port %d\n",
- icmp_port->icp_ipport));
- break;
- }
- icmp_port->icp_state= ICPS_IPOPT;
- icmp_port->icp_flags &= ~ICPF_SUSPEND;
- result= ip_ioctl (icmp_port->icp_ipfd, NWIOSIPOPT);
- if (result == NW_SUSPEND)
- {
- icmp_port->icp_flags |= ICPF_SUSPEND;
- break;
- }
- assert(result == NW_OK);
-
- /* falls through */
- case ICPS_IPOPT:
- icmp_port->icp_state= ICPS_MAIN;
- icmp_port->icp_flags &= ~ICPF_SUSPEND;
- icmp_read(icmp_port);
- break;
- default:
- DBLOCK(1, printf("unknown state %d\n",
- icmp_port->icp_state));
- break;
- }
-}
-
-static acc_t *icmp_getdata(port, offset, count, for_ioctl)
-int port;
-size_t offset, count;
-int for_ioctl;
-{
- icmp_port_t *icmp_port;
- nwio_ipopt_t *ipopt;
- acc_t *data;
- int result;
- ev_arg_t ev_arg;
-
- icmp_port= &icmp_port_table[port];
-
- if (icmp_port->icp_flags & ICPF_WRITE_IP)
- {
- if (!count)
- {
- bf_afree(icmp_port->icp_write_pack);
- icmp_port->icp_write_pack= 0;
-
- result= (int)offset;
- if (result<0)
- {
- DBLOCK(1, printf("got write error %d\n",
- result));
- }
- if (icmp_port->icp_flags & ICPF_WRITE_SP)
- {
- icmp_port->icp_flags &= ~ICPF_WRITE_SP;
- ev_arg.ev_ptr= icmp_port;
- ev_enqueue(&icmp_port->icp_event, icmp_write,
- ev_arg);
- }
- return NW_OK;
- }
- return bf_cut(icmp_port->icp_write_pack, offset, count);
- }
- switch (icmp_port->icp_state)
- {
- case ICPS_IPOPT:
- if (!count)
- {
- result= (int)offset;
- assert(result == NW_OK);
- if (result < 0)
- {
- icmp_port->icp_state= ICPS_ERROR;
- break;
- }
- if (icmp_port->icp_flags & ICPF_SUSPEND)
- icmp_main(icmp_port);
- return NW_OK;
- }
-
- data= bf_memreq (sizeof (*ipopt));
- ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
- ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |
- NWIO_EN_BROAD |
- NWIO_REMANY | NWIO_PROTOSPEC |
- NWIO_HDR_O_ANY | NWIO_RWDATALL;
- ipopt->nwio_proto= IPPROTO_ICMP;
- return data;
- default:
- break;
- }
- DBLOCK(1, printf("unknown state %d\n", icmp_port->icp_state));
- return NULL;
-}
-
-static int icmp_putdata(port, offset, data, for_ioctl)
-int port;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- icmp_port_t *icmp_port;
- int result;
-
- icmp_port= &icmp_port_table[port];
-
- if (icmp_port->icp_flags & ICPF_READ_IP)
- {
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- DBLOCK(1, printf("got read error %d\n",
- result));
- }
- if (icmp_port->icp_flags & ICPF_READ_SP)
- {
- icmp_port->icp_flags &=
- ~(ICPF_READ_IP|ICPF_READ_SP);
- icmp_read (icmp_port);
- }
- return NW_OK;
- }
- process_data(icmp_port, data);
- return NW_OK;
- }
- switch (icmp_port->icp_state)
- {
- default:
- DBLOCK(1, printf("unknown state %d\n",
- icmp_port->icp_state));
- return 0;
- }
-}
-
-static void icmp_read(icmp_port)
-icmp_port_t *icmp_port;
-{
- int result;
-
- for (;;)
- {
- icmp_port->icp_flags |= ICPF_READ_IP;
- icmp_port->icp_flags &= ~ICPF_READ_SP;
-
- result= ip_read(icmp_port->icp_ipfd, ICMP_MAX_DATAGRAM);
- if (result == NW_SUSPEND)
- {
- icmp_port->icp_flags |= ICPF_READ_SP;
- return;
- }
- }
-}
-
-void icmp_snd_time_exceeded(port_nr, pack, code)
-int port_nr;
-acc_t *pack;
-int code;
-{
- icmp_hdr_t *icmp_hdr;
- icmp_port_t *icmp_port;
-
- if (port_nr >= 0 && port_nr < ip_conf_nr)
- icmp_port= &icmp_port_table[port_nr];
- else
- {
- printf("icmp_snd_time_exceeded: strange port %d\n", port_nr);
- bf_afree(pack);
- return;
- }
- pack= icmp_err_pack(pack, &icmp_hdr);
- if (pack == NULL)
- return;
- icmp_hdr->ih_type= ICMP_TYPE_TIME_EXCEEDED;
- icmp_hdr->ih_code= code;
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_type, 2);
- enqueue_pack(icmp_port, pack);
-}
-
-void icmp_snd_redirect(port_nr, pack, code, gw)
-int port_nr;
-acc_t *pack;
-int code;
-ipaddr_t gw;
-{
- icmp_hdr_t *icmp_hdr;
- icmp_port_t *icmp_port;
-
- if (port_nr >= 0 && port_nr < ip_conf_nr)
- icmp_port= &icmp_port_table[port_nr];
- else
- {
- printf("icmp_snd_redirect: strange port %d\n", port_nr);
- bf_afree(pack);
- return;
- }
- pack= icmp_err_pack(pack, &icmp_hdr);
- if (pack == NULL)
- return;
- icmp_hdr->ih_type= ICMP_TYPE_REDIRECT;
- icmp_hdr->ih_code= code;
- icmp_hdr->ih_hun.ihh_gateway= gw;
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_type, 2);
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_hun.ihh_gateway, 4);
- enqueue_pack(icmp_port, pack);
-}
-
-void icmp_snd_unreachable(port_nr, pack, code)
-int port_nr;
-acc_t *pack;
-int code;
-{
- icmp_hdr_t *icmp_hdr;
- icmp_port_t *icmp_port;
-
- if (port_nr >= 0 && port_nr < ip_conf_nr)
- icmp_port= &icmp_port_table[port_nr];
- else
- {
- printf("icmp_snd_unreachable: strange port %d\n", port_nr);
- bf_afree(pack);
- return;
- }
- pack= icmp_err_pack(pack, &icmp_hdr);
- if (pack == NULL)
- return;
- icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;
- icmp_hdr->ih_code= code;
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_type, 2);
- enqueue_pack(icmp_port, pack);
-}
-
-void icmp_snd_mtu(
- int port_nr,
- acc_t *pack,
- u16_t mtu
-)
-{
- icmp_hdr_t *icmp_hdr;
- icmp_port_t *icmp_port;
-
- if (port_nr >= 0 && port_nr < ip_conf_nr)
- icmp_port= &icmp_port_table[port_nr];
- else
- {
- printf("icmp_snd_mtu: strange port %d\n", port_nr);
- bf_afree(pack);
- return;
- }
-
- pack= icmp_err_pack(pack, &icmp_hdr);
- if (pack == NULL)
- return;
- icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;
- icmp_hdr->ih_code= ICMP_FRAGM_AND_DF;
- icmp_hdr->ih_hun.ihh_mtu.im_mtu= htons(mtu);
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_type, 2);
- icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
- (u16_t *)&icmp_hdr->ih_hun.ihh_mtu.im_mtu, 2);
- enqueue_pack(icmp_port, pack);
-}
-
-static void process_data(icmp_port, data)
-icmp_port_t *icmp_port;
-acc_t *data;
-{
- ip_hdr_t *ip_hdr;
- icmp_hdr_t *icmp_hdr;
- acc_t *icmp_data;
- int ip_hdr_len;
- size_t pack_len;
-
- /* Align entire packet */
- data= bf_align(data, BUF_S, 4);
-
- data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- DIFBLOCK(0x10, (ip_hdr->ih_dst & HTONL(0xf0000000)) == HTONL(0xe0000000),
- printf("got multicast packet\n"));
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
-
- if (ip_hdr_len>IP_MIN_HDR_SIZE)
- {
- data= bf_packIffLess(data, ip_hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- }
-
- pack_len= bf_bufsize(data);
- pack_len -= ip_hdr_len;
- if (pack_len < ICMP_MIN_HDR_SIZE)
- {
- if (pack_len == 0 && ip_hdr->ih_proto == 0)
- {
- /* IP layer reports new ip address, which can be
- * ignored.
- */
- }
- else
- DBLOCK(1, printf("got an incomplete icmp packet\n"));
- bf_afree(data);
- return;
- }
-
- icmp_data= bf_cut(data, ip_hdr_len, pack_len);
-
- icmp_data= bf_packIffLess (icmp_data, ICMP_MIN_HDR_SIZE);
- icmp_hdr= (icmp_hdr_t *)ptr2acc_data(icmp_data);
-
- if ((u16_t)~icmp_pack_oneCsum(icmp_data))
- {
- DBLOCK(1, printf(
- "got packet with bad checksum (= 0x%x, 0x%x)\n",
- icmp_hdr->ih_chksum,
- (u16_t)~icmp_pack_oneCsum(icmp_data)));
- bf_afree(data);
- bf_afree(icmp_data);
- return;
- }
-
- switch (icmp_hdr->ih_type)
- {
- case ICMP_TYPE_ECHO_REPL:
- break;
- case ICMP_TYPE_DST_UNRCH:
- icmp_dst_unreach (icmp_port, data, ip_hdr_len, ip_hdr,
- icmp_data, pack_len, icmp_hdr);
- break;
- case ICMP_TYPE_SRC_QUENCH:
- /* Ignore src quench ICMPs */
- DBLOCK(2, printf("ignoring SRC QUENCH ICMP.\n"));
- break;
- case ICMP_TYPE_REDIRECT:
- icmp_redirect (icmp_port, ip_hdr, icmp_data, pack_len,
- icmp_hdr);
- break;
- case ICMP_TYPE_ECHO_REQ:
- icmp_echo_request(icmp_port, data, ip_hdr_len, ip_hdr,
- icmp_data, pack_len, icmp_hdr);
- return;
- case ICMP_TYPE_ROUTER_ADVER:
- icmp_router_advertisement(icmp_port, icmp_data, pack_len,
- icmp_hdr);
- break;
- case ICMP_TYPE_ROUTE_SOL:
- break; /* Should be handled by a routing deamon. */
- case ICMP_TYPE_TIME_EXCEEDED:
- icmp_time_exceeded (icmp_port, data, ip_hdr_len, ip_hdr,
- icmp_data, pack_len, icmp_hdr);
- break;
- default:
- DBLOCK(1, printf("got an unknown icmp (%d) from ",
- icmp_hdr->ih_type);
- writeIpAddr(ip_hdr->ih_src); printf("\n"));
- break;
- }
- bf_afree(data);
- bf_afree(icmp_data);
-}
-
-static void icmp_echo_request(icmp_port, ip_data, ip_len, ip_hdr,
- icmp_data, icmp_len, icmp_hdr)
-icmp_port_t *icmp_port;
-acc_t *ip_data, *icmp_data;
-int ip_len, icmp_len;
-ip_hdr_t *ip_hdr;
-icmp_hdr_t *icmp_hdr;
-{
- acc_t *repl_ip_hdr, *repl_icmp;
- ipaddr_t tmpaddr, locaddr, netmask;
- icmp_hdr_t *repl_icmp_hdr;
- i32_t tmp_chksum;
- ip_port_t *ip_port;
-
- if (icmp_hdr->ih_code != 0)
- {
- DBLOCK(1,
- printf("got an icmp echo request with unknown code (%d)\n",
- icmp_hdr->ih_code));
- bf_afree(ip_data);
- bf_afree(icmp_data);
- return;
- }
- if (icmp_len < ICMP_MIN_HDR_SIZE + sizeof(icmp_id_seq_t))
- {
- DBLOCK(1, printf("got an incomplete icmp echo request\n"));
- bf_afree(ip_data);
- bf_afree(icmp_data);
- return;
- }
- tmpaddr= ntohl(ip_hdr->ih_dst);
- if ((tmpaddr & 0xe0000000) == 0xe0000000 &&
- tmpaddr != 0xffffffff)
- {
- /* Respond only to the all hosts multicast address until
- * a decent listening service has been implemented
- */
- if (tmpaddr != 0xe0000001)
- {
- bf_afree(ip_data);
- bf_afree(icmp_data);
- return;
- }
- }
-
- /* Limit subnet broadcasts to the local net */
- ip_port= &ip_port_table[icmp_port->icp_ipport];
- locaddr= ip_port->ip_ipaddr;
- netmask= ip_port->ip_subnetmask;
- if (ip_hdr->ih_dst == (locaddr | ~netmask) &&
- (ip_port->ip_flags & IPF_SUBNET_BCAST) &&
- ((ip_hdr->ih_src ^ locaddr) & netmask) != 0)
- {
- /* Directed broadcast */
- bf_afree(ip_data);
- bf_afree(icmp_data);
- return;
- }
-
- repl_ip_hdr= make_repl_ip(ip_hdr, ip_len);
- repl_icmp= bf_memreq (ICMP_MIN_HDR_SIZE);
- repl_icmp_hdr= (icmp_hdr_t *)ptr2acc_data(repl_icmp);
- repl_icmp_hdr->ih_type= ICMP_TYPE_ECHO_REPL;
- repl_icmp_hdr->ih_code= 0;
-
- DBLOCK(2,
- printf("ih_chksum= 0x%x, ih_type= 0x%x, repl->ih_type= 0x%x\n",
- icmp_hdr->ih_chksum, *(u16_t *)&icmp_hdr->ih_type,
- *(u16_t *)&repl_icmp_hdr->ih_type));
- tmp_chksum= (~icmp_hdr->ih_chksum & 0xffff) -
- (i32_t)*(u16_t *)&icmp_hdr->ih_type+
- *(u16_t *)&repl_icmp_hdr->ih_type;
- tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
- tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
- repl_icmp_hdr->ih_chksum= ~tmp_chksum;
- DBLOCK(2, printf("sending chksum 0x%x\n", repl_icmp_hdr->ih_chksum));
-
- repl_ip_hdr->acc_next= repl_icmp;
- repl_icmp->acc_next= bf_cut (icmp_data, ICMP_MIN_HDR_SIZE,
- icmp_len - ICMP_MIN_HDR_SIZE);
-
- bf_afree(ip_data);
- bf_afree(icmp_data);
-
- enqueue_pack(icmp_port, repl_ip_hdr);
-}
-
-static u16_t icmp_pack_oneCsum(icmp_pack)
-acc_t *icmp_pack;
-{
- u16_t prev;
- int odd_byte;
- char *data_ptr;
- int length;
- char byte_buf[2];
-
- prev= 0;
-
- odd_byte= FALSE;
- for (; icmp_pack; icmp_pack= icmp_pack->acc_next)
- {
- data_ptr= ptr2acc_data(icmp_pack);
- length= icmp_pack->acc_length;
-
- if (!length)
- continue;
- if (odd_byte)
- {
- byte_buf[1]= *data_ptr;
- prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
- data_ptr++;
- length--;
- odd_byte= FALSE;
- }
- if (length & 1)
- {
- odd_byte= TRUE;
- length--;
- byte_buf[0]= data_ptr[length];
- }
- if (!length)
- continue;
- prev= oneC_sum (prev, (u16_t *)data_ptr, length);
- }
- if (odd_byte)
- prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
- return prev;
-}
-
-static acc_t *make_repl_ip(ip_hdr, ip_len)
-ip_hdr_t *ip_hdr;
-int ip_len;
-{
- ip_hdr_t *repl_ip_hdr;
- acc_t *repl;
- int repl_hdr_len;
-
- if (ip_len>IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
- ip_len= IP_MIN_HDR_SIZE;
- }
-
- repl_hdr_len= IP_MIN_HDR_SIZE;
-
- repl= bf_memreq(repl_hdr_len);
-
- repl_ip_hdr= (ip_hdr_t *)ptr2acc_data(repl);
-
- repl_ip_hdr->ih_vers_ihl= repl_hdr_len >> 2;
- repl_ip_hdr->ih_tos= ip_hdr->ih_tos;
- repl_ip_hdr->ih_ttl= ICMP_DEF_TTL;
- repl_ip_hdr->ih_proto= IPPROTO_ICMP;
- repl_ip_hdr->ih_dst= ip_hdr->ih_src;
- repl_ip_hdr->ih_flags_fragoff= 0;
-
- return repl;
-}
-
-static void enqueue_pack(icmp_port, reply_ip_hdr)
-icmp_port_t *icmp_port;
-acc_t *reply_ip_hdr;
-{
- int r;
- ev_arg_t ev_arg;
-
- /* Check rate */
- if (icmp_port->icp_rate_count >= ICMP_MAX_RATE)
- {
- /* Something is going wrong; check policy */
- r= icmp_rate_limit(icmp_port, reply_ip_hdr);
- if (r == -1)
- {
- bf_afree(reply_ip_hdr);
- return;
- }
-
- /* OK, continue */
- }
- icmp_port->icp_rate_count++;
-
- reply_ip_hdr->acc_ext_link= 0;
-
- if (icmp_port->icp_head_queue)
- {
- icmp_port->icp_tail_queue->acc_ext_link=
- reply_ip_hdr;
- }
- else
- {
- icmp_port->icp_head_queue= reply_ip_hdr;
- }
- reply_ip_hdr->acc_ext_link= NULL;
- icmp_port->icp_tail_queue= reply_ip_hdr;
-
- if (!(icmp_port->icp_flags & ICPF_WRITE_IP))
- {
- icmp_port->icp_flags |= ICPF_WRITE_IP;
- ev_arg.ev_ptr= icmp_port;
- ev_enqueue(&icmp_port->icp_event, icmp_write, ev_arg);
- }
-}
-
-static int icmp_rate_limit(icmp_port, reply_ip_hdr)
-icmp_port_t *icmp_port;
-acc_t *reply_ip_hdr;
-{
- time_t t;
- acc_t *pack;
- ip_hdr_t *ip_hdr;
- icmp_hdr_t *icmp_hdr;
- int hdrlen, icmp_hdr_len, type;
-
- /* Check the time first */
- t= get_time();
- if (t >= icmp_port->icp_rate_lasttime + ICMP_RATE_INTERVAL)
- {
- icmp_port->icp_rate_lasttime= t;
- icmp_port->icp_rate_count= 0;
- return 0;
- }
-
- icmp_port->icp_rate_count++;
-
- /* Adjust report limit if necessary */
- if (icmp_port->icp_rate_count >
- icmp_port->icp_rate_report+ICMP_RATE_WARN)
- {
- icmp_port->icp_rate_report *= 2;
- return -1;
- }
-
- /* Do we need to report */
- if (icmp_port->icp_rate_count < icmp_port->icp_rate_report)
- return -1;
-
- pack= bf_dupacc(reply_ip_hdr);
- pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- printf("icmp[%d]: dropping ICMP packet #%d to ",
- icmp_port->icp_ipport, icmp_port->icp_rate_count);
- writeIpAddr(ip_hdr->ih_dst);
- hdrlen= (ip_hdr->ih_vers_ihl & IH_IHL_MASK)*4;
- pack= bf_packIffLess(pack, hdrlen+ICMP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);
- type= icmp_hdr->ih_type;
- printf(" type %d, code %d\n", type, icmp_hdr->ih_code);
- switch(type)
- {
- case ICMP_TYPE_DST_UNRCH:
- case ICMP_TYPE_SRC_QUENCH:
- case ICMP_TYPE_REDIRECT:
- case ICMP_TYPE_TIME_EXCEEDED:
- case ICMP_TYPE_PARAM_PROBLEM:
- icmp_hdr_len= offsetof(struct icmp_hdr, ih_dun);
- pack= bf_packIffLess(pack,
- hdrlen+icmp_hdr_len+IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)(ptr2acc_data(pack)+hdrlen+icmp_hdr_len);
- icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);
- printf("\tinfo %08x, original dst ",
- ntohs(icmp_hdr->ih_hun.ihh_unused));
- writeIpAddr(ip_hdr->ih_dst);
- printf(", proto %d, length %u\n",
- ip_hdr->ih_proto, ntohs(ip_hdr->ih_length));
- break;
- default:
- break;
- }
- bf_afree(pack); pack= NULL;
-
- return -1;
-}
-
-static void icmp_write(ev, ev_arg)
-event_t *ev;
-ev_arg_t ev_arg;
-{
- int result;
- icmp_port_t *icmp_port;
- acc_t *data;
-
- icmp_port= ev_arg.ev_ptr;
- assert(ev == &icmp_port->icp_event);
-
- assert (icmp_port->icp_flags & ICPF_WRITE_IP);
- assert (!(icmp_port->icp_flags & ICPF_WRITE_SP));
-
- while (icmp_port->icp_head_queue != NULL)
- {
- data= icmp_port->icp_head_queue;
- icmp_port->icp_head_queue= data->acc_ext_link;
-
- result= ip_send(icmp_port->icp_ipfd, data,
- bf_bufsize(data));
- if (result != NW_WOULDBLOCK)
- {
- if (result == NW_OK)
- continue;
- DBLOCK(1, printf("icmp_write: error %d\n", result););
- continue;
- }
-
- assert(icmp_port->icp_write_pack == NULL);
- icmp_port->icp_write_pack= data;
-
- result= ip_write(icmp_port->icp_ipfd,
- bf_bufsize(icmp_port->icp_write_pack));
- if (result == NW_SUSPEND)
- {
- icmp_port->icp_flags |= ICPF_WRITE_SP;
- return;
- }
- }
- icmp_port->icp_flags &= ~ICPF_WRITE_IP;
-}
-
-static void icmp_buffree(priority)
-int priority;
-{
- acc_t *tmp_acc;
- int i;
- icmp_port_t *icmp_port;
-
- if (priority == ICMP_PRI_QUEUE)
- {
- for (i=0, icmp_port= icmp_port_table; i<ip_conf_nr;
- i++, icmp_port++)
- {
- while(icmp_port->icp_head_queue)
- {
- tmp_acc= icmp_port->icp_head_queue;
- icmp_port->icp_head_queue=
- tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- }
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void icmp_bufcheck()
-{
- int i;
- icmp_port_t *icmp_port;
- acc_t *pack;
-
- for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
- {
- for (pack= icmp_port->icp_head_queue; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- bf_check_acc(icmp_port->icp_write_pack);
- }
-}
-#endif
-
-static void icmp_dst_unreach(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack,
- icmp_len, icmp_hdr)
-icmp_port_t *icmp_port;
-acc_t *ip_pack;
-int ip_hdr_len;
-ip_hdr_t *ip_hdr;
-acc_t *icmp_pack;
-int icmp_len;
-icmp_hdr_t *icmp_hdr;
-{
- acc_t *old_ip_pack;
- ip_hdr_t *old_ip_hdr;
- int ip_port_nr;
- ipaddr_t dst, mask;
- size_t old_pack_size;
- u16_t new_mtu;
-
- if (icmp_len < 8 + IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("dest unrch with wrong size\n"));
- return;
- }
- old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
- old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
- old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
-
- if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
- {
- DBLOCK(1, printf("dest unrch based on wrong packet\n"));
- bf_afree(old_ip_pack);
- return;
- }
-
- ip_port_nr= icmp_port->icp_ipport;
-
- switch(icmp_hdr->ih_code)
- {
- case ICMP_NET_UNRCH:
- dst= old_ip_hdr->ih_dst;
- mask= ip_get_netmask(dst);
- ipr_destunrch (ip_port_nr, dst & mask, mask,
- IPR_UNRCH_TIMEOUT);
- break;
- case ICMP_HOST_UNRCH:
- ipr_destunrch (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
- IPR_UNRCH_TIMEOUT);
- break;
- case ICMP_PORT_UNRCH:
- /* At the moment we don't do anything with this information.
- * It should be handed to the appropriate transport layer.
- */
- break;
- case ICMP_FRAGM_AND_DF:
-
- DBLOCK(1, printf("icmp_dst_unreach: got mtu icmp from ");
- writeIpAddr(ip_hdr->ih_src);
- printf("; original destination: ");
- writeIpAddr(old_ip_hdr->ih_dst);
- printf("; protocol: %d\n",
- old_ip_hdr->ih_proto));
- old_pack_size= ntohs(old_ip_hdr->ih_length);
- if (!old_pack_size)
- break;
- new_mtu= ntohs(icmp_hdr->ih_hun.ihh_mtu.im_mtu);
- if (!new_mtu || new_mtu > old_pack_size)
- new_mtu= old_pack_size-1;
- ipr_mtu(ip_port_nr, old_ip_hdr->ih_dst, new_mtu,
- IPR_MTU_TIMEOUT);
- break;
-
- default:
- DBLOCK(1, printf("icmp_dst_unreach: got strange code %d from ",
- icmp_hdr->ih_code);
- writeIpAddr(ip_hdr->ih_src);
- printf("; original destination: ");
- writeIpAddr(old_ip_hdr->ih_dst);
- printf("; protocol: %d\n",
- old_ip_hdr->ih_proto));
- break;
- }
- bf_afree(old_ip_pack);
-}
-
-static void icmp_time_exceeded(icmp_port, ip_pack, ip_hdr_len, ip_hdr,
- icmp_pack, icmp_len, icmp_hdr)
-icmp_port_t *icmp_port;
-acc_t *ip_pack;
-int ip_hdr_len;
-ip_hdr_t *ip_hdr;
-acc_t *icmp_pack;
-int icmp_len;
-icmp_hdr_t *icmp_hdr;
-{
- acc_t *old_ip_pack;
- ip_hdr_t *old_ip_hdr;
- int ip_port_nr;
-
- if (icmp_len < 8 + IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("time exceeded with wrong size\n"));
- return;
- }
- old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
- old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
- old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
-
- if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
- {
- DBLOCK(1, printf("time exceeded based on wrong packet\n"));
- bf_afree(old_ip_pack);
- return;
- }
-
- ip_port_nr= icmp_port->icp_ipport;
-
- switch(icmp_hdr->ih_code)
- {
- case ICMP_TTL_EXC:
- ipr_ttl_exc (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
- IPR_TTL_TIMEOUT);
- break;
- case ICMP_FRAG_REASSEM:
- /* Ignore reassembly time-outs. */
- break;
- default:
- DBLOCK(1, printf("got strange code: %d\n",
- icmp_hdr->ih_code));
- break;
- }
- bf_afree(old_ip_pack);
-}
-
-static void icmp_router_advertisement(icmp_port, icmp_pack, icmp_len, icmp_hdr)
-icmp_port_t *icmp_port;
-acc_t *icmp_pack;
-int icmp_len;
-icmp_hdr_t *icmp_hdr;
-{
- int entries;
- int entry_size;
- u16_t lifetime;
- int i;
- char *bufp;
-
- if (icmp_len < 8)
- {
- DBLOCK(1,
- printf("router advertisement with wrong size (%d)\n",
- icmp_len));
- return;
- }
- if (icmp_hdr->ih_code != 0)
- {
- DBLOCK(1,
- printf("router advertisement with wrong code (%d)\n",
- icmp_hdr->ih_code));
- return;
- }
- entries= icmp_hdr->ih_hun.ihh_ram.iram_na;
- entry_size= icmp_hdr->ih_hun.ihh_ram.iram_aes * 4;
- if (entries < 1)
- {
- DBLOCK(1, printf(
- "router advertisement with wrong number of entries (%d)\n",
- entries));
- return;
- }
- if (entry_size < 8)
- {
- DBLOCK(1, printf(
- "router advertisement with wrong entry size (%d)\n",
- entry_size));
- return;
- }
- if (icmp_len < 8 + entries * entry_size)
- {
- DBLOCK(1,
- printf("router advertisement with wrong size\n");
- printf(
- "\t(entries= %d, entry_size= %d, icmp_len= %d)\n",
- entries, entry_size, icmp_len));
- return;
- }
- lifetime= ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt);
- if (lifetime > 9000)
- {
- DBLOCK(1, printf(
- "router advertisement with wrong lifetime (%d)\n",
- lifetime));
- return;
- }
- for (i= 0, bufp= (char *)&icmp_hdr->ih_dun.uhd_data[0]; i< entries; i++,
- bufp += entry_size)
- {
- u32_t addr;
- i32_t pref;
-
- addr= *(ipaddr_t *)bufp;
- pref= ntohl(*(u32_t *)(bufp+4));
- ipr_add_oroute(icmp_port->icp_ipport, HTONL(0L), HTONL(0L),
- addr, lifetime ? lifetime * HZ : 1,
- 1, 0, 0, pref, NULL);
- }
-}
-
-static void icmp_redirect(icmp_port, ip_hdr, icmp_pack, icmp_len, icmp_hdr)
-icmp_port_t *icmp_port;
-ip_hdr_t *ip_hdr;
-acc_t *icmp_pack;
-int icmp_len;
-icmp_hdr_t *icmp_hdr;
-{
- acc_t *old_ip_pack;
- ip_hdr_t *old_ip_hdr;
- int ip_port_nr;
- ipaddr_t dst, mask;
-
- if (icmp_len < 8 + IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("redirect with wrong size\n"));
- return;
- }
- old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
- old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
- old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
-
- ip_port_nr= icmp_port->icp_ipport;
-
- switch(icmp_hdr->ih_code)
- {
- case ICMP_REDIRECT_NET:
- dst= old_ip_hdr->ih_dst;
- mask= ip_get_netmask(dst);
- ipr_redirect (ip_port_nr, dst & mask, mask,
- ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway,
- IPR_REDIRECT_TIMEOUT);
- break;
- case ICMP_REDIRECT_HOST:
- ipr_redirect (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
- ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway,
- IPR_REDIRECT_TIMEOUT);
- break;
- default:
- DBLOCK(1, printf("got strange code: %d\n",
- icmp_hdr->ih_code));
- break;
- }
- bf_afree(old_ip_pack);
-}
-
-static acc_t *icmp_err_pack(pack, icmp_hdr_pp)
-acc_t *pack;
-icmp_hdr_t **icmp_hdr_pp;
-{
- ip_hdr_t *ip_hdr;
- icmp_hdr_t *icmp_hdr_p;
- acc_t *ip_pack, *icmp_pack, *tmp_pack;
- int ip_hdr_len, icmp_hdr_len, ih_type;
- size_t size, pack_len;
- ipaddr_t dest;
- nettype_t nettype;
-
- pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- pack_len= bf_bufsize(pack);
-
- /* If the IP protocol is ICMP (except echo request/reply) or the
- * fragment offset is non-zero,
- * drop the packet. Also check if the source address is valid.
- */
- if ((ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK) != 0)
- {
- bf_afree(pack);
- return NULL;
- }
- if (ip_hdr->ih_proto == IPPROTO_ICMP)
- {
- if (ip_hdr_len>IP_MIN_HDR_SIZE)
- {
- pack= bf_packIffLess(pack, ip_hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- }
-
- if (pack_len < ip_hdr_len+ICMP_MIN_HDR_SIZE)
- {
- bf_afree(pack);
- return NULL;
- }
- icmp_pack= bf_cut(pack, ip_hdr_len, ICMP_MIN_HDR_SIZE);
- icmp_pack= bf_packIffLess (icmp_pack, ICMP_MIN_HDR_SIZE);
- icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(icmp_pack);
- ih_type= icmp_hdr_p->ih_type;
- bf_afree(icmp_pack); icmp_pack= NULL;
-
- if (ih_type != ICMP_TYPE_ECHO_REQ &&
- ih_type != ICMP_TYPE_ECHO_REPL)
- {
- bf_afree(pack);
- return NULL;
- }
- }
- dest= ip_hdr->ih_src;
- nettype= ip_nettype(dest);
- if (nettype != IPNT_CLASS_A && nettype != IPNT_LOCAL &&
- nettype != IPNT_CLASS_B && nettype != IPNT_CLASS_C)
- {
- printf("icmp_err_pack: invalid source address: ");
- writeIpAddr(dest);
- printf("\n");
- bf_afree(pack);
- return NULL;
- }
-
- /* Take the IP header and the first 64 bits of user data. */
- size= ntohs(ip_hdr->ih_length);
- if (size < ip_hdr_len || pack_len < size)
- {
- printf("icmp_err_pack: wrong packet size:\n");
- printf("\thdrlen= %d, ih_length= %d, bufsize= %d\n",
- ip_hdr_len, size, pack_len);
- bf_afree(pack);
- return NULL;
- }
- if (ip_hdr_len + 8 < size)
- size= ip_hdr_len+8;
- tmp_pack= bf_cut(pack, 0, size);
- bf_afree(pack);
- pack= tmp_pack;
- tmp_pack= NULL;
-
- /* Create a minimal size ICMP hdr. */
- icmp_hdr_len= offsetof(icmp_hdr_t, ih_dun);
- icmp_pack= bf_memreq(icmp_hdr_len);
- pack= bf_append(icmp_pack, pack);
- size += icmp_hdr_len;
- pack= bf_packIffLess(pack, icmp_hdr_len);
- icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(pack);
- icmp_hdr_p->ih_type= 0;
- icmp_hdr_p->ih_code= 0;
- icmp_hdr_p->ih_chksum= 0;
- icmp_hdr_p->ih_hun.ihh_unused= 0;
- icmp_hdr_p->ih_chksum= ~icmp_pack_oneCsum(pack);
- *icmp_hdr_pp= icmp_hdr_p;
-
- /* Create an IP header */
- ip_hdr_len= IP_MIN_HDR_SIZE;
-
- ip_pack= bf_memreq(ip_hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
-
- ip_hdr->ih_vers_ihl= ip_hdr_len >> 2;
- ip_hdr->ih_tos= 0;
- ip_hdr->ih_length= htons(ip_hdr_len + size);
- ip_hdr->ih_flags_fragoff= 0;
- ip_hdr->ih_ttl= ICMP_DEF_TTL;
- ip_hdr->ih_proto= IPPROTO_ICMP;
- ip_hdr->ih_dst= dest;
-
- assert(ip_pack->acc_next == NULL);
- ip_pack->acc_next= pack;
- return ip_pack;
-}
-
-/*
- * $PchId: icmp.c,v 1.23 2005/06/28 14:16:56 philip Exp $
- */
+++ /dev/null
-/*
-icmp.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef ICMP_H
-#define ICMP_H
-
-#define ICMP_MAX_DATAGRAM 8196
-#define ICMP_DEF_TTL 96
-
-/* Rate limit. The implementation is a bit sloppy and may send twice the
- * number of packets.
- */
-#define ICMP_MAX_RATE 100 /* This many per interval */
-#define ICMP_RATE_INTERVAL (1*HZ) /* Interval in ticks */
-#define ICMP_RATE_WARN 10 /* Report this many dropped packets */
-
-/* Prototypes */
-
-void icmp_prep ARGS(( void ));
-void icmp_init ARGS(( void ));
-
-
-#endif /* ICMP_H */
-
-/*
- * $PchId: icmp.h,v 1.7 2001/04/19 19:06:18 philip Exp $
- */
+++ /dev/null
-/*
-icmp_lib.h
-
-Created Sept 30, 1991 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef ICMP_LIB_H
-#define ICMP_LIB_H
-
-/* Prototypes */
-
-void icmp_snd_parmproblem ARGS(( acc_t *pack ));
-void icmp_snd_time_exceeded ARGS(( int port_nr, acc_t *pack, int code ));
-void icmp_snd_unreachable ARGS(( int port_nr, acc_t *pack, int code ));
-void icmp_snd_redirect ARGS(( int port_nr, acc_t *pack, int code,
- ipaddr_t gw ));
-void icmp_snd_mtu ARGS(( int port_nr, acc_t *pack, u16_t mtu ));
-
-#endif /* ICMP_LIB_H */
-
-/*
- * $PchId: icmp_lib.h,v 1.6 2002/06/08 21:32:44 philip Exp $
- */
+++ /dev/null
-/*
-io.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include <stdlib.h>
-
-#include "inet.h"
-#include "io.h"
-
-void writeIpAddr(addr)
-ipaddr_t addr;
-{
-#define addrInBytes ((u8_t *)&addr)
-
- printf("%d.%d.%d.%d", addrInBytes[0], addrInBytes[1],
- addrInBytes[2], addrInBytes[3]);
-#undef addrInBytes
-}
-
-void writeEtherAddr(addr)
-ether_addr_t *addr;
-{
-#define addrInBytes ((u8_t *)addr->ea_addr)
-
- printf("%x:%x:%x:%x:%x:%x", addrInBytes[0], addrInBytes[1],
- addrInBytes[2], addrInBytes[3], addrInBytes[4], addrInBytes[5]);
-#undef addrInBytes
-}
-
-/*
- * $PchId: io.c,v 1.6 1998/10/23 20:24:34 philip Exp $
- */
+++ /dev/null
-/*
-io.h
-
-Created Sept 30, 1991 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef IO_H
-#define IO_H
-
-/* Prototypes */
-
-void writeIpAddr ARGS(( ipaddr_t addr ));
-void writeEtherAddr ARGS(( ether_addr_t *addr ));
-
-#endif /* IO_H */
-
-/*
- * $PchId: io.h,v 1.4 1995/11/21 06:45:27 philip Exp $
- */
+++ /dev/null
-/*
-ip.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-
-#include "arp.h"
-#include "assert.h"
-#include "clock.h"
-#include "eth.h"
-#include "icmp.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "ipr.h"
-#include "sr.h"
-
-THIS_FILE
-
-static void ip_close ARGS(( int fd ));
-static int ip_cancel ARGS(( int fd, int which_operation ));
-static int ip_select ARGS(( int fd, unsigned operations ));
-
-static void ip_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void ip_bufcheck ARGS(( void ));
-#endif
-static void ip_bad_callback ARGS(( struct ip_port *ip_port ));
-
-ip_port_t *ip_port_table;
-ip_fd_t ip_fd_table[IP_FD_NR];
-ip_ass_t ip_ass_table[IP_ASS_NR];
-
-void ip_prep()
-{
- ip_port_table= alloc(ip_conf_nr * sizeof(ip_port_table[0]));
- icmp_prep();
-}
-
-void ip_init()
-{
- int i, j, result;
- ip_ass_t *ip_ass;
- ip_fd_t *ip_fd;
- ip_port_t *ip_port;
- struct ip_conf *icp;
-
- assert (BUF_S >= sizeof(struct nwio_ethopt));
- assert (BUF_S >= IP_MAX_HDR_SIZE + ETH_HDR_SIZE);
- assert (BUF_S >= sizeof(nwio_ipopt_t));
- assert (BUF_S >= sizeof(nwio_route_t));
-
- for (i=0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
- {
- ip_ass->ia_frags= 0;
- ip_ass->ia_first_time= 0;
- ip_ass->ia_port= 0;
- }
-
- for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- ip_fd->if_flags= IFF_EMPTY;
- ip_fd->if_rdbuf_head= 0;
- }
-
- for (i=0, ip_port= ip_port_table, icp= ip_conf;
- i<ip_conf_nr; i++, ip_port++, icp++)
- {
- ip_port->ip_port= i;
- ip_port->ip_flags= IPF_EMPTY;
- ip_port->ip_dev_main= (ip_dev_t)ip_bad_callback;
- ip_port->ip_dev_set_ipaddr= (ip_dev_t)ip_bad_callback;
- ip_port->ip_dev_send= (ip_dev_send_t)ip_bad_callback;
- ip_port->ip_dl_type= icp->ic_devtype;
- ip_port->ip_mtu= IP_DEF_MTU;
- ip_port->ip_mtu_max= IP_MAX_PACKSIZE;
- memset(&ip_port->ip_dl, 0, sizeof(ip_port->ip_dl));
-
- switch(ip_port->ip_dl_type)
- {
- case IPDL_ETH:
- ip_port->ip_dl.dl_eth.de_port= icp->ic_port;
- result= ipeth_init(ip_port);
- if (result == -1)
- continue;
- assert(result == NW_OK);
- break;
- case IPDL_PSIP:
- ip_port->ip_dl.dl_ps.ps_port= icp->ic_port;
- result= ipps_init(ip_port);
- if (result == -1)
- continue;
- assert(result == NW_OK);
- break;
- default:
- ip_panic(( "unknown ip_dl_type %d",
- ip_port->ip_dl_type ));
- break;
- }
- ip_port->ip_loopb_head= NULL;
- ip_port->ip_loopb_tail= NULL;
- ev_init(&ip_port->ip_loopb_event);
- ip_port->ip_routeq_head= NULL;
- ip_port->ip_routeq_tail= NULL;
- ev_init(&ip_port->ip_routeq_event);
- ip_port->ip_flags |= IPF_CONFIGURED;
- ip_port->ip_proto_any= NULL;
- for (j= 0; j<IP_PROTO_HASH_NR; j++)
- ip_port->ip_proto[j]= NULL;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(ip_buffree);
-#else
- bf_logon(ip_buffree, ip_bufcheck);
-#endif
-
- icmp_init();
- ipr_init();
-
- for (i=0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
- {
- if (!(ip_port->ip_flags & IPF_CONFIGURED))
- continue;
- ip_port->ip_frame_id= (u16_t)get_time();
-
- sr_add_minor(if2minor(ip_conf[i].ic_ifno, IP_DEV_OFF),
- i, ip_open, ip_close, ip_read,
- ip_write, ip_ioctl, ip_cancel, ip_select);
-
- (*ip_port->ip_dev_main)(ip_port);
- }
-}
-
-static int ip_cancel (fd, which_operation)
-int fd;
-int which_operation;
-{
- ip_fd_t *ip_fd;
- acc_t *repl_res;
- int result;
-
- ip_fd= &ip_fd_table[fd];
-
- switch (which_operation)
- {
- case SR_CANCEL_IOCTL:
- assert (ip_fd->if_flags & IFF_IOCTL_IP);
- ip_fd->if_flags &= ~IFF_IOCTL_IP;
- repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- (size_t)EINTR, (size_t)0, TRUE);
- assert (!repl_res);
- break;
- case SR_CANCEL_READ:
- assert (ip_fd->if_flags & IFF_READ_IP);
- ip_fd->if_flags &= ~IFF_READ_IP;
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- (size_t)EINTR, (acc_t *)0, FALSE);
- assert (!result);
- break;
-#if 0
- case SR_CANCEL_WRITE:
- assert(0);
- assert (ip_fd->if_flags & IFF_WRITE_MASK);
- ip_fd->if_flags &= ~IFF_WRITE_MASK;
- repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- (size_t)EINTR, (size_t)0, FALSE);
- assert (!repl_res);
- break;
-#endif
- default:
- ip_panic(( "unknown cancel request" ));
- break;
- }
- return NW_OK;
-}
-
-static int ip_select(fd, operations)
-int fd;
-unsigned operations;
-{
- unsigned resops;
- ip_fd_t *ip_fd;
-
- ip_fd= &ip_fd_table[fd];
- assert (ip_fd->if_flags & IFF_INUSE);
-
- resops= 0;
-
- if (operations & SR_SELECT_READ)
- {
- if (ip_sel_read(ip_fd))
- resops |= SR_SELECT_READ;
- else if (!(operations & SR_SELECT_POLL))
- ip_fd->if_flags |= IFF_SEL_READ;
- }
- if (operations & SR_SELECT_WRITE)
- {
- /* Should handle special case when the interface is down */
- resops |= SR_SELECT_WRITE;
- }
- if (operations & SR_SELECT_EXCEPTION)
- {
- /* Nothing */
- }
- return resops;
-}
-
-int ip_open (port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port;
-int srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- int i;
- ip_fd_t *ip_fd;
- ip_port_t *ip_port;
-
- ip_port= &ip_port_table[port];
- if (!(ip_port->ip_flags & IPF_CONFIGURED))
- return ENXIO;
-
- for (i=0; i<IP_FD_NR && (ip_fd_table[i].if_flags & IFF_INUSE);
- i++);
-
- if (i>=IP_FD_NR)
- {
- DBLOCK(1, printf("out of fds\n"));
- return EAGAIN;
- }
-
- ip_fd= &ip_fd_table[i];
-
- ip_fd->if_flags= IFF_INUSE;
-
- ip_fd->if_ipopt.nwio_flags= NWIO_DEFAULT;
- ip_fd->if_ipopt.nwio_tos= 0;
- ip_fd->if_ipopt.nwio_df= FALSE;
- ip_fd->if_ipopt.nwio_ttl= 255;
- ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz= 0;
-
- ip_fd->if_port= ip_port;
- ip_fd->if_srfd= srfd;
- assert(ip_fd->if_rdbuf_head == NULL);
- ip_fd->if_get_userdata= get_userdata;
- ip_fd->if_put_userdata= put_userdata;
- ip_fd->if_put_pkt= put_pkt;
- ip_fd->if_select_res= select_res;
-
- return i;
-}
-
-static void ip_close (fd)
-int fd;
-{
- ip_fd_t *ip_fd;
- acc_t *pack;
-
- ip_fd= &ip_fd_table[fd];
-
- assert ((ip_fd->if_flags & IFF_INUSE) &&
- !(ip_fd->if_flags & IFF_BUSY));
-
- if (ip_fd->if_flags & IFF_OPTSET)
- ip_unhash_proto(ip_fd);
- while (ip_fd->if_rdbuf_head)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- ip_fd->if_flags= IFF_EMPTY;
-}
-
-static void ip_buffree(priority)
-int priority;
-{
- int i;
- ip_port_t *ip_port;
- ip_fd_t *ip_fd;
- ip_ass_t *ip_ass;
- acc_t *pack, *next_pack;
-
- for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
- {
- if (ip_port->ip_dl_type == IPDL_ETH)
- {
- /* Can't free de_frame.
- * bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
- */
- if (priority == IP_PRI_PORTBUFS)
- {
- next_pack= ip_port->ip_dl.dl_eth.de_arp_head;
- while(next_pack != NULL)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- ip_port->ip_dl.dl_eth.de_arp_head= next_pack;
-
- next_pack= ip_port->ip_dl.dl_eth.de_q_head;
- while(next_pack != NULL)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- ip_port->ip_dl.dl_eth.de_q_head= next_pack;
- }
- }
- else if (ip_port->ip_dl_type == IPDL_PSIP)
- {
- if (priority == IP_PRI_PORTBUFS)
- {
- next_pack= ip_port->ip_dl.dl_ps.ps_send_head;
- while (next_pack != NULL)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- ip_port->ip_dl.dl_ps.ps_send_head= next_pack;
- }
- }
- if (priority == IP_PRI_PORTBUFS)
- {
- next_pack= ip_port->ip_loopb_head;
- while(next_pack && next_pack->acc_ext_link)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- if (next_pack)
- {
- if (ev_in_queue(&ip_port->ip_loopb_event))
- {
-#if DEBUG
- printf(
-"not freeing ip_loopb_head, ip_loopb_event enqueued\n");
-#endif
- }
- else
- {
- bf_afree(next_pack);
- next_pack= NULL;
- }
- }
- ip_port->ip_loopb_head= next_pack;
-
- next_pack= ip_port->ip_routeq_head;
- while(next_pack && next_pack->acc_ext_link)
- {
- pack= next_pack;
- next_pack= pack->acc_ext_link;
- bf_afree(pack);
- }
- if (next_pack)
- {
- if (ev_in_queue(&ip_port->ip_routeq_event))
- {
-#if DEBUG
- printf(
-"not freeing ip_loopb_head, ip_routeq_event enqueued\n");
-#endif
- }
- else
- {
- bf_afree(next_pack);
- next_pack= NULL;
- }
- }
- ip_port->ip_routeq_head= next_pack;
- }
- }
- if (priority == IP_PRI_FDBUFS_EXTRA)
- {
- for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- while (ip_fd->if_rdbuf_head &&
- ip_fd->if_rdbuf_head->acc_ext_link)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- }
- if (priority == IP_PRI_FDBUFS)
- {
- for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- while (ip_fd->if_rdbuf_head)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- }
- if (priority == IP_PRI_ASSBUFS)
- {
- for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
- {
- while(ip_ass->ia_frags != NULL)
- {
- pack= ip_ass->ia_frags;
- ip_ass->ia_frags= pack->acc_ext_link;
- bf_afree(pack);
- }
- ip_ass->ia_first_time= 0;
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void ip_bufcheck()
-{
- int i;
- ip_port_t *ip_port;
- ip_fd_t *ip_fd;
- ip_ass_t *ip_ass;
- acc_t *pack;
-
- for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
- {
- if (ip_port->ip_dl_type == IPDL_ETH)
- {
- bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
- for (pack= ip_port->ip_dl.dl_eth.de_q_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- for (pack= ip_port->ip_dl.dl_eth.de_arp_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
- else if (ip_port->ip_dl_type == IPDL_PSIP)
- {
- for (pack= ip_port->ip_dl.dl_ps.ps_send_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
- for (pack= ip_port->ip_loopb_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- for (pack= ip_port->ip_routeq_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
- for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- for (pack= ip_fd->if_rdbuf_head; pack;
- pack= pack->acc_ext_link)
- {
- bf_check_acc(pack);
- }
- }
- for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
- {
- for (pack= ip_ass->ia_frags; pack; pack= pack->acc_ext_link)
- bf_check_acc(pack);
- }
-}
-#endif /* BUF_CONSISTENCY_CHECK */
-
-__dead
-static void ip_bad_callback(ip_port)
-struct ip_port *ip_port;
-{
- ip_panic(( "no callback filled in for port %d", ip_port->ip_port ));
-}
-
-/*
- * $PchId: ip.c,v 1.19 2005/06/28 14:17:40 philip Exp $
- */
+++ /dev/null
-/*
-ip.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET_IP_H
-#define INET_IP_H
-
-/* Prototypes */
-
-struct acc;
-
-void ip_prep ARGS(( void ));
-void ip_init ARGS(( void ));
-int ip_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t select_res ));
-int ip_ioctl ARGS(( int fd, ioreq_t req ));
-int ip_read ARGS(( int fd, size_t count ));
-int ip_write ARGS(( int fd, size_t count ));
-int ip_send ARGS(( int fd, struct acc *data, size_t data_len ));
-
-#endif /* INET_IP_H */
-
-/*
- * $PchId: ip.h,v 1.8 2005/06/28 14:17:57 philip Exp $
- */
+++ /dev/null
-/*
-generic/ip_eth.c
-
-Ethernet specific part of the IP implementation
-
-Created: Apr 22, 1993 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "type.h"
-#include "arp.h"
-#include "assert.h"
-#include "buf.h"
-#include "clock.h"
-#include "eth.h"
-#include "event.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "ip_int.h"
-
-THIS_FILE
-
-typedef struct xmit_hdr
-{
- time_t xh_time;
- ipaddr_t xh_ipaddr;
-} xmit_hdr_t;
-
-static ether_addr_t broadcast_ethaddr=
-{
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
-};
-static ether_addr_t ipmulticast_ethaddr=
-{
- { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }
-};
-
-static void do_eth_read ARGS(( ip_port_t *port ));
-static acc_t *get_eth_data ARGS(( int fd, size_t offset,
- size_t count, int for_ioctl ));
-static int put_eth_data ARGS(( int fd, size_t offset,
- acc_t *data, int for_ioctl ));
-static void ipeth_main ARGS(( ip_port_t *port ));
-static void ipeth_set_ipaddr ARGS(( ip_port_t *port ));
-static void ipeth_restart_send ARGS(( ip_port_t *ip_port ));
-static int ipeth_send ARGS(( struct ip_port *ip_port, ipaddr_t dest,
- acc_t *pack, int type ));
-static void ipeth_arp_reply ARGS(( int ip_port_nr, ipaddr_t ipaddr,
- ether_addr_t *dst_ether_ptr ));
-static int ipeth_update_ttl ARGS(( time_t enq_time, time_t now,
- acc_t *eth_pack ));
-static void ip_eth_arrived ARGS(( int port, acc_t *pack,
- size_t pack_size ));
-
-
-int ipeth_init(ip_port)
-ip_port_t *ip_port;
-{
- assert(BUF_S >= sizeof(xmit_hdr_t));
- assert(BUF_S >= sizeof(eth_hdr_t));
-
- ip_port->ip_dl.dl_eth.de_fd= eth_open(ip_port->
- ip_dl.dl_eth.de_port, ip_port->ip_port,
- get_eth_data, put_eth_data, ip_eth_arrived,
- 0 /* no select_res */);
- if (ip_port->ip_dl.dl_eth.de_fd < 0)
- {
- DBLOCK(1, printf("ip.c: unable to open eth port\n"));
- return -1;
- }
- ip_port->ip_dl.dl_eth.de_state= IES_EMPTY;
- ip_port->ip_dl.dl_eth.de_flags= IEF_EMPTY;
- ip_port->ip_dl.dl_eth.de_q_head= NULL;
- ip_port->ip_dl.dl_eth.de_q_tail= NULL;
- ip_port->ip_dl.dl_eth.de_arp_head= NULL;
- ip_port->ip_dl.dl_eth.de_arp_tail= NULL;
- ip_port->ip_dev_main= ipeth_main;
- ip_port->ip_dev_set_ipaddr= ipeth_set_ipaddr;
- ip_port->ip_dev_send= ipeth_send;
- ip_port->ip_mtu= ETH_MAX_PACK_SIZE-ETH_HDR_SIZE;
- ip_port->ip_mtu_max= ip_port->ip_mtu;
- return 0;
-}
-
-static void ipeth_main(ip_port)
-ip_port_t *ip_port;
-{
- int result;
-
- switch (ip_port->ip_dl.dl_eth.de_state)
- {
- case IES_EMPTY:
- ip_port->ip_dl.dl_eth.de_state= IES_SETPROTO;
-
- result= eth_ioctl(ip_port->ip_dl.dl_eth.de_fd, NWIOSETHOPT);
- if (result == NW_SUSPEND)
- ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
- if (result<0)
- {
- DBLOCK(1, printf("eth_ioctl(..,0x%lx)=%d\n",
- (unsigned long)NWIOSETHOPT, result));
- return;
- }
- if (ip_port->ip_dl.dl_eth.de_state != IES_SETPROTO)
- return;
- /* drops through */
- case IES_SETPROTO:
- result= arp_set_cb(ip_port->ip_dl.dl_eth.de_port,
- ip_port->ip_port,
- ipeth_arp_reply);
- if (result != NW_OK)
- {
- printf("ipeth_main: arp_set_cb failed: %d\n",
- result);
- return;
- }
-
- /* Wait until the interface is configured up. */
- ip_port->ip_dl.dl_eth.de_state= IES_GETIPADDR;
- if (!(ip_port->ip_flags & IPF_IPADDRSET))
- {
- ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
- return;
- }
-
- /* fall through */
- case IES_GETIPADDR:
- ip_port->ip_dl.dl_eth.de_state= IES_MAIN;
- do_eth_read(ip_port);
- return;
- default:
- ip_panic(( "unknown state: %d",
- ip_port->ip_dl.dl_eth.de_state));
- }
-}
-
-static acc_t *get_eth_data (fd, offset, count, for_ioctl)
-int fd;
-size_t offset;
-size_t count;
-int for_ioctl;
-{
- ip_port_t *ip_port;
- acc_t *data;
- int result;
-
- ip_port= &ip_port_table[fd];
-
- switch (ip_port->ip_dl.dl_eth.de_state)
- {
- case IES_SETPROTO:
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- {
- ip_port->ip_dl.dl_eth.de_state= IES_ERROR;
- break;
- }
- if (ip_port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)
- ipeth_main(ip_port);
- return NW_OK;
- }
- assert ((!offset) && (count == sizeof(struct nwio_ethopt)));
- {
- struct nwio_ethopt *ethopt;
- acc_t *acc;
-
- acc= bf_memreq(sizeof(*ethopt));
- ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);
- ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|
- NWEO_EN_MULTI|NWEO_TYPESPEC;
- ethopt->nweo_type= HTONS(ETH_IP_PROTO);
- return acc;
- }
-
- case IES_MAIN:
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- ip_warning(( "error on write: %d\n", result ));
- bf_afree (ip_port->ip_dl.dl_eth.de_frame);
- ip_port->ip_dl.dl_eth.de_frame= 0;
-
- if (ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_SP)
- {
- ip_port->ip_dl.dl_eth.de_flags &=
- ~IEF_WRITE_SP;
- ipeth_restart_send(ip_port);
- }
- return NW_OK;
- }
- data= bf_cut (ip_port->ip_dl.dl_eth.de_frame, offset, count);
- assert (data);
- return data;
- default:
- printf(
- "get_eth_data(%d, 0x%d, 0x%d) called but ip_state=0x%x\n",
- fd, offset, count, ip_port->ip_dl.dl_eth.de_state);
- break;
- }
- return 0;
-}
-
-static int put_eth_data (port, offset, data, for_ioctl)
-int port;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- ip_port_t *ip_port;
- int result;
-
- ip_port= &ip_port_table[port];
-
- assert(0);
-
- if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP)
- {
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- DBLOCK(1, printf(
- "ip.c: put_eth_data(..,%d,..)\n", result));
- return NW_OK;
- }
- if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_SP)
- {
- ip_port->ip_dl.dl_eth.de_flags &=
- ~(IEF_READ_IP|IEF_READ_SP);
- do_eth_read(ip_port);
- }
- else
- ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
- return NW_OK;
- }
- assert (!offset);
- /* Warning: the above assertion is illegal; puts and
- gets of data can be brokenup in any piece the server
- likes. However we assume that the server is eth.c
- and it transfers only whole packets. */
- ip_eth_arrived(port, data, bf_bufsize(data));
- return NW_OK;
- }
- printf("ip_port->ip_dl.dl_eth.de_state= 0x%x",
- ip_port->ip_dl.dl_eth.de_state);
- ip_panic (( "strange status" ));
- return -1;
-}
-
-static void ipeth_set_ipaddr(ip_port)
-ip_port_t *ip_port;
-{
- arp_set_ipaddr (ip_port->ip_dl.dl_eth.de_port, ip_port->ip_ipaddr);
- if (ip_port->ip_dl.dl_eth.de_state == IES_GETIPADDR)
- ipeth_main(ip_port);
-}
-
-static int ipeth_send(ip_port, dest, pack, type)
-struct ip_port *ip_port;
-ipaddr_t dest;
-acc_t *pack;
-int type;
-{
- int i, r;
- acc_t *eth_pack, *tail;
- size_t pack_size;
- eth_hdr_t *eth_hdr;
- xmit_hdr_t *xmit_hdr;
- ipaddr_t tmpaddr;
- time_t t;
- u32_t *p;
-
- /* Start optimistic: the arp will succeed without blocking and the
- * ethernet packet can be sent without blocking also. Start with
- * the allocation of the ethernet header.
- */
- eth_pack= bf_memreq(sizeof(*eth_hdr));
- assert(eth_pack->acc_next == NULL);
- eth_pack->acc_next= pack;
- pack_size= bf_bufsize(eth_pack);
- if (pack_size<ETH_MIN_PACK_SIZE)
- {
- tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
-
- /* Clear padding */
- for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
- p= (u32_t *)ptr2acc_data(tail);
- i >= 0; i--, p++)
- {
- *p= 0xdeadbeef;
- }
-
- eth_pack= bf_append(eth_pack, tail);
- }
- eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
-
- /* Lookup the ethernet address */
- if (type != IP_LT_NORMAL)
- {
- if (type == IP_LT_BROADCAST)
- eth_hdr->eh_dst= broadcast_ethaddr;
- else
- {
- tmpaddr= ntohl(dest);
- eth_hdr->eh_dst= ipmulticast_ethaddr;
- eth_hdr->eh_dst.ea_addr[5]= tmpaddr & 0xff;
- eth_hdr->eh_dst.ea_addr[4]= (tmpaddr >> 8) & 0xff;
- eth_hdr->eh_dst.ea_addr[3]= (tmpaddr >> 16) & 0x7f;
- }
- }
- else
- {
- if ((dest ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)
- {
- ip_panic(( "invalid destination" ));
- }
-
- assert(dest != ip_port->ip_ipaddr);
-
- r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
- dest, ð_hdr->eh_dst);
- if (r == NW_SUSPEND)
- {
- /* Unfortunately, the arp takes some time, use
- * the ethernet header to store the next hop
- * ip address and the current time.
- */
- xmit_hdr= (xmit_hdr_t *)eth_hdr;
- xmit_hdr->xh_time= get_time();
- xmit_hdr->xh_ipaddr= dest;
- eth_pack->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_eth.de_arp_head == NULL)
- ip_port->ip_dl.dl_eth.de_arp_head= eth_pack;
- else
- {
- ip_port->ip_dl.dl_eth.de_arp_tail->
- acc_ext_link= eth_pack;
- }
- ip_port->ip_dl.dl_eth.de_arp_tail= eth_pack;
- return NW_OK;
- }
- if (r == EHOSTUNREACH)
- {
- bf_afree(eth_pack);
- return r;
- }
- assert(r == NW_OK);
- }
-
- /* If we have no write in progress, we can try to send the ethernet
- * packet using eth_send. If the IP packet is larger than mtu,
- * enqueue the packet and let ipeth_restart_send deal with it.
- */
- pack_size= bf_bufsize(eth_pack);
- if (ip_port->ip_dl.dl_eth.de_frame == NULL && pack_size <=
- ip_port->ip_mtu + sizeof(*eth_hdr))
- {
- r= eth_send(ip_port->ip_dl.dl_eth.de_fd,
- eth_pack, pack_size);
- if (r == NW_OK)
- return NW_OK;
-
- /* A non-blocking send is not possible, start a regular
- * send.
- */
- assert(r == NW_WOULDBLOCK);
- ip_port->ip_dl.dl_eth.de_frame= eth_pack;
- r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
- if (r == NW_SUSPEND)
- {
- assert(!(ip_port->ip_dl.dl_eth.de_flags &
- IEF_WRITE_SP));
- ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
- }
- assert(r == NW_OK || r == NW_SUSPEND);
- return NW_OK;
- }
-
- /* Enqueue the packet, and store the current time, in the
- * space for the ethernet source address.
- */
- t= get_time();
- assert(sizeof(t) <= sizeof(eth_hdr->eh_src));
- memcpy(ð_hdr->eh_src, &t, sizeof(t));
-
- eth_pack->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
- ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
- else
- {
- ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= eth_pack;
- }
- ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
- if (ip_port->ip_dl.dl_eth.de_frame == NULL)
- ipeth_restart_send(ip_port);
- return NW_OK;
-}
-
-static void ipeth_restart_send(ip_port)
-ip_port_t *ip_port;
-{
- time_t now, enq_time;
- int i, r;
- acc_t *eth_pack, *ip_pack, *next_eth_pack, *next_part, *tail;
- size_t pack_size;
- eth_hdr_t *eth_hdr, *next_eth_hdr;
- u32_t *p;
-
- now= get_time();
-
- while (ip_port->ip_dl.dl_eth.de_q_head != NULL)
- {
- eth_pack= ip_port->ip_dl.dl_eth.de_q_head;
- ip_port->ip_dl.dl_eth.de_q_head= eth_pack->acc_ext_link;
-
- eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
-
- pack_size= bf_bufsize(eth_pack);
-
- if (pack_size > ip_port->ip_mtu+sizeof(*eth_hdr))
- {
- /* Split the IP packet */
- assert(eth_pack->acc_linkC == 1);
- ip_pack= eth_pack->acc_next; eth_pack->acc_next= NULL;
- next_part= ip_pack; ip_pack= NULL;
- ip_pack= ip_split_pack(ip_port, &next_part,
- ip_port->ip_mtu);
- if (ip_pack == NULL)
- {
- bf_afree(eth_pack);
- continue;
- }
-
- eth_pack->acc_next= ip_pack; ip_pack= NULL;
-
- /* Allocate new ethernet header */
- next_eth_pack= bf_memreq(sizeof(*next_eth_hdr));
- next_eth_hdr= (eth_hdr_t *)ptr2acc_data(next_eth_pack);
- *next_eth_hdr= *eth_hdr;
- next_eth_pack->acc_next= next_part;
-
- next_eth_pack->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
- ip_port->ip_dl.dl_eth.de_q_head= next_eth_pack;
- else
- {
- ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
- next_eth_pack;
- }
- ip_port->ip_dl.dl_eth.de_q_tail= next_eth_pack;
-
- pack_size= bf_bufsize(eth_pack);
- }
-
- memcpy(&enq_time, ð_hdr->eh_src, sizeof(enq_time));
- if (enq_time + HZ < now)
- {
- r= ipeth_update_ttl(enq_time, now, eth_pack);
- if (r == ETIMEDOUT)
- {
- ip_pack= bf_delhead(eth_pack, sizeof(*eth_hdr));
- eth_pack= NULL;
- icmp_snd_time_exceeded(ip_port->ip_port,
- ip_pack, ICMP_TTL_EXC);
- continue;
- }
- assert(r == NW_OK);
- }
-
- if (pack_size<ETH_MIN_PACK_SIZE)
- {
- tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
-
- /* Clear padding */
- for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
- p= (u32_t *)ptr2acc_data(tail);
- i >= 0; i--, p++)
- {
- *p= 0xdeadbeef;
- }
-
- eth_pack= bf_append(eth_pack, tail);
- pack_size= ETH_MIN_PACK_SIZE;
- }
-
- assert(ip_port->ip_dl.dl_eth.de_frame == NULL);
-
- r= eth_send(ip_port->ip_dl.dl_eth.de_fd, eth_pack, pack_size);
- if (r == NW_OK)
- continue;
-
- /* A non-blocking send is not possible, start a regular
- * send.
- */
- assert(r == NW_WOULDBLOCK);
- ip_port->ip_dl.dl_eth.de_frame= eth_pack;
- r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
- if (r == NW_SUSPEND)
- {
- assert(!(ip_port->ip_dl.dl_eth.de_flags &
- IEF_WRITE_SP));
- ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
- return;
- }
- assert(r == NW_OK);
- }
-}
-
-
-static void ipeth_arp_reply(ip_port_nr, ipaddr, eth_addr)
-int ip_port_nr;
-ipaddr_t ipaddr;
-ether_addr_t *eth_addr;
-{
- acc_t *prev, *eth_pack;
- int r;
- xmit_hdr_t *xmit_hdr;
- ip_port_t *ip_port;
- time_t t;
- eth_hdr_t *eth_hdr;
- ether_addr_t tmp_eth_addr;
-
- assert (ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
- ip_port= &ip_port_table[ip_port_nr];
-
- for (;;)
- {
- for (prev= 0, eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
- eth_pack;
- prev= eth_pack, eth_pack= eth_pack->acc_ext_link)
- {
- xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
- if (xmit_hdr->xh_ipaddr == ipaddr)
- break;
- }
-
- if (eth_pack == NULL)
- {
- /* No packet found. */
- break;
- }
-
- /* Delete packet from the queue. */
- if (prev == NULL)
- {
- ip_port->ip_dl.dl_eth.de_arp_head=
- eth_pack->acc_ext_link;
- }
- else
- {
- prev->acc_ext_link= eth_pack->acc_ext_link;
- if (prev->acc_ext_link == NULL)
- ip_port->ip_dl.dl_eth.de_arp_tail= prev;
- }
-
- if (eth_addr == NULL)
- {
- /* Destination is unreachable, delete packet. */
- bf_afree(eth_pack);
- continue;
- }
-
- /* Fill in the ethernet address and put the packet on the
- * transmit queue.
- */
- t= xmit_hdr->xh_time;
- eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
- eth_hdr->eh_dst= *eth_addr;
- memcpy(ð_hdr->eh_src, &t, sizeof(t));
-
- eth_pack->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
- ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
- else
- {
- ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
- eth_pack;
- }
- ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
- }
-
- /* Try to get some more ARPs in progress. */
- while (ip_port->ip_dl.dl_eth.de_arp_head)
- {
- eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
- xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
- r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
- xmit_hdr->xh_ipaddr, &tmp_eth_addr);
- if (r == NW_SUSPEND)
- break; /* Normal case */
-
- /* Dequeue the packet */
- ip_port->ip_dl.dl_eth.de_arp_head= eth_pack->acc_ext_link;
-
- if (r == EHOSTUNREACH)
- {
- bf_afree(eth_pack);
- continue;
- }
- assert(r == NW_OK);
-
- /* Fill in the ethernet address and put the packet on the
- * transmit queue.
- */
- t= xmit_hdr->xh_time;
- eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
- eth_hdr->eh_dst= tmp_eth_addr;
- memcpy(ð_hdr->eh_src, &t, sizeof(t));
-
- eth_pack->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
- ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
- else
- {
- ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
- eth_pack;
- }
- ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
- }
-
- /* Restart sending ethernet packets. */
- if (ip_port->ip_dl.dl_eth.de_frame == NULL)
- ipeth_restart_send(ip_port);
-}
-
-static int ipeth_update_ttl(enq_time, now, eth_pack)
-time_t enq_time;
-time_t now;
-acc_t *eth_pack;
-{
- int ttl_diff;
- ip_hdr_t *ip_hdr;
- u32_t sum;
- u16_t word;
- acc_t *ip_pack;
-
- ttl_diff= (now-enq_time)/HZ;
- enq_time += ttl_diff*HZ;
- assert(enq_time <= now && enq_time + HZ > now);
-
- ip_pack= eth_pack->acc_next;
- assert(ip_pack->acc_length >= sizeof(*ip_hdr));
- assert(ip_pack->acc_linkC == 1 &&
- ip_pack->acc_buffer->buf_linkC == 1);
-
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
- if (ip_hdr->ih_ttl <= ttl_diff)
- return ETIMEDOUT;
- sum= (u16_t)~ip_hdr->ih_hdr_chk;
- word= *(u16_t *)&ip_hdr->ih_ttl;
- if (word > sum)
- sum += 0xffff - word;
- else
- sum -= word;
- ip_hdr->ih_ttl -= ttl_diff;
- word= *(u16_t *)&ip_hdr->ih_ttl;
- sum += word;
- if (sum > 0xffff)
- sum -= 0xffff;
- assert(!(sum & 0xffff0000));
- ip_hdr->ih_hdr_chk= ~sum;
- assert(ip_hdr->ih_ttl > 0);
- return NW_OK;
-}
-
-static void do_eth_read(ip_port)
-ip_port_t *ip_port;
-{
- int result;
-
- assert(!(ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP));
-
- for (;;)
- {
- ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_IP;
-
- result= eth_read (ip_port->ip_dl.dl_eth.de_fd,
- ETH_MAX_PACK_SIZE);
- if (result == NW_SUSPEND)
- {
- assert(!(ip_port->ip_dl.dl_eth.de_flags &
- IEF_READ_SP));
- ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_SP;
- return;
- }
- ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
- if (result<0)
- {
- return;
- }
- }
-}
-
-static void ip_eth_arrived(port, pack, pack_size)
-int port;
-acc_t *pack;
-size_t pack_size;
-{
- int broadcast;
- ip_port_t *ip_port;
-
- ip_port= &ip_port_table[port];
- broadcast= (*(u8_t *)ptr2acc_data(pack) & 1);
-
- pack= bf_delhead(pack, ETH_HDR_SIZE);
-
- if (broadcast)
- ip_arrived_broadcast(ip_port, pack);
- else
- ip_arrived(ip_port, pack);
-}
-
-/*
- * $PchId: ip_eth.c,v 1.25 2005/06/28 14:18:10 philip Exp $
- */
+++ /dev/null
-/*
-ip_int.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET_IP_INT_H
-#define INET_IP_INT_H
-
-#define IP_FD_NR (8*IP_PORT_MAX)
-#define IP_ASS_NR 3
-
-#define IP_42BSD_BCAST 1 /* hostnumber 0 is also network
- broadcast */
-
-#define IP_LT_NORMAL 0 /* Normal */
-#define IP_LT_BROADCAST 1 /* Broadcast */
-#define IP_LT_MULTICAST 2 /* Multicast */
-
-struct ip_port;
-struct ip_fd;
-typedef void (*ip_dev_t) ARGS(( struct ip_port *ip_port ));
-typedef int (*ip_dev_send_t) ARGS(( struct ip_port *ip_port, ipaddr_t dest,
- acc_t *pack, int type ));
-
-#define IP_PROTO_HASH_NR 32
-
-typedef struct ip_port
-{
- int ip_flags, ip_dl_type;
- int ip_port;
- union sxfer_ip_dl_u
- {
- struct
- {
- int de_state;
- int de_flags;
- int de_port;
- int de_fd;
- acc_t *de_frame;
- acc_t *de_q_head;
- acc_t *de_q_tail;
- acc_t *de_arp_head;
- acc_t *de_arp_tail;
- } dl_eth;
- struct
- {
- int dummy_int[3];
- int ps_port;
- acc_t *ps_send_head;
- acc_t *ps_send_tail;
- void* dummy_ptr[3];
- } dl_ps;
- } ip_dl;
- ipaddr_t ip_ipaddr;
- ipaddr_t ip_subnetmask;
- ipaddr_t ip_classfulmask;
- u16_t ip_frame_id;
- u16_t ip_mtu;
- u16_t ip_mtu_max; /* Max MTU for this kind of network */
- ip_dev_t ip_dev_main;
- ip_dev_t ip_dev_set_ipaddr;
- ip_dev_send_t ip_dev_send;
- acc_t *ip_loopb_head;
- acc_t *ip_loopb_tail;
- event_t ip_loopb_event;
- acc_t *ip_routeq_head;
- acc_t *ip_routeq_tail;
- event_t ip_routeq_event;
- struct ip_fd *ip_proto_any;
- struct ip_fd *ip_proto[IP_PROTO_HASH_NR];
-} ip_port_t;
-
-#define IES_EMPTY 0x0
-#define IES_SETPROTO 0x1
-#define IES_GETIPADDR 0x2
-#define IES_MAIN 0x3
-#define IES_ERROR 0x4
-
-#define IEF_EMPTY 0x1
-#define IEF_SUSPEND 0x8
-#define IEF_READ_IP 0x10
-#define IEF_READ_SP 0x20
-#define IEF_WRITE_SP 0x80
-
-#define IPF_EMPTY 0x0
-#define IPF_CONFIGURED 0x1
-#define IPF_IPADDRSET 0x2
-#define IPF_NETMASKSET 0x4
-#define IPF_SUBNET_BCAST 0x8 /* Subset support subnet broadcasts */
-
-#define IPDL_ETH NETTYPE_ETH
-#define IPDL_PSIP NETTYPE_PSIP
-
-typedef struct ip_ass
-{
- acc_t *ia_frags;
- int ia_min_ttl;
- ip_port_t *ia_port;
- time_t ia_first_time;
- ipaddr_t ia_srcaddr, ia_dstaddr;
- int ia_proto, ia_id;
-} ip_ass_t;
-
-typedef struct ip_fd
-{
- int if_flags;
- struct nwio_ipopt if_ipopt;
- ip_port_t *if_port;
- struct ip_fd *if_proto_next;
- int if_srfd;
- acc_t *if_rdbuf_head;
- acc_t *if_rdbuf_tail;
- get_userdata_t if_get_userdata;
- put_userdata_t if_put_userdata;
- put_pkt_t if_put_pkt;
- select_res_t if_select_res;
- time_t if_exp_time;
- size_t if_rd_count;
- ioreq_t if_ioctl;
-} ip_fd_t;
-
-#define IFF_EMPTY 0x00
-#define IFF_INUSE 0x01
-#define IFF_OPTSET 0x02
-#define IFF_BUSY 0x0C
-# define IFF_READ_IP 0x04
-# define IFF_IOCTL_IP 0x08
-#define IFF_SEL_READ 0x10
-
-typedef enum nettype
-{
- IPNT_ZERO, /* 0.xx.xx.xx */
- IPNT_CLASS_A, /* 1.xx.xx.xx .. 126.xx.xx.xx */
- IPNT_LOCAL, /* 127.xx.xx.xx */
- IPNT_CLASS_B, /* 128.xx.xx.xx .. 191.xx.xx.xx */
- IPNT_CLASS_C, /* 192.xx.xx.xx .. 223.xx.xx.xx */
- IPNT_CLASS_D, /* 224.xx.xx.xx .. 239.xx.xx.xx */
- IPNT_CLASS_E, /* 240.xx.xx.xx .. 247.xx.xx.xx */
- IPNT_MARTIAN, /* 248.xx.xx.xx .. 254.xx.xx.xx + others */
- IPNT_BROADCAST /* 255.255.255.255 */
-} nettype_t;
-
-struct nwio_ipconf;
-
-/* ip_eth.c */
-int ipeth_init ARGS(( ip_port_t *ip_port ));
-
-/* ip_ioctl.c */
-void ip_hash_proto ARGS(( ip_fd_t *ip_fd ));
-void ip_unhash_proto ARGS(( ip_fd_t *ip_fd ));
-int ip_setconf ARGS(( int ip_port, struct nwio_ipconf *ipconfp ));
-
-/* ip_lib.c */
-ipaddr_t ip_get_netmask ARGS(( ipaddr_t hostaddr ));
-ipaddr_t ip_get_ifaddr ARGS(( int ip_port_nr ));
-int ip_chk_hdropt ARGS(( u8_t *opt, int optlen ));
-void ip_print_frags ARGS(( acc_t *acc ));
-nettype_t ip_nettype ARGS(( ipaddr_t ipaddr ));
-ipaddr_t ip_netmask ARGS(( nettype_t nettype ));
-char *ip_nettoa ARGS(( nettype_t nettype ));
-
-/* ip_ps.c */
-int ipps_init ARGS(( ip_port_t *ip_port ));
-void ipps_get ARGS(( int ip_port_nr ));
-void ipps_put ARGS(( int ip_port_nr, ipaddr_t nexthop, acc_t *pack ));
-
-/* ip_read.c */
-void ip_port_arrive ARGS(( ip_port_t *port, acc_t *pack, ip_hdr_t *ip_hdr ));
-void ip_arrived ARGS(( ip_port_t *port, acc_t *pack ));
-void ip_arrived_broadcast ARGS(( ip_port_t *port, acc_t *pack ));
-void ip_process_loopb ARGS(( event_t *ev, ev_arg_t arg ));
-int ip_sel_read ARGS(( ip_fd_t *ip_fd ));
-void ip_packet2user ARGS(( ip_fd_t *ip_fd, acc_t *pack, time_t exp_time,
- size_t data_len ));
-
-/* ip_write.c */
-void dll_eth_write_frame ARGS(( ip_port_t *port ));
-acc_t *ip_split_pack ARGS(( ip_port_t *ip_port, acc_t **ref_last, int mtu ));
-void ip_hdr_chksum ARGS(( ip_hdr_t *ip_hdr, int ip_hdr_len ));
-
-
-extern ip_fd_t ip_fd_table[IP_FD_NR];
-extern ip_port_t *ip_port_table;
-extern ip_ass_t ip_ass_table[IP_ASS_NR];
-
-#define NWIO_DEFAULT (NWIO_EN_LOC | NWIO_EN_BROAD | NWIO_REMANY | \
- NWIO_RWDATALL | NWIO_HDR_O_SPEC)
-
-#endif /* INET_IP_INT_H */
-
-/*
- * $PchId: ip_int.h,v 1.19 2004/08/03 16:24:23 philip Exp $
- */
+++ /dev/null
-/*
-ip_ioctl.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-
-#include "arp.h"
-#include "assert.h"
-#include "clock.h"
-#include "icmp_lib.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "ipr.h"
-
-THIS_FILE
-
-static int ip_checkopt ARGS(( ip_fd_t *ip_fd ));
-static void reply_thr_get ARGS(( ip_fd_t *ip_fd, size_t
- reply, int for_ioctl ));
-static void report_addr ARGS(( ip_port_t *ip_port ));
-
-int ip_ioctl (fd, req)
-int fd;
-ioreq_t req;
-{
- ip_fd_t *ip_fd;
- ip_port_t *ip_port;
- nwio_ipopt_t *ipopt;
- nwio_ipopt_t oldopt, newopt;
- nwio_ipconf2_t *ipconf2;
- nwio_ipconf_t *ipconf;
- nwio_route_t *route_ent;
- acc_t *data;
- int result;
- unsigned int new_en_flags, new_di_flags,
- old_en_flags, old_di_flags;
- unsigned long new_flags;
- int ent_no, r;
- nwio_ipconf_t ipconf_var;
-
- assert (fd>=0 && fd<IP_FD_NR);
- ip_fd= &ip_fd_table[fd];
-
- assert (ip_fd->if_flags & IFF_INUSE);
-
- switch (req)
- {
- case NWIOSIPOPT:
- ip_port= ip_fd->if_port;
-
- if (!(ip_port->ip_flags & IPF_IPADDRSET))
- {
- ip_fd->if_ioctl= NWIOSIPOPT;
- ip_fd->if_flags |= IFF_IOCTL_IP;
- return NW_SUSPEND;
- }
- ip_fd->if_flags &= ~IFF_IOCTL_IP;
-
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0,
- sizeof(nwio_ipopt_t), TRUE);
-
- data= bf_packIffLess (data, sizeof(nwio_ipopt_t));
- assert (data->acc_length == sizeof(nwio_ipopt_t));
-
- ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
- oldopt= ip_fd->if_ipopt;
- newopt= *ipopt;
-
- old_en_flags= oldopt.nwio_flags & 0xffff;
- old_di_flags= (oldopt.nwio_flags >> 16) & 0xffff;
- new_en_flags= newopt.nwio_flags & 0xffff;
- new_di_flags= (newopt.nwio_flags >> 16) & 0xffff;
- if (new_en_flags & new_di_flags)
- {
- bf_afree(data);
- reply_thr_get (ip_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- /* NWIO_ACC_MASK */
- if (new_di_flags & NWIO_ACC_MASK)
- {
- bf_afree(data);
- reply_thr_get (ip_fd, EBADMODE, TRUE);
- return NW_OK;
- /* access modes can't be disable */
- }
-
- if (!(new_en_flags & NWIO_ACC_MASK))
- new_en_flags |= (old_en_flags & NWIO_ACC_MASK);
-
- /* NWIO_LOC_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_LOC_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_LOC_MASK);
- new_di_flags |= (old_di_flags & NWIO_LOC_MASK);
- }
-
- /* NWIO_BROAD_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_BROAD_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_BROAD_MASK);
- new_di_flags |= (old_di_flags & NWIO_BROAD_MASK);
- }
-
- /* NWIO_REM_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_REM_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_REM_MASK);
- new_di_flags |= (old_di_flags & NWIO_REM_MASK);
- newopt.nwio_rem= oldopt.nwio_rem;
- }
-
- /* NWIO_PROTO_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_PROTO_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_PROTO_MASK);
- new_di_flags |= (old_di_flags & NWIO_PROTO_MASK);
- newopt.nwio_proto= oldopt.nwio_proto;
- }
-
- /* NWIO_HDR_O_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_HDR_O_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_HDR_O_MASK);
- new_di_flags |= (old_di_flags & NWIO_HDR_O_MASK);
- newopt.nwio_tos= oldopt.nwio_tos;
- newopt.nwio_ttl= oldopt.nwio_ttl;
- newopt.nwio_df= oldopt.nwio_df;
- newopt.nwio_hdropt= oldopt.nwio_hdropt;
- }
-
- /* NWIO_RW_MASK */
- if (!((new_en_flags|new_di_flags) & NWIO_RW_MASK))
- {
- new_en_flags |= (old_en_flags & NWIO_RW_MASK);
- new_di_flags |= (old_di_flags & NWIO_RW_MASK);
- }
-
- new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
-
- if ((new_flags & NWIO_RWDATONLY) && (new_flags &
- (NWIO_REMANY|NWIO_PROTOANY|NWIO_HDR_O_ANY)))
- {
- bf_afree(data);
- reply_thr_get(ip_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- if (ip_fd->if_flags & IFF_OPTSET)
- ip_unhash_proto(ip_fd);
-
- newopt.nwio_flags= new_flags;
- ip_fd->if_ipopt= newopt;
-
- result= ip_checkopt(ip_fd);
-
- if (result<0)
- ip_fd->if_ipopt= oldopt;
-
- bf_afree(data);
- reply_thr_get (ip_fd, result, TRUE);
- return NW_OK;
-
- case NWIOGIPOPT:
- data= bf_memreq(sizeof(nwio_ipopt_t));
-
- ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
-
- *ipopt= ip_fd->if_ipopt;
-
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data,
- TRUE);
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
- (acc_t *)0, TRUE);
-
- case NWIOSIPCONF2:
- case NWIOSIPCONF:
- ip_port= ip_fd->if_port;
-
- if (req == NWIOSIPCONF2)
- {
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0,
- sizeof(*ipconf2), TRUE);
- data= bf_packIffLess (data, sizeof(*ipconf2));
- assert (data->acc_length == sizeof(*ipconf2));
-
- ipconf2= (nwio_ipconf2_t *)ptr2acc_data(data);
-
- ipconf= &ipconf_var;
- ipconf->nwic_flags= ipconf2->nwic_flags;
- ipconf->nwic_ipaddr= ipconf2->nwic_ipaddr;
- ipconf->nwic_netmask= ipconf2->nwic_netmask;
- ipconf->nwic_flags &= ~NWIC_MTU_SET;
- }
- else
- {
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0,
- sizeof(*ipconf), TRUE);
- data= bf_packIffLess (data, sizeof(*ipconf));
- assert (data->acc_length == sizeof(*ipconf));
-
- ipconf= (nwio_ipconf_t *)ptr2acc_data(data);
- }
- r= ip_setconf(ip_port-ip_port_table, ipconf);
- bf_afree(data);
- return (*ip_fd->if_put_userdata)(ip_fd-> if_srfd, r,
- (acc_t *)0, TRUE);
-
- case NWIOGIPCONF2:
- ip_port= ip_fd->if_port;
-
- if (!(ip_port->ip_flags & IPF_IPADDRSET))
- {
- ip_fd->if_ioctl= NWIOGIPCONF2;
- ip_fd->if_flags |= IFF_IOCTL_IP;
- return NW_SUSPEND;
- }
- ip_fd->if_flags &= ~IFF_IOCTL_IP;
- data= bf_memreq(sizeof(nwio_ipconf_t));
- ipconf2= (nwio_ipconf2_t *)ptr2acc_data(data);
- ipconf2->nwic_flags= NWIC_IPADDR_SET;
- ipconf2->nwic_ipaddr= ip_port->ip_ipaddr;
- ipconf2->nwic_netmask= ip_port->ip_subnetmask;
- if (ip_port->ip_flags & IPF_NETMASKSET)
- ipconf2->nwic_flags |= NWIC_NETMASK_SET;
-
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data,
- TRUE);
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
- (acc_t *)0, TRUE);
-
- case NWIOGIPCONF:
- ip_port= ip_fd->if_port;
-
- if (!(ip_port->ip_flags & IPF_IPADDRSET))
- {
- ip_fd->if_ioctl= NWIOGIPCONF;
- ip_fd->if_flags |= IFF_IOCTL_IP;
- return NW_SUSPEND;
- }
- ip_fd->if_flags &= ~IFF_IOCTL_IP;
- data= bf_memreq(sizeof(*ipconf));
- ipconf= (nwio_ipconf_t *)ptr2acc_data(data);
- ipconf->nwic_flags= NWIC_IPADDR_SET;
- ipconf->nwic_ipaddr= ip_port->ip_ipaddr;
- ipconf->nwic_netmask= ip_port->ip_subnetmask;
- if (ip_port->ip_flags & IPF_NETMASKSET)
- ipconf->nwic_flags |= NWIC_NETMASK_SET;
- ipconf->nwic_mtu= ip_port->ip_mtu;
-
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data,
- TRUE);
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
- (acc_t *)0, TRUE);
-
- case NWIOGIPOROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- ent_no= route_ent->nwr_ent_no;
- bf_afree(data);
-
- data= bf_memreq(sizeof(nwio_route_t));
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_get_oroute(ent_no, route_ent);
- if (result < 0)
- bf_afree(data);
- else
- {
- assert(result == NW_OK);
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0,
- data, TRUE);
- }
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- case NWIOSIPOROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
- if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
- {
- /* Interface is down, no changes allowed */
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- ENETDOWN, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_add_oroute(ip_fd->if_port-ip_port_table,
- route_ent->nwr_dest, route_ent->nwr_netmask,
- route_ent->nwr_gateway, (time_t)0,
- route_ent->nwr_dist, route_ent->nwr_mtu,
- !!(route_ent->nwr_flags & NWRF_STATIC),
- route_ent->nwr_pref, NULL);
- bf_afree(data);
-
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- case NWIODIPOROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_del_oroute(ip_fd->if_port-ip_port_table,
- route_ent->nwr_dest, route_ent->nwr_netmask,
- route_ent->nwr_gateway,
- !!(route_ent->nwr_flags & NWRF_STATIC));
- bf_afree(data);
-
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- case NWIOGIPIROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- ent_no= route_ent->nwr_ent_no;
- bf_afree(data);
-
- data= bf_memreq(sizeof(nwio_route_t));
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_get_iroute(ent_no, route_ent);
- if (result < 0)
- bf_afree(data);
- else
- {
- assert(result == NW_OK);
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0,
- data, TRUE);
- }
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- case NWIOSIPIROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
- if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
- {
- /* Interface is down, no changes allowed */
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- ENETDOWN, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_add_iroute(ip_fd->if_port-ip_port_table,
- route_ent->nwr_dest, route_ent->nwr_netmask,
- route_ent->nwr_gateway,
- (route_ent->nwr_flags & NWRF_UNREACHABLE) ?
- IRTD_UNREACHABLE : route_ent->nwr_dist,
- route_ent->nwr_mtu,
- !!(route_ent->nwr_flags & NWRF_STATIC), NULL);
- bf_afree(data);
-
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- case NWIODIPIROUTE:
- data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
- 0, sizeof(nwio_route_t), TRUE);
- if (data == NULL)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- EFAULT, NULL, TRUE);
- }
-
- data= bf_packIffLess (data, sizeof(nwio_route_t) );
- route_ent= (nwio_route_t *)ptr2acc_data(data);
- result= ipr_del_iroute(ip_fd->if_port-ip_port_table,
- route_ent->nwr_dest, route_ent->nwr_netmask,
- route_ent->nwr_gateway,
- !!(route_ent->nwr_flags & NWRF_STATIC));
- bf_afree(data);
-
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- result, (acc_t *)0, TRUE);
-
- /* The following ARP ioctls are only valid if the
- * underlying device is an ethernet.
- */
- case NWIOARPGIP:
- case NWIOARPGNEXT:
- case NWIOARPSIP:
- case NWIOARPDIP:
- ip_port= ip_fd->if_port;
-
- if (ip_port->ip_dl_type != IPDL_ETH)
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- ENOTTY, (acc_t *)0, TRUE);
- }
-
- if (!(ip_port->ip_flags & IPF_IPADDRSET))
- {
- ip_fd->if_ioctl= req;
- ip_fd->if_flags |= IFF_IOCTL_IP;
- printf("ip_ioctl: suspending ARP request\n");
- return NW_SUSPEND;
- }
-
- result= arp_ioctl(ip_port->ip_dl.dl_eth.de_port,
- ip_fd->if_srfd, req, ip_fd->if_get_userdata,
- ip_fd->if_put_userdata);
- assert (result != SUSPEND);
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
- (acc_t *)0, TRUE);
-
- default:
- break;
- }
- DBLOCK(1, printf("replying ENOTTY: 0x%lx\n", req));
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, ENOTTY,
- (acc_t *)0, TRUE);
-}
-
-void ip_hash_proto(ip_fd)
-ip_fd_t *ip_fd;
-{
- ip_port_t *ip_port;
- int hash;
-
- ip_port= ip_fd->if_port;
- if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOANY)
- {
- ip_fd->if_proto_next= ip_port->ip_proto_any;
- ip_port->ip_proto_any= ip_fd;
- }
- else
- {
- hash= ip_fd->if_ipopt.nwio_proto & (IP_PROTO_HASH_NR-1);
- ip_fd->if_proto_next= ip_port->ip_proto[hash];
- ip_port->ip_proto[hash]= ip_fd;
- }
-}
-
-void ip_unhash_proto(ip_fd)
-ip_fd_t *ip_fd;
-{
- ip_port_t *ip_port;
- ip_fd_t *prev, *curr, **ip_fd_p;
- int hash;
-
- ip_port= ip_fd->if_port;
- if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOANY)
- {
- ip_fd_p= &ip_port->ip_proto_any;
- }
- else
- {
- hash= ip_fd->if_ipopt.nwio_proto & (IP_PROTO_HASH_NR-1);
- ip_fd_p= &ip_port->ip_proto[hash];
- }
- for (prev= NULL, curr= *ip_fd_p; curr;
- prev= curr, curr= curr->if_proto_next)
- {
- if (curr == ip_fd)
- break;
- }
- assert(curr);
- if (prev)
- prev->if_proto_next= curr->if_proto_next;
- else
- *ip_fd_p= curr->if_proto_next;
-}
-
-int ip_setconf(ip_port_nr, ipconf)
-int ip_port_nr;
-nwio_ipconf_t *ipconf;
-{
- int i, do_report;
- ip_port_t *ip_port;
- ip_fd_t *ip_fd;
- ipaddr_t ipaddr;
- u32_t mtu;
-
- ip_port= &ip_port_table[ip_port_nr];
-
- if (ipconf->nwic_flags & ~NWIC_FLAGS)
- return EBADMODE;
-
- do_report= 0;
- if (ipconf->nwic_flags & NWIC_MTU_SET)
- {
- mtu= ipconf->nwic_mtu;
- if (mtu < IP_MIN_MTU || mtu > ip_port->ip_mtu_max)
- return EINVAL;
- ip_port->ip_mtu= mtu;
- do_report= 1;
- }
-
- if (ipconf->nwic_flags & NWIC_NETMASK_SET)
- {
- ip_port->ip_subnetmask= ipconf->nwic_netmask;
- ip_port->ip_flags |= IPF_NETMASKSET|IPF_SUBNET_BCAST;
- if (ntohl(ip_port->ip_subnetmask) >= 0xfffffffe)
- ip_port->ip_flags &= ~IPF_SUBNET_BCAST;
- do_report= 1;
- }
- if (ipconf->nwic_flags & NWIC_IPADDR_SET)
- {
- ipaddr= ipconf->nwic_ipaddr;
- ip_port->ip_ipaddr= ipaddr;
- ip_port->ip_flags |= IPF_IPADDRSET;
- ip_port->ip_classfulmask=
- ip_netmask(ip_nettype(ipaddr));
- if (!(ip_port->ip_flags & IPF_NETMASKSET))
- {
- ip_port->ip_subnetmask= ip_port->ip_classfulmask;
- }
- if (ipaddr == HTONL(0x00000000))
- {
- /* Special case. Use 0.0.0.0 to shutdown interface. */
- ip_port->ip_flags &= ~(IPF_IPADDRSET|IPF_NETMASKSET);
- ip_port->ip_subnetmask= HTONL(0x00000000);
- }
- (*ip_port->ip_dev_set_ipaddr)(ip_port);
-
- /* revive calls waiting for an ip addresses */
- for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- if (!(ip_fd->if_flags & IFF_INUSE))
- continue;
- if (ip_fd->if_port != ip_port)
- continue;
- if (ip_fd->if_flags & IFF_IOCTL_IP)
- ip_ioctl (i, ip_fd->if_ioctl);
- }
-
- do_report= 1;
- }
-
- ipr_chk_itab(ip_port-ip_port_table, ip_port->ip_ipaddr,
- ip_port->ip_subnetmask);
- ipr_chk_otab(ip_port-ip_port_table, ip_port->ip_ipaddr,
- ip_port->ip_subnetmask);
- if (do_report)
- report_addr(ip_port);
-
- return 0;
-}
-
-static int ip_checkopt (ip_fd)
-ip_fd_t *ip_fd;
-{
-/* bug: we don't check access modes yet */
-
- unsigned long flags;
- unsigned int en_di_flags;
- acc_t *pack;
- int result;
-
- flags= ip_fd->if_ipopt.nwio_flags;
- en_di_flags= (flags >>16) | (flags & 0xffff);
-
- if (flags & NWIO_HDR_O_SPEC)
- {
- result= ip_chk_hdropt (ip_fd->if_ipopt.nwio_hdropt.iho_data,
- ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz);
- if (result<0)
- return result;
- }
- if ((en_di_flags & NWIO_ACC_MASK) &&
- (en_di_flags & NWIO_LOC_MASK) &&
- (en_di_flags & NWIO_BROAD_MASK) &&
- (en_di_flags & NWIO_REM_MASK) &&
- (en_di_flags & NWIO_PROTO_MASK) &&
- (en_di_flags & NWIO_HDR_O_MASK) &&
- (en_di_flags & NWIO_RW_MASK))
- {
- ip_fd->if_flags |= IFF_OPTSET;
-
- ip_hash_proto(ip_fd);
- }
-
- else
- ip_fd->if_flags &= ~IFF_OPTSET;
-
- while (ip_fd->if_rdbuf_head)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- return NW_OK;
-}
-
-static void reply_thr_get(ip_fd, reply, for_ioctl)
-ip_fd_t *ip_fd;
-size_t reply;
-int for_ioctl;
-{
- acc_t *result;
- result= (ip_fd->if_get_userdata)(ip_fd->if_srfd, reply,
- (size_t)0, for_ioctl);
- assert (!result);
-}
-
-static void report_addr(ip_port)
-ip_port_t *ip_port;
-{
- int i, hdr_len;
- ip_fd_t *ip_fd;
- acc_t *pack;
- ip_hdr_t *ip_hdr;
-
- pack= bf_memreq(IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
-
- hdr_len= IP_MIN_HDR_SIZE;
- ip_hdr->ih_vers_ihl= (IP_VERSION << 4) | (hdr_len/4);
- ip_hdr->ih_tos= 0;
- ip_hdr->ih_length= htons(ip_port->ip_mtu);
- ip_hdr->ih_id= 0;
- ip_hdr->ih_flags_fragoff= 0;
- ip_hdr->ih_ttl= 0;
- ip_hdr->ih_proto= 0;
- ip_hdr->ih_src= ip_port->ip_ipaddr;
- ip_hdr->ih_dst= ip_port->ip_subnetmask;
- ip_hdr_chksum(ip_hdr, hdr_len);
-
- for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
- {
- if (!(ip_fd->if_flags & IFF_INUSE))
- {
- continue;
- }
- if (ip_fd->if_port != ip_port)
- {
- continue;
- }
-
- /* Deliver packet to user */
- pack->acc_linkC++;
- ip_packet2user(ip_fd, pack, 255, IP_MIN_HDR_SIZE);
- }
- bf_afree(pack); pack= NULL;
-}
-
-/*
- * $PchId: ip_ioctl.c,v 1.22 2004/08/03 11:10:08 philip Exp $
- */
+++ /dev/null
-/*
-ip_lib.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-
-#include "assert.h"
-#include "io.h"
-#include "ip_int.h"
-
-THIS_FILE
-
-ipaddr_t ip_get_netmask (ipaddr_t hostaddr)
-{
- return ip_netmask(ip_nettype(hostaddr));
-}
-
-int ip_chk_hdropt (u8_t *opt, int optlen)
-{
- int i, security_present= FALSE, lose_source_present= FALSE,
- strict_source_present= FALSE, record_route_present= FALSE,
- timestamp_present= FALSE;
-
- assert (!(optlen & 3));
- i= 0;
- while (i<optlen)
- {
- DBLOCK(2, printf("*opt= %d\n", *opt));
-
- switch (*opt)
- {
- case IP_OPT_EOL: /* End of Option list */
- return NW_OK;
- case IP_OPT_NOP: /* No Operation */
- i++;
- opt++;
- break;
- case IP_OPT_SEC: /* Security */
- if (security_present)
- return EINVAL;
- security_present= TRUE;
- if (opt[1] != 11)
- return EINVAL;
- i += opt[1];
- opt += opt[1];
- break;
- case IP_OPT_LSRR: /* Lose Source and Record Route */
- if (lose_source_present)
- {
- DBLOCK(1, printf("2nd lose soruce route\n"));
- return EINVAL;
- }
- lose_source_present= TRUE;
- if (opt[1]<3)
- {
- DBLOCK(1,
- printf("wrong length in source route\n"));
- return EINVAL;
- }
- i += opt[1];
- opt += opt[1];
- break;
- case IP_OPT_SSRR: /* Strict Source and Record Route */
- if (strict_source_present)
- return EINVAL;
- strict_source_present= TRUE;
- if (opt[1]<3)
- return EINVAL;
- i += opt[1];
- opt += opt[1];
- break;
- case IP_OPT_RR: /* Record Route */
- if (record_route_present)
- return EINVAL;
- record_route_present= TRUE;
- if (opt[1]<3)
- return EINVAL;
- i += opt[1];
- opt += opt[1];
- break;
- case IP_OPT_TS: /* Timestamp */
- if (timestamp_present)
- return EINVAL;
- timestamp_present= TRUE;
- if (opt[1] != 4)
- return EINVAL;
- switch (opt[3] & 0xff)
- {
- case 0:
- case 1:
- case 3:
- break;
- default:
- return EINVAL;
- }
- i += opt[1];
- opt += opt[1];
- break;
- case IP_OPT_RTRALT:
- if (opt[1] != 4)
- return EINVAL;
- i += opt[1];
- opt += opt[1];
- break;
- default:
- return EINVAL;
- }
- }
- if (i > optlen)
- {
- DBLOCK(1, printf("option of wrong length\n"));
- return EINVAL;
- }
- return NW_OK;
-}
-
-void ip_print_frags(acc_t *acc)
-{
-#if DEBUG
- ip_hdr_t *ip_hdr;
- int first;
-
- if (!acc)
- printf("(null)");
-
- for (first= 1; acc; acc= acc->acc_ext_link, first= 0)
- {
-assert (acc->acc_length >= IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(acc);
- if (first)
- {
- writeIpAddr(ip_hdr->ih_src);
- printf(" > ");
- writeIpAddr(ip_hdr->ih_dst);
- }
- printf(" {%x:%d@%d%c}", ntohs(ip_hdr->ih_id),
- ntohs(ip_hdr->ih_length),
- (ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK)*8,
- (ntohs(ip_hdr->ih_flags_fragoff) & IH_MORE_FRAGS) ?
- '+' : '\0');
- }
-#endif
-}
-
-ipaddr_t ip_get_ifaddr(int port_nr)
-{
- assert(port_nr >= 0 && port_nr < ip_conf_nr);
-
- return ip_port_table[port_nr].ip_ipaddr;
-}
-
-nettype_t ip_nettype(ipaddr_t ipaddr)
-{
- u8_t highbyte;
- nettype_t nettype;
-
- ipaddr= ntohl(ipaddr);
- highbyte= (ipaddr >> 24) & 0xff;
- if (highbyte == 0)
- {
- if (ipaddr == 0)
- nettype= IPNT_ZERO;
- else
- nettype= IPNT_MARTIAN;
- }
- else if (highbyte < 127)
- nettype= IPNT_CLASS_A;
- else if (highbyte == 127)
- nettype= IPNT_LOCAL;
- else if (highbyte < 192)
- nettype= IPNT_CLASS_B;
- else if (highbyte < 224)
- nettype= IPNT_CLASS_C;
- else if (highbyte < 240)
- nettype= IPNT_CLASS_D;
- else if (highbyte < 248)
- nettype= IPNT_CLASS_E;
- else if (highbyte < 255)
- nettype= IPNT_MARTIAN;
- else
- {
- if (ipaddr == (ipaddr_t)-1)
- nettype= IPNT_BROADCAST;
- else
- nettype= IPNT_MARTIAN;
- }
- return nettype;
-}
-
-ipaddr_t ip_netmask(nettype_t nettype)
-{
- switch(nettype)
- {
- case IPNT_ZERO: return HTONL(0x00000000);
- case IPNT_CLASS_A:
- case IPNT_LOCAL: return HTONL(0xff000000);
- case IPNT_CLASS_B: return HTONL(0xffff0000);
- case IPNT_CLASS_C: return HTONL(0xffffff00);
- default: return HTONL(0xffffffff);
- }
-}
-
-#if 0
-char *ip_nettoa(nettype_t nettype)
-{
- switch(nettype)
- {
- case IPNT_ZERO: return "zero";
- case IPNT_CLASS_A: return "class A";
- case IPNT_LOCAL: return "local";
- case IPNT_CLASS_B: return "class B";
- case IPNT_CLASS_C: return "class C";
- case IPNT_CLASS_D: return "class D";
- case IPNT_CLASS_E: return "class E";
- case IPNT_MARTIAN: return "martian";
- case IPNT_BROADCAST: return "broadcast";
- default: return "<unknown>";
- }
-}
-#endif
-
-/*
- * $PchId: ip_lib.c,v 1.10 2002/06/08 21:35:52 philip Exp $
- */
+++ /dev/null
-/*
-generic/ip_ps.c
-
-pseudo IP specific part of the IP implementation
-
-Created: Apr 23, 1993 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "assert.h"
-#include "type.h"
-#include "buf.h"
-#include "event.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "psip.h"
-
-THIS_FILE
-
-static void ipps_main ARGS(( ip_port_t *ip_port ));
-static void ipps_set_ipaddr ARGS(( ip_port_t *ip_port ));
-static int ipps_send ARGS(( struct ip_port *ip_port, ipaddr_t dest,
- acc_t *pack, int type ));
-
-int ipps_init(ip_port)
-ip_port_t *ip_port;
-{
- int result;
-
- result= psip_enable(ip_port->ip_dl.dl_ps.ps_port, ip_port->ip_port);
- if (result == -1)
- return -1;
- ip_port->ip_dl.dl_ps.ps_send_head= NULL;
- ip_port->ip_dl.dl_ps.ps_send_tail= NULL;
- ip_port->ip_dev_main= ipps_main;
- ip_port->ip_dev_set_ipaddr= ipps_set_ipaddr;
- ip_port->ip_dev_send= ipps_send;
- return result;
-}
-
-void ipps_get(ip_port_nr)
-int ip_port_nr;
-{
- int result;
- ipaddr_t dest;
- acc_t *acc, *pack, *next_part;
- ip_port_t *ip_port;
-
- assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
- ip_port= &ip_port_table[ip_port_nr];
- assert(ip_port->ip_dl_type == IPDL_PSIP);
-
- while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
- {
- pack= ip_port->ip_dl.dl_ps.ps_send_head;
- ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
-
- /* Extract nexthop address */
- pack= bf_packIffLess(pack, sizeof(dest));
- dest= *(ipaddr_t *)ptr2acc_data(pack);
- pack= bf_delhead(pack, sizeof(dest));
-
- if (bf_bufsize(pack) > ip_port->ip_mtu)
- {
- next_part= pack;
- pack= ip_split_pack(ip_port, &next_part,
- ip_port->ip_mtu);
- if (pack == NULL)
- continue;
-
- /* Prepend nexthop address */
- acc= bf_memreq(sizeof(dest));
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= next_part;
- next_part= acc; acc= NULL;
-
- assert(next_part->acc_linkC == 1);
- next_part->acc_ext_link= NULL;
- if (ip_port->ip_dl.dl_ps.ps_send_head)
- {
- ip_port->ip_dl.dl_ps.ps_send_tail->
- acc_ext_link= next_part;
- }
- else
- {
- ip_port->ip_dl.dl_ps.ps_send_head=
- next_part;
- }
- ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
- }
-
- result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
- if (result != NW_SUSPEND)
- {
- assert(result == NW_OK);
- continue;
- }
-
- /* Prepend nexthop address */
- acc= bf_memreq(sizeof(dest));
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= pack;
- pack= acc; acc= NULL;
-
- pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
- ip_port->ip_dl.dl_ps.ps_send_head= pack;
- if (pack->acc_ext_link == NULL)
- ip_port->ip_dl.dl_ps.ps_send_tail= pack;
- break;
- }
-}
-
-void ipps_put(ip_port_nr, nexthop, pack)
-int ip_port_nr;
-ipaddr_t nexthop;
-acc_t *pack;
-{
- ip_port_t *ip_port;
-
- assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
- ip_port= &ip_port_table[ip_port_nr];
- assert(ip_port->ip_dl_type == IPDL_PSIP);
- if (nexthop == HTONL(0xffffffff))
- ip_arrived_broadcast(ip_port, pack);
- else
- ip_arrived(ip_port, pack);
-}
-
-static void ipps_main(ip_port)
-ip_port_t *ip_port;
-{
- /* nothing to do */
-}
-
-static void ipps_set_ipaddr(ip_port)
-ip_port_t *ip_port;
-{
-}
-
-static int ipps_send(ip_port, dest, pack, type)
-struct ip_port *ip_port;
-ipaddr_t dest;
-acc_t *pack;
-int type;
-{
- int result;
- acc_t *acc, *next_part;
-
- if (type != IP_LT_NORMAL)
- {
- ip_arrived_broadcast(ip_port, bf_dupacc(pack));
-
- /* Map all broadcasts to the on-link broadcast address.
- * This saves the application from having to to find out
- * if the destination is a subnet broadcast.
- */
- dest= HTONL(0xffffffff);
- }
-
- /* Note that allocating a packet may trigger a cleanup action,
- * which may cause the send queue to become empty.
- */
- while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
- {
- acc= bf_memreq(sizeof(dest));
-
- if (ip_port->ip_dl.dl_ps.ps_send_head == NULL)
- {
- bf_afree(acc); acc= NULL;
- continue;
- }
-
- /* Prepend nexthop address */
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= pack;
- pack= acc; acc= NULL;
-
- assert(pack->acc_linkC == 1);
- pack->acc_ext_link= NULL;
-
- ip_port->ip_dl.dl_ps.ps_send_tail->acc_ext_link= pack;
- ip_port->ip_dl.dl_ps.ps_send_tail= pack;
-
- return NW_OK;
- }
-
- while (pack)
- {
- if (bf_bufsize(pack) > ip_port->ip_mtu)
- {
- next_part= pack;
- pack= ip_split_pack(ip_port, &next_part,
- ip_port->ip_mtu);
- if (pack == NULL)
- {
- return NW_OK;
- }
-
- /* Prepend nexthop address */
- acc= bf_memreq(sizeof(dest));
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= next_part;
- next_part= acc; acc= NULL;
-
- assert(next_part->acc_linkC == 1);
- next_part->acc_ext_link= NULL;
- ip_port->ip_dl.dl_ps.ps_send_head= next_part;
- ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
- }
- result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
- if (result == NW_SUSPEND)
- {
- /* Prepend nexthop address */
- acc= bf_memreq(sizeof(dest));
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= pack;
- pack= acc; acc= NULL;
-
- assert(pack->acc_linkC == 1);
- pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
- ip_port->ip_dl.dl_ps.ps_send_head= pack;
- if (!pack->acc_ext_link)
- ip_port->ip_dl.dl_ps.ps_send_tail= pack;
- break;
- }
- assert(result == NW_OK);
- pack= ip_port->ip_dl.dl_ps.ps_send_head;
- if (!pack)
- break;
- ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
-
- /* Extract nexthop address */
- pack= bf_packIffLess(pack, sizeof(dest));
- dest= *(ipaddr_t *)ptr2acc_data(pack);
- pack= bf_delhead(pack, sizeof(dest));
- }
-
- return NW_OK;
-}
-
-#if 0
-int ipps_check(ip_port_t *ip_port)
-{
- int n, bad;
- acc_t *prev, *curr;
-
- for (n= 0, prev= NULL, curr= ip_port->ip_dl.dl_ps.ps_send_head_;
- curr; prev= curr, curr= curr->acc_ext_link)
- {
- n++;
- }
- bad= 0;
- if (prev != NULL && prev != ip_port->ip_dl.dl_ps.ps_send_tail_)
- {
- printf("ipps_check, ip[%d]: wrong tail: got %p, expected %p\n",
- ip_port-ip_port_table,
- ip_port->ip_dl.dl_ps.ps_send_tail_, prev);
- bad++;
- }
- if (n != ip_port->ip_dl.dl_ps.ps_send_nr)
- {
- printf("ipps_check, ip[%d]: wrong count: got %d, expected %d\n",
- ip_port-ip_port_table,
- ip_port->ip_dl.dl_ps.ps_send_nr, n);
- bad++;
- }
- return bad == 0;
-}
-#endif
-
-/*
- * $PchId: ip_ps.c,v 1.15 2003/01/21 15:57:52 philip Exp $
- */
+++ /dev/null
-/*
-ip_read.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "type.h"
-
-#include "assert.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "ipr.h"
-#include "sr.h"
-
-THIS_FILE
-
-static ip_ass_t *find_ass_ent ARGS(( ip_port_t *ip_port, u16_t id,
- ipproto_t proto, ipaddr_t src, ipaddr_t dst ));
-static acc_t *merge_frags ARGS(( acc_t *first, acc_t *second ));
-static int ip_frag_chk ARGS(( acc_t *pack ));
-static acc_t *reassemble ARGS(( ip_port_t *ip_port, acc_t *pack,
- ip_hdr_t *ip_hdr ));
-static void route_packets ARGS(( event_t *ev, ev_arg_t ev_arg ));
-static int broadcast_dst ARGS(( ip_port_t *ip_port, ipaddr_t dest ));
-
-int ip_read(int fd, size_t count)
-{
- ip_fd_t *ip_fd;
- acc_t *pack;
-
- ip_fd= &ip_fd_table[fd];
- if (!(ip_fd->if_flags & IFF_OPTSET))
- {
- return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, EBADMODE,
- (acc_t *)0, FALSE);
- }
-
- ip_fd->if_rd_count= count;
-
- ip_fd->if_flags |= IFF_READ_IP;
- if (ip_fd->if_rdbuf_head)
- {
- if (get_time() <= ip_fd->if_exp_time)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- ip_packet2user (ip_fd, pack, ip_fd->if_exp_time,
- bf_bufsize(pack));
- assert(!(ip_fd->if_flags & IFF_READ_IP));
- return NW_OK;
- }
- while (ip_fd->if_rdbuf_head)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- return NW_SUSPEND;
-}
-
-static acc_t *reassemble (ip_port, pack, pack_hdr)
-ip_port_t *ip_port;
-acc_t *pack;
-ip_hdr_t *pack_hdr;
-{
- ip_ass_t *ass_ent;
- size_t pack_offset, tmp_offset;
- u16_t pack_flags_fragoff;
- acc_t *prev_acc, *curr_acc, *next_acc, *head_acc, *tmp_acc;
- ip_hdr_t *tmp_hdr;
- time_t first_time;
-
- ass_ent= find_ass_ent (ip_port, pack_hdr->ih_id,
- pack_hdr->ih_proto, pack_hdr->ih_src, pack_hdr->ih_dst);
-
- pack_flags_fragoff= ntohs(pack_hdr->ih_flags_fragoff);
- pack_offset= (pack_flags_fragoff & IH_FRAGOFF_MASK)*8;
- pack->acc_ext_link= NULL;
-
- head_acc= ass_ent->ia_frags;
- ass_ent->ia_frags= NULL;
- if (head_acc == NULL)
- {
- ass_ent->ia_frags= pack;
- return NULL;
- }
-
- prev_acc= NULL;
- curr_acc= NULL;
- next_acc= head_acc;
-
- while(next_acc)
- {
- tmp_hdr= (ip_hdr_t *)ptr2acc_data(next_acc);
- tmp_offset= (ntohs(tmp_hdr->ih_flags_fragoff) &
- IH_FRAGOFF_MASK)*8;
-
- if (pack_offset < tmp_offset)
- break;
-
- prev_acc= curr_acc;
- curr_acc= next_acc;
- next_acc= next_acc->acc_ext_link;
- }
- if (curr_acc == NULL)
- {
- assert(prev_acc == NULL);
- assert(next_acc != NULL);
-
- curr_acc= merge_frags(pack, next_acc);
- head_acc= curr_acc;
- }
- else
- {
- curr_acc= merge_frags(curr_acc, pack);
- if (next_acc != NULL)
- curr_acc= merge_frags(curr_acc, next_acc);
- if (prev_acc != NULL)
- prev_acc->acc_ext_link= curr_acc;
- else
- head_acc= curr_acc;
- }
- ass_ent->ia_frags= head_acc;
-
- pack= ass_ent->ia_frags;
- pack_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- pack_flags_fragoff= ntohs(pack_hdr->ih_flags_fragoff);
-
- if (!(pack_flags_fragoff & (IH_FRAGOFF_MASK|IH_MORE_FRAGS)))
- /* it's now a complete packet */
- {
- first_time= ass_ent->ia_first_time;
-
- ass_ent->ia_frags= 0;
- ass_ent->ia_first_time= 0;
-
- while (pack->acc_ext_link)
- {
- tmp_acc= pack->acc_ext_link;
- pack->acc_ext_link= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- }
- if ((ass_ent->ia_min_ttl) * HZ + first_time <
- get_time())
- {
- if (broadcast_dst(ip_port, pack_hdr->ih_dst))
- {
- DBLOCK(1, printf(
- "ip_read'reassemble: reassembly timeout for broadcast packet\n"););
- bf_afree(pack); pack= NULL;
- return NULL;
- }
- icmp_snd_time_exceeded(ip_port->ip_port, pack,
- ICMP_FRAG_REASSEM);
- }
- else
- return pack;
- }
- return NULL;
-}
-
-static acc_t *merge_frags (first, second)
-acc_t *first, *second;
-{
- ip_hdr_t *first_hdr, *second_hdr;
- size_t first_hdr_size, second_hdr_size, first_datasize, second_datasize,
- first_offset, second_offset;
- acc_t *cut_second, *tmp_acc;
-
- if (!second)
- {
- first->acc_ext_link= NULL;
- return first;
- }
-
-assert (first->acc_length >= IP_MIN_HDR_SIZE);
-assert (second->acc_length >= IP_MIN_HDR_SIZE);
-
- first_hdr= (ip_hdr_t *)ptr2acc_data(first);
- first_offset= (ntohs(first_hdr->ih_flags_fragoff) &
- IH_FRAGOFF_MASK) * 8;
- first_hdr_size= (first_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
- first_datasize= ntohs(first_hdr->ih_length) - first_hdr_size;
-
- second_hdr= (ip_hdr_t *)ptr2acc_data(second);
- second_offset= (ntohs(second_hdr->ih_flags_fragoff) &
- IH_FRAGOFF_MASK) * 8;
- second_hdr_size= (second_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
- second_datasize= ntohs(second_hdr->ih_length) - second_hdr_size;
-
- assert (first_hdr_size + first_datasize == bf_bufsize(first));
- assert (second_hdr_size + second_datasize == bf_bufsize(second));
- assert (second_offset >= first_offset);
-
- if (second_offset > first_offset+first_datasize)
- {
- DBLOCK(1, printf("ip fragments out of order\n"));
- first->acc_ext_link= second;
- return first;
- }
-
- if (second_offset + second_datasize <= first_offset +
- first_datasize)
- {
- /* May cause problems if we try to merge. */
- bf_afree(first);
- return second;
- }
-
- if (!(second_hdr->ih_flags_fragoff & HTONS(IH_MORE_FRAGS)))
- first_hdr->ih_flags_fragoff &= ~HTONS(IH_MORE_FRAGS);
-
- second_datasize= second_offset+second_datasize-(first_offset+
- first_datasize);
- cut_second= bf_cut(second, second_hdr_size + first_offset+
- first_datasize-second_offset, second_datasize);
- tmp_acc= second->acc_ext_link;
- bf_afree(second);
- second= tmp_acc;
-
- first_datasize += second_datasize;
- first_hdr->ih_length= htons(first_hdr_size + first_datasize);
-
- first= bf_append (first, cut_second);
- first->acc_ext_link= second;
-
-assert (first_hdr_size + first_datasize == bf_bufsize(first));
-
- return first;
-}
-
-static ip_ass_t *find_ass_ent ARGS(( ip_port_t *ip_port, u16_t id,
- ipproto_t proto, ipaddr_t src, ipaddr_t dst ))
-{
- ip_ass_t *new_ass_ent, *tmp_ass_ent;
- int i;
- acc_t *tmp_acc, *curr_acc;
-
- new_ass_ent= 0;
-
- for (i=0, tmp_ass_ent= ip_ass_table; i<IP_ASS_NR; i++,
- tmp_ass_ent++)
- {
- if (!tmp_ass_ent->ia_frags && tmp_ass_ent->ia_first_time)
- {
- DBLOCK(1,
- printf("strange ip_ass entry (can be a race condition)\n"));
- continue;
- }
-
- if ((tmp_ass_ent->ia_srcaddr == src) &&
- (tmp_ass_ent->ia_dstaddr == dst) &&
- (tmp_ass_ent->ia_proto == proto) &&
- (tmp_ass_ent->ia_id == id) &&
- (tmp_ass_ent->ia_port == ip_port))
- {
- return tmp_ass_ent;
- }
- if (!new_ass_ent || tmp_ass_ent->ia_first_time <
- new_ass_ent->ia_first_time)
- {
- new_ass_ent= tmp_ass_ent;
- }
- }
-
- if (new_ass_ent->ia_frags)
- {
- DBLOCK(2, printf("old frags id= %u, proto= %u, src= ",
- ntohs(new_ass_ent->ia_id),
- new_ass_ent->ia_proto);
- writeIpAddr(new_ass_ent->ia_srcaddr); printf(" dst= ");
- writeIpAddr(new_ass_ent->ia_dstaddr); printf(": ");
- ip_print_frags(new_ass_ent->ia_frags); printf("\n"));
- curr_acc= new_ass_ent->ia_frags->acc_ext_link;
- while (curr_acc)
- {
- tmp_acc= curr_acc->acc_ext_link;
- bf_afree(curr_acc);
- curr_acc= tmp_acc;
- }
- curr_acc= new_ass_ent->ia_frags;
- new_ass_ent->ia_frags= 0;
- if (broadcast_dst(ip_port, new_ass_ent->ia_dstaddr))
- {
- DBLOCK(1, printf(
- "ip_read'find_ass_ent: reassembly timeout for broadcast packet\n"));
- bf_afree(curr_acc); curr_acc= NULL;
- }
- else
- {
- icmp_snd_time_exceeded(ip_port->ip_port,
- curr_acc, ICMP_FRAG_REASSEM);
- }
- }
- new_ass_ent->ia_min_ttl= IP_MAX_TTL;
- new_ass_ent->ia_port= ip_port;
- new_ass_ent->ia_first_time= get_time();
- new_ass_ent->ia_srcaddr= src;
- new_ass_ent->ia_dstaddr= dst;
- new_ass_ent->ia_proto= proto;
- new_ass_ent->ia_id= id;
-
- return new_ass_ent;
-}
-
-static int ip_frag_chk(pack)
-acc_t *pack;
-{
- ip_hdr_t *ip_hdr;
- int hdr_len;
-
- if (pack->acc_length < sizeof(ip_hdr_t))
- {
- DBLOCK(1, printf("wrong length\n"));
- return FALSE;
- }
-
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
-
- hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
- if (pack->acc_length < hdr_len)
- {
- DBLOCK(1, printf("wrong length\n"));
-
- return FALSE;
- }
-
- if (((ip_hdr->ih_vers_ihl >> 4) & IH_VERSION_MASK) !=
- IP_VERSION)
- {
- DBLOCK(1, printf("wrong version (ih_vers_ihl=0x%x)\n",
- ip_hdr->ih_vers_ihl));
- return FALSE;
- }
- if (ntohs(ip_hdr->ih_length) != bf_bufsize(pack))
- {
- DBLOCK(1, printf("wrong size\n"));
-
- return FALSE;
- }
- if ((u16_t)~oneC_sum(0, (u16_t *)ip_hdr, hdr_len))
- {
- DBLOCK(1, printf("packet with wrong checksum (= %x)\n",
- (u16_t)~oneC_sum(0, (u16_t *)ip_hdr, hdr_len)));
- return FALSE;
- }
- if (hdr_len>IP_MIN_HDR_SIZE && ip_chk_hdropt((u8_t *)
- (ptr2acc_data(pack) + IP_MIN_HDR_SIZE),
- hdr_len-IP_MIN_HDR_SIZE))
- {
- DBLOCK(1, printf("packet with wrong options\n"));
- return FALSE;
- }
- return TRUE;
-}
-
-int ip_sel_read (ip_fd_t *ip_fd)
-{
- acc_t *pack;
-
- if (!(ip_fd->if_flags & IFF_OPTSET))
- return 1; /* Read will not block */
-
- if (ip_fd->if_rdbuf_head)
- {
- if (get_time() <= ip_fd->if_exp_time)
- return 1;
-
- while (ip_fd->if_rdbuf_head)
- {
- pack= ip_fd->if_rdbuf_head;
- ip_fd->if_rdbuf_head= pack->acc_ext_link;
- bf_afree(pack);
- }
- }
- return 0;
-}
-
-void ip_packet2user (ip_fd, pack, exp_time, data_len)
-ip_fd_t *ip_fd;
-acc_t *pack;
-time_t exp_time;
-size_t data_len;
-{
- acc_t *tmp_pack;
- ip_hdr_t *ip_hdr;
- int result, ip_hdr_len;
- size_t transf_size;
-
- assert (ip_fd->if_flags & IFF_INUSE);
- if (!(ip_fd->if_flags & IFF_READ_IP))
- {
- if (pack->acc_linkC != 1)
- {
- tmp_pack= bf_dupacc(pack);
- bf_afree(pack);
- pack= tmp_pack;
- tmp_pack= NULL;
- }
- pack->acc_ext_link= NULL;
- if (ip_fd->if_rdbuf_head == NULL)
- {
- ip_fd->if_rdbuf_head= pack;
- ip_fd->if_exp_time= exp_time;
- }
- else
- ip_fd->if_rdbuf_tail->acc_ext_link= pack;
- ip_fd->if_rdbuf_tail= pack;
-
- if (ip_fd->if_flags & IFF_SEL_READ)
- {
- ip_fd->if_flags &= ~IFF_SEL_READ;
- if (ip_fd->if_select_res)
- ip_fd->if_select_res(ip_fd->if_srfd,
- SR_SELECT_READ);
- else
- printf("ip_packet2user: no select_res\n");
- }
- return;
- }
-
- assert (pack->acc_length >= IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
-
- if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY)
- {
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
-
- assert (data_len > ip_hdr_len);
- data_len -= ip_hdr_len;
- pack= bf_delhead(pack, ip_hdr_len);
- }
-
- if (data_len > ip_fd->if_rd_count)
- {
- tmp_pack= bf_cut (pack, 0, ip_fd->if_rd_count);
- bf_afree(pack);
- pack= tmp_pack;
- transf_size= ip_fd->if_rd_count;
- }
- else
- transf_size= data_len;
-
- if (ip_fd->if_put_pkt)
- {
- (*ip_fd->if_put_pkt)(ip_fd->if_srfd, pack, transf_size);
- return;
- }
-
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
- (size_t)0, pack, FALSE);
- if (result >= 0)
- {
- if (data_len > transf_size)
- result= EPACKSIZE;
- else
- result= transf_size;
- }
-
- ip_fd->if_flags &= ~IFF_READ_IP;
- result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
- (acc_t *)0, FALSE);
- assert (result >= 0);
-}
-
-void ip_port_arrive (ip_port, pack, ip_hdr)
-ip_port_t *ip_port;
-acc_t *pack;
-ip_hdr_t *ip_hdr;
-{
- ip_fd_t *ip_fd, *first_fd, *share_fd;
- unsigned long ip_pack_stat;
- unsigned size;
- int i;
- int hash, proto;
- time_t exp_time;
-
- assert (pack->acc_linkC>0);
- assert (pack->acc_length >= IP_MIN_HDR_SIZE);
-
- if (ntohs(ip_hdr->ih_flags_fragoff) & (IH_FRAGOFF_MASK|IH_MORE_FRAGS))
- {
- pack= reassemble (ip_port, pack, ip_hdr);
- if (!pack)
- return;
- assert (pack->acc_length >= IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- assert (!(ntohs(ip_hdr->ih_flags_fragoff) &
- (IH_FRAGOFF_MASK|IH_MORE_FRAGS)));
- }
- size= ntohs(ip_hdr->ih_length);
- if (size > bf_bufsize(pack))
- {
- /* Should discard packet */
- assert(0);
- bf_afree(pack); pack= NULL;
- return;
- }
-
- exp_time= get_time() + (ip_hdr->ih_ttl+1) * HZ;
-
- if (ip_hdr->ih_dst == ip_port->ip_ipaddr)
- ip_pack_stat= NWIO_EN_LOC;
- else
- ip_pack_stat= NWIO_EN_BROAD;
-
- proto= ip_hdr->ih_proto;
- hash= proto & (IP_PROTO_HASH_NR-1);
-
- first_fd= NULL;
- for (i= 0; i<2; i++)
- {
- share_fd= NULL;
-
- ip_fd= (i == 0) ? ip_port->ip_proto_any :
- ip_port->ip_proto[hash];
- for (; ip_fd; ip_fd= ip_fd->if_proto_next)
- {
- if (i && ip_fd->if_ipopt.nwio_proto != proto)
- continue;
- if (!(ip_fd->if_ipopt.nwio_flags & ip_pack_stat))
- continue;
- if ((ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC) &&
- ip_hdr->ih_src != ip_fd->if_ipopt.nwio_rem)
- {
- continue;
- }
- if ((ip_fd->if_ipopt.nwio_flags & NWIO_ACC_MASK) ==
- NWIO_SHARED)
- {
- if (!share_fd)
- {
- share_fd= ip_fd;
- continue;
- }
- if (!ip_fd->if_rdbuf_head)
- share_fd= ip_fd;
- continue;
- }
- if (!first_fd)
- {
- first_fd= ip_fd;
- continue;
- }
- pack->acc_linkC++;
- ip_packet2user(ip_fd, pack, exp_time, size);
-
- }
- if (share_fd)
- {
- pack->acc_linkC++;
- ip_packet2user(share_fd, pack, exp_time, size);
- }
- }
- if (first_fd)
- {
- if (first_fd->if_put_pkt &&
- (first_fd->if_flags & IFF_READ_IP) &&
- !(first_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY))
- {
- (*first_fd->if_put_pkt)(first_fd->if_srfd, pack,
- size);
- }
- else
- ip_packet2user(first_fd, pack, exp_time, size);
- }
- else
- {
- if (ip_pack_stat == NWIO_EN_LOC)
- {
- DBLOCK(0x01,
- printf("ip_port_arrive: dropping packet for proto %d\n",
- proto));
- }
- else
- {
- DBLOCK(0x20, printf("dropping packet for proto %d\n",
- proto));
- }
- bf_afree(pack);
- }
-}
-
-void ip_arrived(ip_port, pack)
-ip_port_t *ip_port;
-acc_t *pack;
-{
- ip_hdr_t *ip_hdr;
- ipaddr_t dest;
- int ip_frag_len, ip_hdr_len, highbyte;
- size_t pack_size;
- acc_t *tmp_pack, *hdr_pack;
- ev_arg_t ev_arg;
-
- pack_size= bf_bufsize(pack);
-
- if (pack_size < IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("wrong acc_length\n"));
- bf_afree(pack);
- return;
- }
- pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
- pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
-assert (pack->acc_length >= IP_MIN_HDR_SIZE);
-
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- if (ip_hdr_len>IP_MIN_HDR_SIZE)
- {
- pack= bf_packIffLess(pack, ip_hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- }
- ip_frag_len= ntohs(ip_hdr->ih_length);
- if (ip_frag_len != pack_size)
- {
- if (pack_size < ip_frag_len)
- {
- /* Sent ICMP? */
- DBLOCK(1, printf("wrong acc_length\n"));
- bf_afree(pack);
- return;
- }
- assert(ip_frag_len<pack_size);
- tmp_pack= pack;
- pack= bf_cut(tmp_pack, 0, ip_frag_len);
- bf_afree(tmp_pack);
- pack_size= ip_frag_len;
- }
-
- if (!ip_frag_chk(pack))
- {
- DBLOCK(1, printf("fragment not allright\n"));
- bf_afree(pack);
- return;
- }
-
- /* Decide about local delivery or routing. Local delivery can happen
- * when the destination is the local ip address, or one of the
- * broadcast addresses and the packet happens to be delivered
- * point-to-point.
- */
-
- dest= ip_hdr->ih_dst;
-
- if (dest == ip_port->ip_ipaddr)
- {
- ip_port_arrive (ip_port, pack, ip_hdr);
- return;
- }
- if (broadcast_dst(ip_port, dest))
- {
- ip_port_arrive (ip_port, pack, ip_hdr);
- return;
- }
-
- if (pack->acc_linkC != 1 || pack->acc_buffer->buf_linkC != 1)
- {
- /* Get a private copy of the IP header */
- hdr_pack= bf_memreq(ip_hdr_len);
- memcpy(ptr2acc_data(hdr_pack), ip_hdr, ip_hdr_len);
- pack= bf_delhead(pack, ip_hdr_len);
- hdr_pack->acc_next= pack;
- pack= hdr_pack; hdr_pack= NULL;
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- }
- assert(pack->acc_linkC == 1);
- assert(pack->acc_buffer->buf_linkC == 1);
-
- /* Try to decrement the ttl field with one. */
- if (ip_hdr->ih_ttl < 2)
- {
- icmp_snd_time_exceeded(ip_port->ip_port, pack,
- ICMP_TTL_EXC);
- return;
- }
- ip_hdr->ih_ttl--;
- ip_hdr_chksum(ip_hdr, ip_hdr_len);
-
- /* Avoid routing to bad destinations. */
- highbyte= ntohl(dest) >> 24;
- if (highbyte == 0 || highbyte == 127 ||
- (highbyte == 169 && (((ntohl(dest) >> 16) & 0xff) == 254)) ||
- highbyte >= 0xe0)
- {
- /* Bogus destination address */
- bf_afree(pack);
- return;
- }
-
- /* Further processing from an event handler */
- if (pack->acc_linkC != 1)
- {
- tmp_pack= bf_dupacc(pack);
- bf_afree(pack);
- pack= tmp_pack;
- tmp_pack= NULL;
- }
- pack->acc_ext_link= NULL;
- if (ip_port->ip_routeq_head)
- {
- ip_port->ip_routeq_tail->acc_ext_link= pack;
- ip_port->ip_routeq_tail= pack;
- return;
- }
-
- ip_port->ip_routeq_head= pack;
- ip_port->ip_routeq_tail= pack;
- ev_arg.ev_ptr= ip_port;
- ev_enqueue(&ip_port->ip_routeq_event, route_packets, ev_arg);
-}
-
-void ip_arrived_broadcast(ip_port, pack)
-ip_port_t *ip_port;
-acc_t *pack;
-{
- ip_hdr_t *ip_hdr;
- int ip_frag_len, ip_hdr_len;
- size_t pack_size;
- acc_t *tmp_pack;
-
- pack_size= bf_bufsize(pack);
-
- if (pack_size < IP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("wrong acc_length\n"));
- bf_afree(pack);
- return;
- }
- pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
- pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
-assert (pack->acc_length >= IP_MIN_HDR_SIZE);
-
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
-
- DIFBLOCK(0x20, (ip_hdr->ih_dst & HTONL(0xf0000000)) == HTONL(0xe0000000),
- printf("got multicast packet\n"));
-
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- if (ip_hdr_len>IP_MIN_HDR_SIZE)
- {
- pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
- pack= bf_packIffLess(pack, ip_hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- }
- ip_frag_len= ntohs(ip_hdr->ih_length);
- if (ip_frag_len<pack_size)
- {
- tmp_pack= pack;
- pack= bf_cut(tmp_pack, 0, ip_frag_len);
- bf_afree(tmp_pack);
- }
-
- if (!ip_frag_chk(pack))
- {
- DBLOCK(1, printf("fragment not allright\n"));
- bf_afree(pack);
- return;
- }
-
- if (!broadcast_dst(ip_port, ip_hdr->ih_dst))
- {
-#if 0
- printf(
- "ip[%d]: broadcast packet for ip-nonbroadcast addr, src=",
- ip_port->ip_port);
- writeIpAddr(ip_hdr->ih_src);
- printf(" dst=");
- writeIpAddr(ip_hdr->ih_dst);
- printf("\n");
-#endif
- bf_afree(pack);
- return;
- }
-
- ip_port_arrive (ip_port, pack, ip_hdr);
-}
-
-static void route_packets(ev, ev_arg)
-event_t *ev;
-ev_arg_t ev_arg;
-{
- ip_port_t *ip_port;
- ipaddr_t dest;
- acc_t *pack;
- iroute_t *iroute;
- ip_port_t *next_port;
- int r, type;
- ip_hdr_t *ip_hdr;
- size_t req_mtu;
-
- ip_port= ev_arg.ev_ptr;
- assert(&ip_port->ip_routeq_event == ev);
-
- while (pack= ip_port->ip_routeq_head, pack != NULL)
- {
- ip_port->ip_routeq_head= pack->acc_ext_link;
-
- ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
- dest= ip_hdr->ih_dst;
-
- iroute= iroute_frag(ip_port->ip_port, dest);
- if (iroute == NULL || iroute->irt_dist == IRTD_UNREACHABLE)
- {
- /* Also unreachable */
- /* Finding out if we send a network unreachable is too
- * much trouble.
- */
- if (iroute == NULL)
- {
- printf("ip[%d]: no route to ",
- ip_port-ip_port_table);
- writeIpAddr(dest);
- printf("\n");
- }
- icmp_snd_unreachable(ip_port->ip_port, pack,
- ICMP_HOST_UNRCH);
- continue;
- }
- next_port= &ip_port_table[iroute->irt_port];
-
- if (ip_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))
- {
- req_mtu= bf_bufsize(pack);
- if (req_mtu > next_port->ip_mtu ||
- (iroute->irt_mtu && req_mtu>iroute->irt_mtu))
- {
- icmp_snd_mtu(ip_port->ip_port, pack,
- next_port->ip_mtu);
- continue;
- }
- }
-
- if (next_port != ip_port)
- {
- if (iroute->irt_gateway != 0)
- {
- /* Just send the packet to the next gateway */
- pack->acc_linkC++; /* Extra ref for ICMP */
- r= next_port->ip_dev_send(next_port,
- iroute->irt_gateway,
- pack, IP_LT_NORMAL);
- if (r == EHOSTUNREACH)
- {
- printf("ip[%d]: gw ",
- ip_port-ip_port_table);
- writeIpAddr(iroute->irt_gateway);
- printf(" on ip[%d] is down for dest ",
- next_port-ip_port_table);
- writeIpAddr(dest);
- printf("\n");
- icmp_snd_unreachable(next_port-
- ip_port_table, pack,
- ICMP_HOST_UNRCH);
- pack= NULL;
- }
- else
- {
- assert(r == 0);
- bf_afree(pack); pack= NULL;
- }
- continue;
- }
- /* The packet is for the attached network. Special
- * addresses are the ip address of the interface and
- * net.0 if no IP_42BSD_BCAST.
- */
- if (dest == next_port->ip_ipaddr)
- {
- ip_port_arrive (next_port, pack, ip_hdr);
- continue;
- }
- if (dest == iroute->irt_dest)
- {
- /* Never forward obsolete directed broadcasts */
-#if IP_42BSD_BCAST && 0
- type= IP_LT_BROADCAST;
-#else
- /* Bogus destination address */
- DBLOCK(1, printf(
- "ip[%d]: dropping old-fashioned directed broadcast ",
- ip_port-ip_port_table);
- writeIpAddr(dest);
- printf("\n"););
- icmp_snd_unreachable(next_port-ip_port_table,
- pack, ICMP_HOST_UNRCH);
- continue;
-#endif
- }
- else if (dest == (iroute->irt_dest |
- ~iroute->irt_subnetmask))
- {
- if (!ip_forward_directed_bcast)
- {
- /* Do not forward directed broadcasts */
- DBLOCK(1, printf(
- "ip[%d]: dropping directed broadcast ",
- ip_port-ip_port_table);
- writeIpAddr(dest);
- printf("\n"););
- icmp_snd_unreachable(next_port-
- ip_port_table, pack,
- ICMP_HOST_UNRCH);
- continue;
- }
- else
- type= IP_LT_BROADCAST;
- }
- else
- type= IP_LT_NORMAL;
-
- /* Just send the packet to it's destination */
- pack->acc_linkC++; /* Extra ref for ICMP */
- r= next_port->ip_dev_send(next_port, dest, pack, type);
- if (r == EHOSTUNREACH)
- {
- DBLOCK(1, printf("ip[%d]: next hop ",
- ip_port-ip_port_table);
- writeIpAddr(dest);
- printf(" on ip[%d] is down\n",
- next_port-ip_port_table););
- icmp_snd_unreachable(next_port-ip_port_table,
- pack, ICMP_HOST_UNRCH);
- pack= NULL;
- }
- else
- {
- assert(r == 0 || (printf("r = %d\n", r), 0));
- bf_afree(pack); pack= NULL;
- }
- continue;
- }
-
- /* Now we know that the packet should be routed over the same
- * network as it came from. If there is a next hop gateway,
- * we can send the packet to that gateway and send a redirect
- * ICMP to the sender if the sender is on the attached
- * network. If there is no gateway complain.
- */
- if (iroute->irt_gateway == 0)
- {
- printf("ip_arrived: packet should not be here, src=");
- writeIpAddr(ip_hdr->ih_src);
- printf(" dst=");
- writeIpAddr(ip_hdr->ih_dst);
- printf("\n");
- bf_afree(pack);
- continue;
- }
- if (((ip_hdr->ih_src ^ ip_port->ip_ipaddr) &
- ip_port->ip_subnetmask) == 0)
- {
- /* Finding out if we can send a network redirect
- * instead of a host redirect is too much trouble.
- */
- pack->acc_linkC++;
- icmp_snd_redirect(ip_port->ip_port, pack,
- ICMP_REDIRECT_HOST, iroute->irt_gateway);
- }
- else
- {
- printf("ip_arrived: packet is wrongly routed, src=");
- writeIpAddr(ip_hdr->ih_src);
- printf(" dst=");
- writeIpAddr(ip_hdr->ih_dst);
- printf("\n");
- printf("in port %d, output %d, dest net ",
- ip_port->ip_port,
- iroute->irt_port);
- writeIpAddr(iroute->irt_dest);
- printf("/");
- writeIpAddr(iroute->irt_subnetmask);
- printf(" next hop ");
- writeIpAddr(iroute->irt_gateway);
- printf("\n");
- bf_afree(pack);
- continue;
- }
- /* No code for unreachable ICMPs here. The sender should
- * process the ICMP redirect and figure it out.
- */
- ip_port->ip_dev_send(ip_port, iroute->irt_gateway, pack,
- IP_LT_NORMAL);
- }
-}
-
-static int broadcast_dst(ip_port, dest)
-ip_port_t *ip_port;
-ipaddr_t dest;
-{
- ipaddr_t my_ipaddr, netmask, classmask;
-
- /* Treat class D (multicast) address as broadcasts. */
- if ((dest & HTONL(0xF0000000)) == HTONL(0xE0000000))
- {
- return 1;
- }
-
- /* Accept without complaint if netmask not yet configured. */
- if (!(ip_port->ip_flags & IPF_NETMASKSET))
- {
- return 1;
- }
- /* Two possibilities, 0 (iff IP_42BSD_BCAST) and -1 */
- if (dest == HTONL((ipaddr_t)-1))
- return 1;
-#if IP_42BSD_BCAST
- if (dest == HTONL((ipaddr_t)0))
- return 1;
-#endif
- netmask= ip_port->ip_subnetmask;
- my_ipaddr= ip_port->ip_ipaddr;
-
- if (((my_ipaddr ^ dest) & netmask) != 0)
- {
- classmask= ip_port->ip_classfulmask;
-
- /* Not a subnet broadcast, maybe a classful broadcast */
- if (((my_ipaddr ^ dest) & classmask) != 0)
- {
- return 0;
- }
- /* Two possibilities, net.0 (iff IP_42BSD_BCAST) and net.-1 */
- if ((dest & ~classmask) == ~classmask)
- {
- return 1;
- }
-#if IP_42BSD_BCAST
- if ((dest & ~classmask) == 0)
- return 1;
-#endif
- return 0;
- }
-
- if (!(ip_port->ip_flags & IPF_SUBNET_BCAST))
- return 0; /* No subnet broadcasts on this network */
-
- /* Two possibilities, subnet.0 (iff IP_42BSD_BCAST) and subnet.-1 */
- if ((dest & ~netmask) == ~netmask)
- return 1;
-#if IP_42BSD_BCAST
- if ((dest & ~netmask) == 0)
- return 1;
-#endif
- return 0;
-}
-
-void ip_process_loopb(ev, arg)
-event_t *ev;
-ev_arg_t arg;
-{
- ip_port_t *ip_port;
- acc_t *pack;
-
- ip_port= arg.ev_ptr;
- assert(ev == &ip_port->ip_loopb_event);
-
- while(pack= ip_port->ip_loopb_head, pack != NULL)
- {
- ip_port->ip_loopb_head= pack->acc_ext_link;
- ip_arrived(ip_port, pack);
- }
-}
-
-/*
- * $PchId: ip_read.c,v 1.33 2005/06/28 14:18:50 philip Exp $
- */
+++ /dev/null
-/*
-ip_write.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-
-#include "arp.h"
-#include "assert.h"
-#include "clock.h"
-#include "eth.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "ip_int.h"
-#include "ipr.h"
-
-THIS_FILE
-
-static void error_reply ARGS(( ip_fd_t *fd, int error ));
-
-int ip_write (fd, count)
-int fd;
-size_t count;
-{
- ip_fd_t *ip_fd;
- acc_t *pack;
- int r;
-
- ip_fd= &ip_fd_table[fd];
- if (count > IP_MAX_PACKSIZE)
- {
- error_reply (ip_fd, EPACKSIZE);
- return NW_OK;
- }
- pack= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)0,
- count, FALSE);
- if (!pack)
- return NW_OK;
- r= ip_send(fd, pack, count);
- assert(r != NW_WOULDBLOCK);
-
- if (r == NW_OK)
- error_reply (ip_fd, count);
- else
- error_reply (ip_fd, r);
- return NW_OK;
-}
-
-int ip_send(fd, data, data_len)
-int fd;
-acc_t *data;
-size_t data_len;
-{
- ip_port_t *ip_port;
- ip_fd_t *ip_fd;
- ip_hdr_t *ip_hdr, *tmp_hdr;
- ipaddr_t dstaddr, nexthop, hostrep_dst, my_ipaddr, netmask;
- u8_t *addrInBytes;
- acc_t *tmp_pack, *tmp_pack1;
- int hdr_len, hdr_opt_len, r;
- int type, ttl;
- size_t req_mtu;
- ev_arg_t arg;
-
- ip_fd= &ip_fd_table[fd];
- ip_port= ip_fd->if_port;
-
- if (!(ip_fd->if_flags & IFF_OPTSET))
- {
- bf_afree(data);
- return EBADMODE;
- }
-
- if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
- {
- /* Interface is down. */
- bf_afree(data);
- return ENETDOWN;
- }
-
- data_len= bf_bufsize(data);
-
- if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY)
- {
- tmp_pack= bf_memreq(IP_MIN_HDR_SIZE);
- tmp_pack->acc_next= data;
- data= tmp_pack;
- data_len += IP_MIN_HDR_SIZE;
- }
- if (data_len<IP_MIN_HDR_SIZE)
- {
- bf_afree(data);
- return EPACKSIZE;
- }
-
- data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- if (data->acc_linkC != 1 || data->acc_buffer->buf_linkC != 1)
- {
- tmp_pack= bf_memreq(IP_MIN_HDR_SIZE);
- tmp_hdr= (ip_hdr_t *)ptr2acc_data(tmp_pack);
- *tmp_hdr= *ip_hdr;
- tmp_pack->acc_next= bf_cut(data, IP_MIN_HDR_SIZE,
- data_len-IP_MIN_HDR_SIZE);
- bf_afree(data);
- ip_hdr= tmp_hdr;
- data= tmp_pack;
- assert (data->acc_length >= IP_MIN_HDR_SIZE);
- }
-
- if (ip_fd->if_ipopt.nwio_flags & NWIO_HDR_O_SPEC)
- {
- hdr_opt_len= ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz;
- if (hdr_opt_len)
- {
- tmp_pack= bf_cut(data, 0, IP_MIN_HDR_SIZE);
- tmp_pack1= bf_cut (data, IP_MIN_HDR_SIZE,
- data_len-IP_MIN_HDR_SIZE);
- bf_afree(data);
- data= bf_packIffLess(tmp_pack, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- tmp_pack= bf_memreq (hdr_opt_len);
- memcpy (ptr2acc_data(tmp_pack), ip_fd->if_ipopt.
- nwio_hdropt.iho_data, hdr_opt_len);
- data->acc_next= tmp_pack;
- tmp_pack->acc_next= tmp_pack1;
- hdr_len= IP_MIN_HDR_SIZE+hdr_opt_len;
- }
- else
- hdr_len= IP_MIN_HDR_SIZE;
- ip_hdr->ih_vers_ihl= hdr_len/4;
- ip_hdr->ih_tos= ip_fd->if_ipopt.nwio_tos;
- ip_hdr->ih_flags_fragoff= 0;
- if (ip_fd->if_ipopt.nwio_df)
- ip_hdr->ih_flags_fragoff |= HTONS(IH_DONT_FRAG);
- ip_hdr->ih_ttl= ip_fd->if_ipopt.nwio_ttl;
- ttl= ORTD_UNREACHABLE+1; /* Don't check TTL */
- }
- else
- {
- hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK)*4;
- r= NW_OK;
- if (hdr_len<IP_MIN_HDR_SIZE)
- r= EINVAL;
- else if (hdr_len>data_len)
- r= EPACKSIZE;
- else if (!ip_hdr->ih_ttl)
- r= EINVAL;
- if (r != NW_OK)
- {
- bf_afree(data);
- return r;
- }
-
- data= bf_packIffLess(data, hdr_len);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- if (hdr_len != IP_MIN_HDR_SIZE)
- {
- r= ip_chk_hdropt((u8_t *)(ptr2acc_data(data) +
- IP_MIN_HDR_SIZE),
- hdr_len-IP_MIN_HDR_SIZE);
- if (r != NW_OK)
- {
- bf_afree(data);
- return r;
- }
- }
- ttl= ip_hdr->ih_ttl;
- }
-
- ip_hdr->ih_vers_ihl= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) |
- (IP_VERSION << 4);
- ip_hdr->ih_length= htons(data_len);
- ip_hdr->ih_flags_fragoff &= ~HTONS(IH_FRAGOFF_MASK |
- IH_FLAGS_UNUSED | IH_MORE_FRAGS);
- if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOSPEC)
- ip_hdr->ih_proto= ip_fd->if_ipopt.nwio_proto;
- ip_hdr->ih_id= htons(ip_port->ip_frame_id++);
- ip_hdr->ih_src= ip_fd->if_port->ip_ipaddr;
- if (ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC)
- ip_hdr->ih_dst= ip_fd->if_ipopt.nwio_rem;
-
- netmask= ip_port->ip_subnetmask;
- my_ipaddr= ip_port->ip_ipaddr;
-
- dstaddr= ip_hdr->ih_dst;
- hostrep_dst= ntohl(dstaddr);
- r= 0;
- if (hostrep_dst == (ipaddr_t)-1)
- ; /* OK, local broadcast */
- else if ((hostrep_dst & 0xe0000000l) == 0xe0000000l)
- ; /* OK, Multicast */
- else if ((hostrep_dst & 0xf0000000l) == 0xf0000000l)
- r= EAFNOSUPPORT; /* Bad class */
- else if ((dstaddr ^ my_ipaddr) & netmask)
- ; /* OK, remote destination */
- else if (!(dstaddr & ~netmask) &&
- (ip_port->ip_flags & IPF_SUBNET_BCAST))
- {
- r= EAFNOSUPPORT; /* Zero host part */
- }
- if (r<0)
- {
- DIFBLOCK(1, r == EAFNOSUPPORT,
- printf("bad destination: ");
- writeIpAddr(ip_hdr->ih_dst);
- printf("\n"));
- bf_afree(data);
- return r;
- }
- ip_hdr_chksum(ip_hdr, hdr_len);
-
- data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
- assert (data->acc_length >= IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
-
- if (ip_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))
- {
- req_mtu= bf_bufsize(data);
- if (req_mtu > ip_port->ip_mtu)
- {
- DBLOCK(1, printf(
- "packet is larger than link MTU and DF is set\n"));
- bf_afree(data);
- return EPACKSIZE;
- }
- }
- else
- req_mtu= 0;
-
- addrInBytes= (u8_t *)&dstaddr;
-
- if ((addrInBytes[0] & 0xff) == 0x7f) /* local loopback */
- {
- assert (data->acc_linkC == 1);
- dstaddr= ip_hdr->ih_dst; /* swap src and dst
- * addresses */
- ip_hdr->ih_dst= ip_hdr->ih_src;
- ip_hdr->ih_src= dstaddr;
- data->acc_ext_link= NULL;
- if (ip_port->ip_loopb_head == NULL)
- {
- ip_port->ip_loopb_head= data;
- arg.ev_ptr= ip_port;
- ev_enqueue(&ip_port->ip_loopb_event,
- ip_process_loopb, arg);
- }
- else
- ip_port->ip_loopb_tail->acc_ext_link= data;
- ip_port->ip_loopb_tail= data;
-
- return NW_OK;
- }
-
- if ((dstaddr & HTONL(0xe0000000)) == HTONL(0xe0000000))
- {
- if (dstaddr == (ipaddr_t)-1)
- {
- r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data,
- IP_LT_BROADCAST);
- return r;
- }
- if (ip_nettype(dstaddr) == IPNT_CLASS_D)
- {
- /* Multicast, what about multicast routing? */
- r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data,
- IP_LT_MULTICAST);
- return r;
- }
- }
-
- if (dstaddr == my_ipaddr)
- {
- assert (data->acc_linkC == 1);
-
- data->acc_ext_link= NULL;
- if (ip_port->ip_loopb_head == NULL)
- {
- ip_port->ip_loopb_head= data;
- arg.ev_ptr= ip_port;
- ev_enqueue(&ip_port->ip_loopb_event,
- ip_process_loopb, arg);
- }
- else
- ip_port->ip_loopb_tail->acc_ext_link= data;
- ip_port->ip_loopb_tail= data;
-
- return NW_OK;
- }
-
- if (((dstaddr ^ my_ipaddr) & netmask) == 0)
- {
- type= ((dstaddr == (my_ipaddr | ~netmask) &&
- (ip_port->ip_flags & IPF_SUBNET_BCAST)) ?
- IP_LT_BROADCAST : IP_LT_NORMAL);
-
- r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data, type);
- return r;
- }
-
- r= oroute_frag (ip_port - ip_port_table, dstaddr, ttl, req_mtu,
- &nexthop);
-
- if (r == NW_OK)
- {
- if (nexthop == ip_port->ip_ipaddr)
- {
- data->acc_ext_link= NULL;
- if (ip_port->ip_loopb_head == NULL)
- {
- ip_port->ip_loopb_head= data;
- arg.ev_ptr= ip_port;
- ev_enqueue(&ip_port->ip_loopb_event,
- ip_process_loopb, arg);
- }
- else
- ip_port->ip_loopb_tail->acc_ext_link= data;
- ip_port->ip_loopb_tail= data;
- }
- else
- {
- r= (*ip_port->ip_dev_send)(ip_port,
- nexthop, data, IP_LT_NORMAL);
- }
- }
- else
- {
- DBLOCK(0x10, printf("got error %d\n", r));
- bf_afree(data);
- }
- return r;
-}
-
-void ip_hdr_chksum(ip_hdr, ip_hdr_len)
-ip_hdr_t *ip_hdr;
-int ip_hdr_len;
-{
- ip_hdr->ih_hdr_chk= 0;
- ip_hdr->ih_hdr_chk= ~oneC_sum (0, (u16_t *)ip_hdr, ip_hdr_len);
-}
-
-acc_t *ip_split_pack (ip_port, ref_last, mtu)
-ip_port_t *ip_port;
-acc_t **ref_last;
-int mtu;
-{
- int pack_siz;
- ip_hdr_t *first_hdr, *second_hdr;
- int first_hdr_len, second_hdr_len;
- int first_data_len, second_data_len;
- int data_len, max_data_len, nfrags, new_first_data_len;
- int first_opt_size, second_opt_size;
- acc_t *first_pack, *second_pack, *tmp_pack;
- u8_t *first_optptr, *second_optptr;
- int i, optlen;
-
- first_pack= *ref_last;
- *ref_last= 0;
- second_pack= 0;
-
- first_pack= bf_align(first_pack, IP_MIN_HDR_SIZE, 4);
- first_pack= bf_packIffLess(first_pack, IP_MIN_HDR_SIZE);
- assert (first_pack->acc_length >= IP_MIN_HDR_SIZE);
-
- first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
- first_hdr_len= (first_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
- if (first_hdr_len>IP_MIN_HDR_SIZE)
- {
- first_pack= bf_packIffLess(first_pack, first_hdr_len);
- first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
- }
-
- pack_siz= bf_bufsize(first_pack);
- assert(pack_siz > mtu);
-
- assert (!(first_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)));
-
- if (first_pack->acc_linkC != 1 ||
- first_pack->acc_buffer->buf_linkC != 1)
- {
- /* Get a private copy of the IP header */
- tmp_pack= bf_memreq(first_hdr_len);
- memcpy(ptr2acc_data(tmp_pack), first_hdr, first_hdr_len);
- first_pack= bf_delhead(first_pack, first_hdr_len);
- tmp_pack->acc_next= first_pack;
- first_pack= tmp_pack; tmp_pack= NULL;
- first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
- }
-
- data_len= ntohs(first_hdr->ih_length) - first_hdr_len;
-
- /* Try to split the packet evenly. */
- assert(mtu > first_hdr_len);
- max_data_len= mtu-first_hdr_len;
- nfrags= (data_len/max_data_len)+1;
- new_first_data_len= data_len/nfrags;
- if (new_first_data_len < 8)
- {
- /* Special case for extremely small MTUs */
- new_first_data_len= 8;
- }
- new_first_data_len &= ~7; /* data goes in 8 byte chuncks */
-
- assert(new_first_data_len >= 8);
- assert(new_first_data_len+first_hdr_len <= mtu);
-
- second_data_len= data_len-new_first_data_len;
- second_pack= bf_cut(first_pack, first_hdr_len+
- new_first_data_len, second_data_len);
- tmp_pack= first_pack;
- first_data_len= new_first_data_len;
- first_pack= bf_cut (tmp_pack, 0, first_hdr_len+first_data_len);
- bf_afree(tmp_pack);
- tmp_pack= bf_memreq(first_hdr_len);
- tmp_pack->acc_next= second_pack;
- second_pack= tmp_pack;
- second_hdr= (ip_hdr_t *)ptr2acc_data(second_pack);
- *second_hdr= *first_hdr;
- second_hdr->ih_flags_fragoff= htons(
- ntohs(first_hdr->ih_flags_fragoff)+(first_data_len/8));
-
- first_opt_size= first_hdr_len-IP_MIN_HDR_SIZE;
- second_opt_size= 0;
- if (first_opt_size)
- {
- first_pack= bf_packIffLess (first_pack,
- first_hdr_len);
- first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
- assert (first_pack->acc_length>=first_hdr_len);
- first_optptr= (u8_t *)ptr2acc_data(first_pack)+
- IP_MIN_HDR_SIZE;
- second_optptr= (u8_t *)ptr2acc_data(
- second_pack)+IP_MIN_HDR_SIZE;
- i= 0;
- while (i<first_opt_size)
- {
- switch (*first_optptr & IP_OPT_NUMBER)
- {
- case 0:
- case 1:
- optlen= 1;
- break;
- default:
- optlen= first_optptr[1];
- break;
- }
- assert (i + optlen <= first_opt_size);
- i += optlen;
- if (*first_optptr & IP_OPT_COPIED)
- {
- second_opt_size += optlen;
- while (optlen--)
- *second_optptr++=
- *first_optptr++;
- }
- else
- first_optptr += optlen;
- }
- while (second_opt_size & 3)
- {
- *second_optptr++= 0;
- second_opt_size++;
- }
- }
- second_hdr_len= IP_MIN_HDR_SIZE + second_opt_size;
-
- second_hdr->ih_vers_ihl= (second_hdr->ih_vers_ihl & 0xf0)
- + (second_hdr_len/4);
- second_hdr->ih_length= htons(second_data_len+
- second_hdr_len);
- second_pack->acc_length= second_hdr_len;
-
- assert(first_pack->acc_linkC == 1);
- assert(first_pack->acc_buffer->buf_linkC == 1);
-
- first_hdr->ih_flags_fragoff |= HTONS(IH_MORE_FRAGS);
- first_hdr->ih_length= htons(first_data_len+
- first_hdr_len);
- assert (!(second_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)));
-
- ip_hdr_chksum(first_hdr, first_hdr_len);
- if (second_data_len+second_hdr_len <= mtu)
- {
- /* second_pack will not be split any further, so we have to
- * calculate the header checksum.
- */
- ip_hdr_chksum(second_hdr, second_hdr_len);
- }
-
- *ref_last= second_pack;
-
- return first_pack;
-}
-
-static void error_reply (ip_fd, error)
-ip_fd_t *ip_fd;
-int error;
-{
- if ((*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)error,
- (size_t)0, FALSE))
- {
- ip_panic(( "can't error_reply" ));
- }
-}
-
-/*
- * $PchId: ip_write.c,v 1.22 2004/08/03 11:11:04 philip Exp $
- */
+++ /dev/null
-/*
-ipr.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "clock.h"
-
-#include "type.h"
-#include "assert.h"
-#include "buf.h"
-#include "event.h"
-#include "io.h"
-#include "ip_int.h"
-#include "ipr.h"
-
-THIS_FILE
-
-#define OROUTE_NR 128
-#define OROUTE_STATIC_NR 16
-#define OROUTE_HASH_ASS_NR 4
-#define OROUTE_HASH_NR 32
-#define OROUTE_HASH_MASK (OROUTE_HASH_NR-1)
-
-#define hash_oroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
- hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
- hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
- hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
- (hash_tmp + (port_nr)) & OROUTE_HASH_MASK)
-
-typedef struct oroute_hash
-{
- ipaddr_t orh_addr;
- oroute_t *orh_route;
-} oroute_hash_t;
-
-static oroute_t oroute_table[OROUTE_NR];
-static oroute_t *oroute_head;
-static int static_oroute_nr;
-static oroute_hash_t oroute_hash_table[OROUTE_HASH_NR][OROUTE_HASH_ASS_NR];
-
-#define IROUTE_NR 512
-#define IROUTE_HASH_ASS_NR 4
-#define IROUTE_HASH_NR 32
-#define IROUTE_HASH_MASK (IROUTE_HASH_NR-1)
-
-#define hash_iroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
- hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
- hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
- hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
- (hash_tmp + (port_nr)) & IROUTE_HASH_MASK)
-
-typedef struct iroute_hash
-{
- ipaddr_t irh_addr;
- iroute_t *irh_route;
-} iroute_hash_t;
-
-static iroute_t iroute_table[IROUTE_NR];
-static iroute_hash_t iroute_hash_table[IROUTE_HASH_NR][IROUTE_HASH_ASS_NR];
-
-static oroute_t *oroute_find_ent ARGS(( int port_nr, ipaddr_t dest ));
-static void oroute_del ARGS(( oroute_t *oroute ));
-static oroute_t *sort_dists ARGS(( oroute_t *oroute ));
-static oroute_t *sort_gws ARGS(( oroute_t *oroute ));
-static void oroute_uncache_nw ARGS(( ipaddr_t dest, ipaddr_t netmask ));
-static void iroute_uncache_nw ARGS(( ipaddr_t dest, ipaddr_t netmask ));
-
-void ipr_init()
-{
- int i;
- oroute_t *oroute;
- iroute_t *iroute;
-
- for (i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
- oroute->ort_flags= ORTF_EMPTY;
- static_oroute_nr= 0;
- assert(OROUTE_HASH_ASS_NR == 4);
-
- for (i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
- iroute->irt_flags= IRTF_EMPTY;
- assert(IROUTE_HASH_ASS_NR == 4);
-}
-
-
-iroute_t *iroute_frag(port_nr, dest)
-int port_nr;
-ipaddr_t dest;
-{
- int hash, i;
- iroute_hash_t *iroute_hash;
- iroute_hash_t tmp_hash;
- iroute_t *iroute, *bestroute;
- unsigned long hash_tmp;
- u32_t tmp_mask;
-
- hash= hash_iroute(port_nr, dest, hash_tmp);
- iroute_hash= &iroute_hash_table[hash][0];
- if (iroute_hash[0].irh_addr == dest)
- iroute= iroute_hash[0].irh_route;
- else if (iroute_hash[1].irh_addr == dest)
- {
- tmp_hash= iroute_hash[1];
- iroute_hash[1]= iroute_hash[0];
- iroute_hash[0]= tmp_hash;
- iroute= tmp_hash.irh_route;
- }
- else if (iroute_hash[2].irh_addr == dest)
- {
- tmp_hash= iroute_hash[2];
- iroute_hash[2]= iroute_hash[1];
- iroute_hash[1]= iroute_hash[0];
- iroute_hash[0]= tmp_hash;
- iroute= tmp_hash.irh_route;
- }
- else if (iroute_hash[3].irh_addr == dest)
- {
- tmp_hash= iroute_hash[3];
- iroute_hash[3]= iroute_hash[2];
- iroute_hash[2]= iroute_hash[1];
- iroute_hash[1]= iroute_hash[0];
- iroute_hash[0]= tmp_hash;
- iroute= tmp_hash.irh_route;
- }
- else
- iroute= NULL;
- if (iroute)
- return iroute;
-
- bestroute= NULL;
- for (i= 0, iroute= iroute_table; i < IROUTE_NR; i++, iroute++)
- {
- if (!(iroute->irt_flags & IRTF_INUSE))
- continue;
- if (((dest ^ iroute->irt_dest) & iroute->irt_subnetmask) != 0)
- continue;
- if (!bestroute)
- {
- bestroute= iroute;
- continue;
- }
-
- /* More specific netmasks are better */
- if (iroute->irt_subnetmask != bestroute->irt_subnetmask)
- {
- /* Using two ntohl macros in one expression
- * is not allowed (tmp_l is modified twice)
- */
- tmp_mask= ntohl(iroute->irt_subnetmask);
- if (tmp_mask > ntohl(bestroute->irt_subnetmask))
- bestroute= iroute;
- continue;
- }
-
- /* Dynamic routes override static routes */
- if ((iroute->irt_flags & IRTF_STATIC) !=
- (bestroute->irt_flags & IRTF_STATIC))
- {
- if (bestroute->irt_flags & IRTF_STATIC)
- bestroute= iroute;
- continue;
- }
-
- /* A route to the local interface give an opportunity
- * to send redirects.
- */
- if (iroute->irt_port != bestroute->irt_port)
- {
- if (iroute->irt_port == port_nr)
- bestroute= iroute;
- continue;
- }
- }
- if (bestroute == NULL)
- return NULL;
-
- iroute_hash[3]= iroute_hash[2];
- iroute_hash[2]= iroute_hash[1];
- iroute_hash[1]= iroute_hash[0];
- iroute_hash[0].irh_addr= dest;
- iroute_hash[0].irh_route= bestroute;
-
- return bestroute;
-}
-
-int oroute_frag(port_nr, dest, ttl, msgsize, nexthop)
-int port_nr;
-ipaddr_t dest;
-int ttl;
-size_t msgsize;
-ipaddr_t *nexthop;
-{
- oroute_t *oroute;
-
- oroute= oroute_find_ent(port_nr, dest);
- if (!oroute || oroute->ort_dist > ttl)
- return ENETUNREACH;
- if (msgsize && oroute->ort_mtu &&
- oroute->ort_mtu < msgsize)
- {
- return EPACKSIZE;
- }
-
- *nexthop= oroute->ort_gateway;
- return NW_OK;
-}
-
-
-int ipr_add_oroute(port_nr, dest, subnetmask, gateway,
- timeout, dist, mtu, static_route, preference, oroute_p)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t subnetmask;
-ipaddr_t gateway;
-time_t timeout;
-int dist;
-int mtu;
-int static_route;
-i32_t preference;
-oroute_t **oroute_p;
-{
- int i;
- ip_port_t *ip_port;
- oroute_t *oroute, *oldest_route, *prev, *nw_route, *gw_route,
- *prev_route;
- time_t currtim, exp_tim, exp_tim_orig;
-
- oldest_route= 0;
- currtim= get_time();
- if (timeout)
- exp_tim= timeout+currtim;
- else
- exp_tim= 0;
-
- DBLOCK(0x10,
- printf("ip[%d]: adding oroute to ", port_nr);
- writeIpAddr(dest);
- printf("["); writeIpAddr(subnetmask); printf("] through ");
- writeIpAddr(gateway);
- printf(" timeout: %lds, distance %d, pref %ld, mtu %d\n",
- (long)timeout/HZ, dist, (long)preference, mtu));
-
- ip_port= &ip_port_table[port_nr];
-
- /* Validate gateway */
- if (((gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask) != 0)
- {
- DBLOCK(1, printf("ip[%d]: (ipr_add_oroute) invalid gateway: ",
- port_nr); writeIpAddr(gateway); printf("\n"));
- return EINVAL;
- }
-
- if (static_route)
- {
- if (static_oroute_nr >= OROUTE_STATIC_NR)
- return ENOMEM;
- static_oroute_nr++;
- }
- else
- {
- /* Try to track down any old routes. */
- for(oroute= oroute_head; oroute; oroute= oroute->ort_nextnw)
- {
- if (oroute->ort_port != port_nr)
- continue;
- if (oroute->ort_dest == dest &&
- oroute->ort_subnetmask == subnetmask)
- {
- break;
- }
- }
- for(; oroute; oroute= oroute->ort_nextgw)
- {
- if (oroute->ort_gateway == gateway)
- break;
- }
- for(; oroute; oroute= oroute->ort_nextdist)
- {
- if ((oroute->ort_flags & ORTF_STATIC) != 0)
- continue;
- if (oroute->ort_dist > dist)
- continue;
- break;
- }
- if (oroute)
- {
- assert(oroute->ort_port == port_nr);
- if (dest != 0)
- {
- /* The new expire should not be later
- * than the old expire time. Except for
- * default routes, where the expire time
- * is simple set to the new value.
- */
- exp_tim_orig= oroute->ort_exp_tim;
- if (!exp_tim)
- exp_tim= exp_tim_orig;
- else if (exp_tim_orig &&
- exp_tim > exp_tim_orig)
- {
- exp_tim= exp_tim_orig;
- }
- }
- oroute_del(oroute);
- oroute->ort_flags= 0;
- oldest_route= oroute;
- }
- }
-
- if (oldest_route == NULL)
- {
- /* Look for an unused entry, or remove an existing one */
- for (i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
- {
- if ((oroute->ort_flags & ORTF_INUSE) == 0)
- break;
- if (oroute->ort_exp_tim && oroute->ort_exp_tim <
- currtim)
- {
- oroute_del(oroute);
- oroute->ort_flags= 0;
- break;
- }
- if (oroute->ort_flags & ORTF_STATIC)
- continue;
- if (oroute->ort_dest == 0)
- {
- /* Never remove default routes. */
- continue;
- }
- if (oldest_route == NULL)
- {
- oldest_route= oroute;
- continue;
- }
- if (oroute->ort_timestamp < oldest_route->ort_timestamp)
- {
- oldest_route= oroute;
- }
- }
- if (i < OROUTE_NR)
- oldest_route= oroute;
- else
- {
- assert(oldest_route);
- oroute_del(oldest_route);
- oldest_route->ort_flags= 0;
- }
- }
-
- oldest_route->ort_dest= dest;
- oldest_route->ort_gateway= gateway;
- oldest_route->ort_subnetmask= subnetmask;
- oldest_route->ort_exp_tim= exp_tim;
- oldest_route->ort_timestamp= currtim;
- oldest_route->ort_dist= dist;
- oldest_route->ort_mtu= mtu;
- oldest_route->ort_port= port_nr;
- oldest_route->ort_flags= ORTF_INUSE;
- oldest_route->ort_pref= preference;
- if (static_route)
- oldest_route->ort_flags |= ORTF_STATIC;
-
- /* Insert the route by tearing apart the routing table,
- * and insert the entry during the reconstruction.
- */
- for (prev= 0, nw_route= oroute_head; nw_route;
- prev= nw_route, nw_route= nw_route->ort_nextnw)
- {
- if (nw_route->ort_port != port_nr)
- continue;
- if (nw_route->ort_dest == dest &&
- nw_route->ort_subnetmask == subnetmask)
- {
- if (prev)
- prev->ort_nextnw= nw_route->ort_nextnw;
- else
- oroute_head= nw_route->ort_nextnw;
- break;
- }
- }
- prev_route= nw_route;
- for(prev= NULL, gw_route= nw_route; gw_route;
- prev= gw_route, gw_route= gw_route->ort_nextgw)
- {
- if (gw_route->ort_gateway == gateway)
- {
- if (prev)
- prev->ort_nextgw= gw_route->ort_nextgw;
- else
- nw_route= gw_route->ort_nextgw;
- break;
- }
- }
- oldest_route->ort_nextdist= gw_route;
- gw_route= oldest_route;
- gw_route= sort_dists(gw_route);
- gw_route->ort_nextgw= nw_route;
- nw_route= gw_route;
- nw_route= sort_gws(nw_route);
- nw_route->ort_nextnw= oroute_head;
- oroute_head= nw_route;
- if (nw_route != prev_route)
- oroute_uncache_nw(nw_route->ort_dest, nw_route->ort_subnetmask);
- if (oroute_p != NULL)
- *oroute_p= oldest_route;
- return NW_OK;
-}
-
-int ipr_del_oroute(port_nr, dest, subnetmask, gateway, static_route)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t subnetmask;
-ipaddr_t gateway;
-int static_route;
-{
- int i;
- oroute_t *oroute;
-
- for(i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
- {
- if ((oroute->ort_flags & ORTF_INUSE) == 0)
- continue;
- if (oroute->ort_port != port_nr ||
- oroute->ort_dest != dest ||
- oroute->ort_subnetmask != subnetmask ||
- oroute->ort_gateway != gateway)
- {
- continue;
- }
- if (!!(oroute->ort_flags & ORTF_STATIC) != static_route)
- continue;
- break;
- }
-
- if (i == OROUTE_NR)
- return ESRCH;
-
- if (static_route)
- static_oroute_nr--;
-
- oroute_del(oroute);
- oroute->ort_flags &= ~ORTF_INUSE;
- return NW_OK;
-}
-
-
-
-void ipr_chk_otab(port_nr, addr, mask)
-int port_nr;
-ipaddr_t addr;
-ipaddr_t mask;
-{
- int i;
- oroute_t *oroute;
-
- DBLOCK(1,
- printf("ip[%d] (ipr_chk_otab): addr ", port_nr);
- writeIpAddr(addr);
- printf(" mask ");
- writeIpAddr(mask);
- printf("\n");
- );
-
- if (addr == 0)
- {
- /* Special hack to flush entries for an interface that
- * goes down.
- */
- addr= mask= HTONL(0xffffffff);
- }
-
- for(i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
- {
- if ((oroute->ort_flags & ORTF_INUSE) == 0)
- continue;
- if (oroute->ort_port != port_nr ||
- ((oroute->ort_gateway ^ addr) & mask) == 0)
- {
- continue;
- }
- DBLOCK(1, printf("ip[%d] (ipr_chk_otab): deleting route to ",
- port_nr);
- writeIpAddr(oroute->ort_dest);
- printf(" gw ");
- writeIpAddr(oroute->ort_gateway);
- printf("\n"));
-
- if (oroute->ort_flags & ORTF_STATIC)
- static_oroute_nr--;
- oroute_del(oroute);
- oroute->ort_flags &= ~ORTF_INUSE;
- }
-}
-
-
-void ipr_gateway_down(port_nr, gateway, timeout)
-int port_nr;
-ipaddr_t gateway;
-time_t timeout;
-{
- oroute_t *route_ind;
- time_t currtim;
- int i;
- int result;
-
- currtim= get_time();
- for (i= 0, route_ind= oroute_table; i<OROUTE_NR; i++, route_ind++)
- {
- if (!(route_ind->ort_flags & ORTF_INUSE))
- continue;
- if (route_ind->ort_gateway != gateway)
- continue;
- if (route_ind->ort_exp_tim && route_ind->ort_exp_tim < currtim)
- continue;
- result= ipr_add_oroute(port_nr, route_ind->ort_dest,
- route_ind->ort_subnetmask, gateway,
- timeout, ORTD_UNREACHABLE, route_ind->ort_mtu,
- FALSE, 0, NULL);
- assert(result == NW_OK);
- }
-}
-
-
-void ipr_destunrch(port_nr, dest, netmask, timeout)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t netmask;
-time_t timeout;
-{
- oroute_t *oroute;
- int result;
-
- oroute= oroute_find_ent(port_nr, dest);
-
- if (!oroute)
- {
- DBLOCK(1, printf("ip[%d]: got a dest unreachable for ",
- port_nr);
- writeIpAddr(dest); printf("but no route present\n"));
-
- return;
- }
- result= ipr_add_oroute(port_nr, dest, netmask, oroute->ort_gateway,
- timeout, ORTD_UNREACHABLE, oroute->ort_mtu, FALSE, 0, NULL);
- assert(result == NW_OK);
-}
-
-
-void ipr_redirect(port_nr, dest, netmask, old_gateway, new_gateway,
- timeout)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t netmask;
-ipaddr_t old_gateway;
-ipaddr_t new_gateway;
-time_t timeout;
-{
- oroute_t *oroute;
- ip_port_t *ip_port;
- int result;
-
- ip_port= &ip_port_table[port_nr];
- oroute= oroute_find_ent(port_nr, dest);
-
- if (!oroute)
- {
- DBLOCK(1, printf("ip[%d]: got a redirect for ", port_nr);
- writeIpAddr(dest); printf("but no route present\n"));
- return;
- }
- if (oroute->ort_gateway != old_gateway)
- {
- DBLOCK(1, printf("ip[%d]: got a redirect from ", port_nr);
- writeIpAddr(old_gateway); printf(" for ");
- writeIpAddr(dest); printf(" but curr gateway is ");
- writeIpAddr(oroute->ort_gateway); printf("\n"));
- return;
- }
- if ((new_gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)
- {
- DBLOCK(1, printf("ip[%d]: redirect from ", port_nr);
- writeIpAddr(old_gateway); printf(" for ");
- writeIpAddr(dest); printf(" but new gateway ");
- writeIpAddr(new_gateway);
- printf(" is not on local subnet\n"));
- return;
- }
- if (oroute->ort_flags & ORTF_STATIC)
- {
- if (oroute->ort_dest == dest)
- {
- DBLOCK(1, printf("ip[%d]: got a redirect for ",
- port_nr);
- writeIpAddr(dest);
- printf("but route is fixed\n"));
- return;
- }
- }
- else
- {
- result= ipr_add_oroute(port_nr, dest, netmask,
- oroute->ort_gateway, HZ, ORTD_UNREACHABLE,
- oroute->ort_mtu, FALSE, 0, NULL);
- assert(result == NW_OK);
- }
- result= ipr_add_oroute(port_nr, dest, netmask, new_gateway,
- timeout, 1, oroute->ort_mtu, FALSE, 0, NULL);
- assert(result == NW_OK);
-}
-
-
-void ipr_ttl_exc(port_nr, dest, netmask, timeout)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t netmask;
-time_t timeout;
-{
- oroute_t *oroute;
- int new_dist;
- int result;
-
- oroute= oroute_find_ent(port_nr, dest);
-
- if (!oroute)
- {
- DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
- port_nr);
- writeIpAddr(dest); printf("but no route present\n"));
- return;
- }
-
- new_dist= oroute->ort_dist * 2;
- if (new_dist > IP_DEF_TTL)
- {
- new_dist= oroute->ort_dist+1;
- if (new_dist >= IP_DEF_TTL)
- {
- DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
- port_nr);
- writeIpAddr(dest);
- printf(" but dist is %d\n",
- oroute->ort_dist));
- return;
- }
- }
-
- result= ipr_add_oroute(port_nr, dest, netmask, oroute->ort_gateway,
- timeout, new_dist, oroute->ort_mtu, FALSE, 0, NULL);
- assert(result == NW_OK);
-}
-
-void ipr_mtu(
- int port_nr,
- ipaddr_t dest,
- u16_t mtu,
- time_t timeout
-)
-{
- oroute_t *oroute;
- int result;
-
- oroute= oroute_find_ent(port_nr, dest);
-
- if (!oroute)
- {
- DBLOCK(1, printf("ip[%d]: got a mtu exceeded for ",
- port_nr);
- writeIpAddr(dest); printf("but no route present\n"));
- return;
- }
-
- if (mtu < IP_MIN_MTU)
- return;
- if (oroute->ort_mtu && mtu >= oroute->ort_mtu)
- return; /* Only decrease mtu */
-
- result= ipr_add_oroute(port_nr, dest, HTONL(0xffffffff),
- oroute->ort_gateway, timeout, oroute->ort_dist, mtu,
- FALSE, 0, NULL);
- assert(result == NW_OK);
-}
-
-
-int ipr_get_oroute(ent_no, route_ent)
-int ent_no;
-nwio_route_t *route_ent;
-{
- oroute_t *oroute;
-
- if (ent_no<0 || ent_no>= OROUTE_NR)
- return ENOENT;
-
- oroute= &oroute_table[ent_no];
- if ((oroute->ort_flags & ORTF_INUSE) && oroute->ort_exp_tim &&
- oroute->ort_exp_tim < get_time())
- {
- oroute_del(oroute);
- oroute->ort_flags &= ~ORTF_INUSE;
- }
-
- route_ent->nwr_ent_no= ent_no;
- route_ent->nwr_ent_count= OROUTE_NR;
- route_ent->nwr_dest= oroute->ort_dest;
- route_ent->nwr_netmask= oroute->ort_subnetmask;
- route_ent->nwr_gateway= oroute->ort_gateway;
- route_ent->nwr_dist= oroute->ort_dist;
- route_ent->nwr_flags= NWRF_EMPTY;
- if (oroute->ort_flags & ORTF_INUSE)
- {
- route_ent->nwr_flags |= NWRF_INUSE;
- if (oroute->ort_flags & ORTF_STATIC)
- route_ent->nwr_flags |= NWRF_STATIC;
- }
- route_ent->nwr_pref= oroute->ort_pref;
- route_ent->nwr_mtu= oroute->ort_mtu;
- route_ent->nwr_ifaddr= ip_get_ifaddr(oroute->ort_port);
- return NW_OK;
-}
-
-
-static oroute_t *oroute_find_ent(port_nr, dest)
-int port_nr;
-ipaddr_t dest;
-{
- int hash;
- oroute_hash_t *oroute_hash;
- oroute_hash_t tmp_hash;
- oroute_t *oroute, *bestroute;
- time_t currtim;
- unsigned long hash_tmp;
- u32_t tmp_mask;
-
- currtim= get_time();
-
- hash= hash_oroute(port_nr, dest, hash_tmp);
- oroute_hash= &oroute_hash_table[hash][0];
- if (oroute_hash[0].orh_addr == dest)
- oroute= oroute_hash[0].orh_route;
- else if (oroute_hash[1].orh_addr == dest)
- {
- tmp_hash= oroute_hash[1];
- oroute_hash[1]= oroute_hash[0];
- oroute_hash[0]= tmp_hash;
- oroute= tmp_hash.orh_route;
- }
- else if (oroute_hash[2].orh_addr == dest)
- {
- tmp_hash= oroute_hash[2];
- oroute_hash[2]= oroute_hash[1];
- oroute_hash[1]= oroute_hash[0];
- oroute_hash[0]= tmp_hash;
- oroute= tmp_hash.orh_route;
- }
- else if (oroute_hash[3].orh_addr == dest)
- {
- tmp_hash= oroute_hash[3];
- oroute_hash[3]= oroute_hash[2];
- oroute_hash[2]= oroute_hash[1];
- oroute_hash[1]= oroute_hash[0];
- oroute_hash[0]= tmp_hash;
- oroute= tmp_hash.orh_route;
- }
- else
- oroute= NULL;
- if (oroute)
- {
- assert(oroute->ort_port == port_nr);
- if (oroute->ort_exp_tim && oroute->ort_exp_tim<currtim)
- {
- oroute_del(oroute);
- oroute->ort_flags &= ~ORTF_INUSE;
- }
- else
- return oroute;
- }
-
- bestroute= NULL;
- for (oroute= oroute_head; oroute; oroute= oroute->ort_nextnw)
- {
- if (((dest ^ oroute->ort_dest) & oroute->ort_subnetmask) != 0)
- continue;
- if (oroute->ort_port != port_nr)
- continue;
- if (!bestroute)
- {
- bestroute= oroute;
- continue;
- }
- assert(oroute->ort_dest != bestroute->ort_dest);
- /* Using two ntohl macros in one expression
- * is not allowed (tmp_l is modified twice)
- */
- tmp_mask= ntohl(oroute->ort_subnetmask);
- if (tmp_mask > ntohl(bestroute->ort_subnetmask))
- {
- bestroute= oroute;
- continue;
- }
- }
- if (bestroute == NULL)
- return NULL;
-
- oroute_hash[3]= oroute_hash[2];
- oroute_hash[2]= oroute_hash[1];
- oroute_hash[1]= oroute_hash[0];
- oroute_hash[0].orh_addr= dest;
- oroute_hash[0].orh_route= bestroute;
-
- return bestroute;
-}
-
-
-static void oroute_del(oroute)
-oroute_t *oroute;
-{
- oroute_t *prev, *nw_route, *gw_route, *dist_route, *prev_route;
-
- DBLOCK(0x10,
- printf("ip[%d]: deleting oroute to ", oroute->ort_port);
- writeIpAddr(oroute->ort_dest);
- printf("["); writeIpAddr(oroute->ort_subnetmask);
- printf("] through ");
- writeIpAddr(oroute->ort_gateway);
- printf(
- " timestamp %lds, timeout: %lds, distance %d pref %ld mtu %ld ",
- (long)oroute->ort_timestamp/HZ,
- (long)oroute->ort_exp_tim/HZ, oroute->ort_dist,
- (long)oroute->ort_pref, (long)oroute->ort_mtu);
- printf("flags 0x%x\n", oroute->ort_flags));
-
- for (prev= NULL, nw_route= oroute_head; nw_route;
- prev= nw_route, nw_route= nw_route->ort_nextnw)
- {
- if (oroute->ort_port == nw_route->ort_port &&
- oroute->ort_dest == nw_route->ort_dest &&
- oroute->ort_subnetmask == nw_route->ort_subnetmask)
- {
- break;
- }
- }
- assert(nw_route);
- if (prev)
- prev->ort_nextnw= nw_route->ort_nextnw;
- else
- oroute_head= nw_route->ort_nextnw;
- prev_route= nw_route;
- for (prev= NULL, gw_route= nw_route; gw_route;
- prev= gw_route, gw_route= gw_route->ort_nextgw)
- {
- if (oroute->ort_gateway == gw_route->ort_gateway)
- break;
- }
- assert(gw_route);
- if (prev)
- prev->ort_nextgw= gw_route->ort_nextgw;
- else
- nw_route= gw_route->ort_nextgw;
- for (prev= NULL, dist_route= gw_route; dist_route;
- prev= dist_route, dist_route= dist_route->ort_nextdist)
- {
- if (oroute == dist_route)
- break;
- }
- assert(dist_route);
- if (prev)
- prev->ort_nextdist= dist_route->ort_nextdist;
- else
- gw_route= dist_route->ort_nextdist;
- gw_route= sort_dists(gw_route);
- if (gw_route != NULL)
- {
- gw_route->ort_nextgw= nw_route;
- nw_route= gw_route;
- }
- nw_route= sort_gws(nw_route);
- if (nw_route != NULL)
- {
- nw_route->ort_nextnw= oroute_head;
- oroute_head= nw_route;
- }
- if (nw_route != prev_route)
- {
- oroute_uncache_nw(prev_route->ort_dest,
- prev_route->ort_subnetmask);
- }
-}
-
-
-static oroute_t *sort_dists(oroute)
-oroute_t *oroute;
-{
- oroute_t *r, *prev, *best, *best_prev;
- int best_dist, best_pref;
-
- best= NULL;
- best_dist= best_pref= 0;
- best_prev= NULL;
- for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextdist)
- {
- if (best == NULL)
- ; /* Force assignment to best */
- else if (r->ort_dist != best_dist)
- {
- if (r->ort_dist > best_dist)
- continue;
- }
- else
- {
- if (r->ort_pref <= best_pref)
- continue;
- }
- best= r;
- best_prev= prev;
- best_dist= r->ort_dist;
- best_pref= r->ort_pref;
- }
- if (!best)
- {
- assert(oroute == NULL);
- return oroute;
- }
- if (!best_prev)
- {
- assert(best == oroute);
- return oroute;
- }
- best_prev->ort_nextdist= best->ort_nextdist;
- best->ort_nextdist= oroute;
- return best;
-}
-
-
-static oroute_t *sort_gws(oroute)
-oroute_t *oroute;
-{
- oroute_t *r, *prev, *best, *best_prev;
- int best_dist, best_pref;
-
- best= NULL;
- best_dist= best_pref= 0;
- best_prev= NULL;
- for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextgw)
- {
- if (best == NULL)
- ; /* Force assignment to best */
- else if (r->ort_dist != best_dist)
- {
- if (r->ort_dist > best_dist)
- continue;
- }
- else
- {
- if (r->ort_pref <= best_pref)
- continue;
- }
- best= r;
- best_prev= prev;
- best_dist= r->ort_dist;
- best_pref= r->ort_pref;
- }
- if (!best)
- {
- assert(oroute == NULL);
- return oroute;
- }
- if (!best_prev)
- {
- assert(best == oroute);
- return oroute;
- }
- best_prev->ort_nextgw= best->ort_nextgw;
- best->ort_nextgw= oroute;
- return best;
-}
-
-
-static void oroute_uncache_nw(dest, netmask)
-ipaddr_t dest;
-ipaddr_t netmask;
-{
- int i, j;
- oroute_hash_t *oroute_hash;
-
- for (i= 0, oroute_hash= &oroute_hash_table[0][0];
- i<OROUTE_HASH_NR; i++, oroute_hash += OROUTE_HASH_ASS_NR)
- {
- for (j= 0; j<OROUTE_HASH_ASS_NR; j++)
- {
- if (((oroute_hash[j].orh_addr ^ dest) & netmask) == 0)
- {
- oroute_hash[j].orh_addr= 0;
- oroute_hash[j].orh_route= NULL;
- }
- }
- }
-}
-
-
-/*
- * Input routing
- */
-
-int ipr_get_iroute(ent_no, route_ent)
-int ent_no;
-nwio_route_t *route_ent;
-{
- iroute_t *iroute;
-
- if (ent_no<0 || ent_no>= IROUTE_NR)
- return ENOENT;
-
- iroute= &iroute_table[ent_no];
-
- route_ent->nwr_ent_no= ent_no;
- route_ent->nwr_ent_count= IROUTE_NR;
- route_ent->nwr_dest= iroute->irt_dest;
- route_ent->nwr_netmask= iroute->irt_subnetmask;
- route_ent->nwr_gateway= iroute->irt_gateway;
- route_ent->nwr_dist= iroute->irt_dist;
- route_ent->nwr_flags= NWRF_EMPTY;
- if (iroute->irt_flags & IRTF_INUSE)
- {
- route_ent->nwr_flags |= NWRF_INUSE;
- if (iroute->irt_flags & IRTF_STATIC)
- route_ent->nwr_flags |= NWRF_STATIC;
- if (iroute->irt_dist == IRTD_UNREACHABLE)
- route_ent->nwr_flags |= NWRF_UNREACHABLE;
- }
- route_ent->nwr_pref= 0;
- route_ent->nwr_mtu= iroute->irt_mtu;
- route_ent->nwr_ifaddr= ip_get_ifaddr(iroute->irt_port);
- return NW_OK;
-}
-
-
-int ipr_add_iroute(port_nr, dest, subnetmask, gateway,
- dist, mtu, static_route, iroute_p)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t subnetmask;
-ipaddr_t gateway;
-int dist;
-int mtu;
-int static_route;
-iroute_t **iroute_p;
-{
- int i;
- iroute_t *iroute, *unused_route;
- ip_port_t *ip_port;
-
- ip_port= &ip_port_table[port_nr];
-
- /* Check gateway */
- if (((gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask) != 0 &&
- gateway != 0)
- {
- DBLOCK(1, printf("ip[%d] (ipr_add_iroute): invalid gateway: ",
- port_nr);
- writeIpAddr(gateway); printf("\n"));
- return EINVAL;
- }
-
- unused_route= NULL;
- if (static_route)
- {
- /* Static routes are not reused automatically, so we look
- * for an unused entry.
- */
- for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
- {
- if ((iroute->irt_flags & IRTF_INUSE) == 0)
- break;
- }
- if (i != IROUTE_NR)
- unused_route= iroute;
- }
- else
- {
- /* Try to track down any old routes, and look for an
- * unused one.
- */
- for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
- {
- if ((iroute->irt_flags & IRTF_INUSE) == 0)
- {
- unused_route= iroute;
- continue;
- }
- if ((iroute->irt_flags & IRTF_STATIC) != 0)
- continue;
- if (iroute->irt_port != port_nr ||
- iroute->irt_dest != dest ||
- iroute->irt_subnetmask != subnetmask ||
- iroute->irt_gateway != gateway)
- {
- continue;
- }
- break;
- }
- if (i != IROUTE_NR)
- unused_route= iroute;
- }
-
- if (unused_route == NULL)
- return ENOMEM;
- iroute= unused_route;
-
- iroute->irt_port= port_nr;
- iroute->irt_dest= dest;
- iroute->irt_subnetmask= subnetmask;
- iroute->irt_gateway= gateway;
- iroute->irt_dist= dist;
- iroute->irt_mtu= mtu;
- iroute->irt_flags= IRTF_INUSE;
- if (static_route)
- iroute->irt_flags |= IRTF_STATIC;
-
- iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
- if (iroute_p != NULL)
- *iroute_p= iroute;
- return NW_OK;
-}
-
-
-int ipr_del_iroute(port_nr, dest, subnetmask, gateway, static_route)
-int port_nr;
-ipaddr_t dest;
-ipaddr_t subnetmask;
-ipaddr_t gateway;
-int static_route;
-{
- int i;
- iroute_t *iroute;
-
- /* Try to track down any old routes, and look for an
- * unused one.
- */
- for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
- {
- if ((iroute->irt_flags & IRTF_INUSE) == 0)
- continue;
- if (iroute->irt_port != port_nr ||
- iroute->irt_dest != dest ||
- iroute->irt_subnetmask != subnetmask ||
- iroute->irt_gateway != gateway)
- {
- continue;
- }
- if (!!(iroute->irt_flags & IRTF_STATIC) != static_route)
- continue;
- break;
- }
-
- if (i == IROUTE_NR)
- return ESRCH;
-
- iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
- iroute->irt_flags= IRTF_EMPTY;
- return NW_OK;
-}
-
-
-void ipr_chk_itab(port_nr, addr, mask)
-int port_nr;
-ipaddr_t addr;
-ipaddr_t mask;
-{
- int i;
- iroute_t *iroute;
-
- DBLOCK(1,
- printf("ip[%d] (ipr_chk_itab): addr ", port_nr);
- writeIpAddr(addr);
- printf(" mask ");
- writeIpAddr(mask);
- printf("\n");
- );
-
- if (addr == 0)
- {
- /* Special hack to flush entries for an interface that
- * goes down.
- */
- addr= mask= HTONL(0xffffffff);
- }
-
- for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
- {
- if ((iroute->irt_flags & IRTF_INUSE) == 0)
- continue;
- if (iroute->irt_port != port_nr)
- continue;
- if (iroute->irt_gateway == 0)
- {
- /* Special case: attached network. */
- if (iroute->irt_subnetmask == mask &&
- iroute->irt_dest == (addr & mask))
- {
- /* Nothing changed. */
- continue;
- }
- }
- if (((iroute->irt_gateway ^ addr) & mask) == 0)
- continue;
-
- DBLOCK(1, printf("ip[%d] (ipr_chk_itab): deleting route to ",
- port_nr);
- writeIpAddr(iroute->irt_dest);
- printf(" gw ");
- writeIpAddr(iroute->irt_gateway);
- printf("\n"));
-
- iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
- iroute->irt_flags &= ~IRTF_INUSE;
- }
-}
-
-
-static void iroute_uncache_nw(dest, netmask)
-ipaddr_t dest;
-ipaddr_t netmask;
-{
- int i, j;
- iroute_hash_t *iroute_hash;
-
- for (i= 0, iroute_hash= &iroute_hash_table[0][0];
- i<IROUTE_HASH_NR; i++, iroute_hash += IROUTE_HASH_ASS_NR)
- {
- for (j= 0; j<IROUTE_HASH_ASS_NR; j++)
- {
- if (((iroute_hash[j].irh_addr ^ dest) &
- netmask) == 0)
- {
- iroute_hash[j].irh_addr= 0;
- iroute_hash[j].irh_route= NULL;
- }
- }
- }
-}
-
-
-
-/*
- * $PchId: ipr.c,v 1.23 2003/01/22 11:49:58 philip Exp $
- */
+++ /dev/null
-/*
-ipr.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef IPR_H
-#define IPR_H
-
-typedef struct oroute
-{
- int ort_port;
- ipaddr_t ort_dest;
- ipaddr_t ort_subnetmask;
- int ort_dist;
- i32_t ort_pref;
- u32_t ort_mtu;
- ipaddr_t ort_gateway;
- time_t ort_exp_tim;
- time_t ort_timestamp;
- int ort_flags;
-
- struct oroute *ort_nextnw;
- struct oroute *ort_nextgw;
- struct oroute *ort_nextdist;
-} oroute_t;
-
-#define ORTD_UNREACHABLE 512
-
-#define ORTF_EMPTY 0
-#define ORTF_INUSE 1
-#define ORTF_STATIC 2
-
-typedef struct iroute
-{
- ipaddr_t irt_dest;
- ipaddr_t irt_gateway;
- ipaddr_t irt_subnetmask;
- int irt_dist;
- u32_t irt_mtu;
- int irt_port;
- int irt_flags;
-} iroute_t;
-
-#define IRTD_UNREACHABLE 512
-
-#define IRTF_EMPTY 0
-#define IRTF_INUSE 1
-#define IRTF_STATIC 2
-
-#define IPR_UNRCH_TIMEOUT (60L * HZ)
-#define IPR_TTL_TIMEOUT (60L * HZ)
-#define IPR_REDIRECT_TIMEOUT (20 * 60L * HZ)
-#define IPR_GW_DOWN_TIMEOUT (60L * HZ)
-#define IPR_MTU_TIMEOUT (10*60L * HZ) /* RFC-1191 */
-
-/* Prototypes */
-
-iroute_t *iroute_frag ARGS(( int port_nr, ipaddr_t dest ));
-int oroute_frag ARGS(( int port_nr, ipaddr_t dest, int ttl, size_t msgsize,
- ipaddr_t *nexthop ));
-void ipr_init ARGS(( void ));
-int ipr_get_iroute ARGS(( int ent_no, nwio_route_t *route_ent ));
-int ipr_add_iroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- ipaddr_t gateway, int dist, int mtu, int static_route,
- iroute_t **route_p ));
-int ipr_del_iroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- ipaddr_t gateway, int static_route ));
-void ipr_chk_itab ARGS(( int port_nr, ipaddr_t addr, ipaddr_t mask ));
-int ipr_get_oroute ARGS(( int ent_no, nwio_route_t *route_ent ));
-int ipr_add_oroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- ipaddr_t gateway, time_t timeout, int dist, int mtu, int static_route,
- i32_t preference, oroute_t **route_p ));
-int ipr_del_oroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- ipaddr_t gateway, int static_route ));
-void ipr_chk_otab ARGS(( int port_nr, ipaddr_t addr, ipaddr_t mask ));
-void ipr_gateway_down ARGS(( int port_nr, ipaddr_t gateway, time_t timeout ));
-void ipr_redirect ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- ipaddr_t old_gateway, ipaddr_t new_gateway, time_t timeout ));
-void ipr_destunrch ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- time_t timeout ));
-void ipr_ttl_exc ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
- time_t timeout ));
-void ipr_mtu ARGS(( int port_nr, ipaddr_t dest, u16_t mtu, time_t timeout ));
-
-#endif /* IPR_H */
-
-/*
- * $PchId: ipr.h,v 1.8 2002/06/09 07:48:11 philip Exp $
- */
+++ /dev/null
-/*
-generic/psip.c
-
-Implementation of a pseudo IP device.
-
-Created: Apr 22, 1993 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "assert.h"
-#include "buf.h"
-#include "event.h"
-#include "type.h"
-#include "ip_int.h"
-#include "psip.h"
-#include "sr.h"
-
-THIS_FILE
-
-typedef struct psip_port
-{
- int pp_flags;
- int pp_ipdev;
- int pp_opencnt;
- struct psip_fd *pp_rd_head;
- struct psip_fd *pp_rd_tail;
- acc_t *pp_promisc_head;
- acc_t *pp_promisc_tail;
-} psip_port_t;
-
-#define PPF_EMPTY 0
-#define PPF_CONFIGURED 1
-#define PPF_ENABLED 2
-#define PPF_PROMISC 4
-
-#define PSIP_FD_NR (1*IP_PORT_MAX)
-
-typedef struct psip_fd
-{
- int pf_flags;
- int pf_srfd;
- psip_port_t *pf_port;
- get_userdata_t pf_get_userdata;
- put_userdata_t pf_put_userdata;
- struct psip_fd *pf_rd_next;
- size_t pf_rd_count;
- nwio_psipopt_t pf_psipopt;
-} psip_fd_t;
-
-#define PFF_EMPTY 0
-#define PFF_INUSE 1
-#define PFF_READ_IP 2
-#define PFF_PROMISC 4
-#define PFF_NEXTHOP 8
-
-static psip_port_t *psip_port_table;
-static psip_fd_t psip_fd_table[PSIP_FD_NR];
-
-static int psip_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t pkt_pkt, select_res_t select_res ));
-static int psip_ioctl ARGS(( int fd, ioreq_t req ));
-static int psip_read ARGS(( int fd, size_t count ));
-static int psip_write ARGS(( int fd, size_t count ));
-static int psip_select ARGS(( int port_nr, unsigned operations ));
-static void psip_close ARGS(( int fd ));
-static int psip_cancel ARGS(( int fd, int which_operation ));
-static void promisc_restart_read ARGS(( psip_port_t *psip_port ));
-static int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));
-static void psip_buffree ARGS(( int priority ));
-static void check_promisc ARGS(( psip_port_t *psip_port ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void psip_bufcheck ARGS(( void ));
-#endif
-static void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,
- int for_ioctl ));
-static void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,
- int for_ioctl ));
-
-void psip_prep()
-{
- psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));
-}
-
-void psip_init()
-{
- int i;
- psip_port_t *psip_port;
- psip_fd_t *psip_fd;
-
- for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
- psip_port->pp_flags= PPF_EMPTY;
-
- for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
- psip_fd->pf_flags= PFF_EMPTY;
-
- for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
- {
- psip_port->pp_flags |= PPF_CONFIGURED;
- psip_port->pp_opencnt= 0;
- psip_port->pp_rd_head= NULL;
- psip_port->pp_promisc_head= NULL;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(psip_buffree);
-#else
- bf_logon(psip_buffree, psip_bufcheck);
-#endif
-}
-
-int psip_enable(port_nr, ip_port_nr)
-int port_nr;
-int ip_port_nr;
-{
- psip_port_t *psip_port;
-
- assert(port_nr >= 0);
- if (port_nr >= psip_conf_nr)
- return -1;
-
- psip_port= &psip_port_table[port_nr];
- if (!(psip_port->pp_flags &PPF_CONFIGURED))
- return -1;
-
- psip_port->pp_ipdev= ip_port_nr;
- psip_port->pp_flags |= PPF_ENABLED;
-
- sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),
- port_nr, psip_open, psip_close, psip_read,
- psip_write, psip_ioctl, psip_cancel, psip_select);
-
- return NW_OK;
-}
-
-int psip_send(port_nr, dest, pack)
-int port_nr;
-ipaddr_t dest;
-acc_t *pack;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd, *mark_fd;
- int i, result, result1;
- size_t buf_size, extrasize;
- acc_t *hdr_pack, *acc;
- psip_io_hdr_t *hdr;
-
- assert(port_nr >= 0 && port_nr < psip_conf_nr);
- psip_port= &psip_port_table[port_nr];
-
- if (psip_port->pp_opencnt == 0)
- {
- bf_afree(pack);
- return NW_OK;
- }
-
- for(;;)
- {
- mark_fd= psip_port->pp_rd_tail;
-
- for(i= 0; i<PSIP_FD_NR; i++)
- {
- psip_fd= psip_port->pp_rd_head;
- if (!psip_fd)
- return NW_SUSPEND;
- psip_port->pp_rd_head= psip_fd->pf_rd_next;
- if (!(psip_fd->pf_flags & PFF_PROMISC))
- break;
- psip_fd->pf_rd_next= NULL;
- if (psip_port->pp_rd_head == NULL)
- psip_port->pp_rd_head= psip_fd;
- else
- psip_port->pp_rd_tail->pf_rd_next= psip_fd;
- psip_port->pp_rd_tail= psip_fd;
- if (psip_fd == mark_fd)
- return NW_SUSPEND;
- }
- if (i == PSIP_FD_NR)
- ip_panic(( "psip_send: loop" ));
-
- assert(psip_fd->pf_flags & PFF_READ_IP);
- psip_fd->pf_flags &= ~PFF_READ_IP;
-
- if (psip_fd->pf_flags & PFF_NEXTHOP)
- extrasize= sizeof(dest);
- else
- extrasize= 0;
-
- buf_size= bf_bufsize(pack);
- if (buf_size+extrasize <= psip_fd->pf_rd_count)
- {
- if (psip_port->pp_flags & PPF_PROMISC)
- {
- /* Deal with promiscuous mode. */
- hdr_pack= bf_memreq(sizeof(*hdr));
- hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
- memset(hdr, '\0', sizeof(*hdr));
- hdr->pih_flags |= PF_LOC2REM;
- hdr->pih_nexthop= dest;
-
- pack->acc_linkC++;
- hdr_pack->acc_next= pack;
- hdr_pack->acc_ext_link= NULL;
- if (psip_port->pp_promisc_head)
- {
- /* Append at the end. */
- psip_port->pp_promisc_tail->
- acc_ext_link= hdr_pack;
- psip_port->pp_promisc_tail= hdr_pack;
- }
- else
- {
- /* First packet. */
- psip_port->pp_promisc_head= hdr_pack;
- psip_port->pp_promisc_tail= hdr_pack;
- if (psip_port->pp_rd_head)
- promisc_restart_read(psip_port);
- }
- }
-
- if (extrasize)
- {
- /* Prepend nexthop address */
- acc= bf_memreq(sizeof(dest));
- *(ipaddr_t *)(ptr2acc_data(acc))= dest;
- acc->acc_next= pack;
- pack= acc; acc= NULL;
- buf_size += extrasize;
- }
-
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)0, pack, FALSE);
- if (result == NW_OK)
- result= buf_size;
- }
- else
- result= EPACKSIZE;
-
- result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)result, NULL, FALSE);
- assert(result1 == NW_OK);
- if (result == EPACKSIZE)
- continue;
- return NW_OK;
- }
- return NW_SUSPEND;
-}
-
-static int psip_open(port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port;
-int srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd;
- int i;
-
- assert(port >= 0 && port < psip_conf_nr);
- psip_port= &psip_port_table[port];
-
- if (!(psip_port->pp_flags & PPF_ENABLED))
- return ENXIO;
-
- for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
- {
- if (psip_fd->pf_flags & PFF_INUSE)
- continue;
- break;
- }
- if (i == PSIP_FD_NR)
- return ENFILE;
- psip_fd->pf_flags |= PFF_INUSE;
- psip_fd->pf_srfd= srfd;
- psip_fd->pf_port= psip_port;
- psip_fd->pf_get_userdata= get_userdata;
- psip_fd->pf_put_userdata= put_userdata;
- psip_port->pp_opencnt++;
-
- return i;
-}
-
-static int psip_ioctl(fd, req)
-int fd;
-ioreq_t req;
-{
- int result;
- psip_fd_t *psip_fd;
- acc_t *data;
- nwio_ipconf_t *ipconfp;
- nwio_psipopt_t *psip_opt, *newoptp;
-
- assert(fd >= 0 && fd < PSIP_FD_NR);
- psip_fd= &psip_fd_table[fd];
-
- switch(req)
- {
- case NWIOSIPCONF:
- data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
- sizeof(*ipconfp), TRUE);
- if (!data)
- {
- result= EFAULT;
- break;
- }
- data= bf_packIffLess(data, sizeof(*ipconfp));
- assert (data->acc_length == sizeof(*ipconfp));
-
- ipconfp= (nwio_ipconf_t *)ptr2acc_data(data);
- result= ip_setconf(psip_fd->pf_port->pp_ipdev, ipconfp);
- bf_afree(data);
- reply_thr_get(psip_fd, result, TRUE);
- break;
- case NWIOSPSIPOPT:
- data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
- sizeof(*psip_opt), TRUE);
- if (!data)
- {
- result= EFAULT;
- break;
- }
- data= bf_packIffLess(data, sizeof(*psip_opt));
- assert (data->acc_length == sizeof(*psip_opt));
-
- newoptp= (nwio_psipopt_t *)ptr2acc_data(data);
- result= psip_setopt(psip_fd, newoptp);
- bf_afree(data);
- if (result == NW_OK)
- {
- if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)
- {
- psip_fd->pf_flags |= PFF_PROMISC;
- psip_fd->pf_port->pp_flags |= PPF_PROMISC;
- }
- else
- {
- psip_fd->pf_flags &= ~PFF_PROMISC;
- check_promisc(psip_fd->pf_port);
- }
- if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_NEXTHOP)
- {
- psip_fd->pf_flags |= PFF_NEXTHOP;
- }
- else
- {
- psip_fd->pf_flags &= ~PFF_NEXTHOP;
- }
- }
- reply_thr_get(psip_fd, result, TRUE);
- break;
- case NWIOGPSIPOPT:
- data= bf_memreq(sizeof(*psip_opt));
- psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);
-
- *psip_opt= psip_fd->pf_psipopt;
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,
- data, TRUE);
- if (result == NW_OK)
- reply_thr_put(psip_fd, NW_OK, TRUE);
- break;
- default:
- reply_thr_put(psip_fd, ENOTTY, TRUE);
- break;
- }
- return NW_OK;
-}
-
-static int psip_read(fd, count)
-int fd;
-size_t count;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd;
- acc_t *pack;
- size_t buf_size;
- int result, result1;
-
- assert(fd >= 0 && fd < PSIP_FD_NR);
- psip_fd= &psip_fd_table[fd];
- psip_port= psip_fd->pf_port;
-
- if ((psip_fd->pf_flags & PFF_PROMISC) && psip_port->pp_promisc_head)
- {
- /* Deliver a queued packet. */
- pack= psip_port->pp_promisc_head;
- buf_size= bf_bufsize(pack);
- if (buf_size <= count)
- {
- psip_port->pp_promisc_head= pack->acc_ext_link;
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)0, pack, FALSE);
- if (result == NW_OK)
- result= buf_size;
- }
- else
- result= EPACKSIZE;
-
- result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)result, NULL, FALSE);
- assert(result1 == NW_OK);
- return NW_OK;
- }
-
- psip_fd->pf_rd_count= count;
- if (psip_port->pp_rd_head == NULL)
- psip_port->pp_rd_head= psip_fd;
- else
- psip_port->pp_rd_tail->pf_rd_next= psip_fd;
- psip_fd->pf_rd_next= NULL;
- psip_port->pp_rd_tail= psip_fd;
-
- psip_fd->pf_flags |= PFF_READ_IP;
- if (!(psip_fd->pf_flags & PFF_PROMISC))
- ipps_get(psip_port->pp_ipdev);
- if (psip_fd->pf_flags & PFF_READ_IP)
- return NW_SUSPEND;
- return NW_OK;
-}
-
-static int psip_write(fd, count)
-int fd;
-size_t count;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd;
- acc_t *pack, *hdr_pack;
- psip_io_hdr_t *hdr;
- size_t pack_len;
- ipaddr_t nexthop;
-
- assert(fd >= 0 && fd < PSIP_FD_NR);
- psip_fd= &psip_fd_table[fd];
- psip_port= psip_fd->pf_port;
-
- pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)0,
- count, FALSE);
- if (pack == NULL)
- {
- pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
- (size_t)EFAULT, (size_t)0, FALSE);
- assert(pack == NULL);
- return NW_OK;
- }
-
- if (psip_fd->pf_flags & PFF_NEXTHOP)
- {
- pack_len= bf_bufsize(pack);
- if (pack_len <= sizeof(nexthop))
- {
- /* Something strange */
- bf_afree(pack); pack= NULL;
- pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
- (size_t)EPACKSIZE, (size_t)0, FALSE);
- assert(pack == NULL);
- return NW_OK;
- }
- pack= bf_packIffLess(pack, sizeof(nexthop));
- nexthop= *(ipaddr_t *)ptr2acc_data(pack);
- pack= bf_delhead(pack, sizeof(nexthop));
-
- /* Map multicast to broadcast */
- if ((nexthop & HTONL(0xE0000000)) == HTONL(0xE0000000))
- nexthop= HTONL(0xffffffff);
- }
- else
- {
- /* Assume point to point */
- nexthop= HTONL(0x00000000);
- }
-
- if (psip_port->pp_flags & PPF_PROMISC)
- {
- /* Deal with promiscuous mode. */
- hdr_pack= bf_memreq(sizeof(*hdr));
- hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
- memset(hdr, '\0', sizeof(*hdr));
- hdr->pih_flags |= PF_REM2LOC;
- hdr->pih_nexthop= nexthop;
-
- pack->acc_linkC++;
- hdr_pack->acc_next= pack;
- hdr_pack->acc_ext_link= NULL;
- if (psip_port->pp_promisc_head)
- {
- /* Append at the end. */
- psip_port->pp_promisc_tail->acc_ext_link= hdr_pack;
- psip_port->pp_promisc_tail= hdr_pack;
- }
- else
- {
- /* First packet. */
- psip_port->pp_promisc_head= hdr_pack;
- psip_port->pp_promisc_tail= hdr_pack;
- if (psip_port->pp_rd_head)
- promisc_restart_read(psip_port);
- }
- }
- ipps_put(psip_port->pp_ipdev, nexthop, pack);
- pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)count,
- (size_t)0, FALSE);
- assert(pack == NULL);
- return NW_OK;
-}
-
-static int psip_select(fd, operations)
-int fd;
-unsigned operations;
-{
- printf("psip_select: not implemented\n");
- return 0;
-}
-
-static void psip_close(fd)
-int fd;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd;
-
- assert(fd >= 0 && fd < PSIP_FD_NR);
- psip_fd= &psip_fd_table[fd];
- psip_port= psip_fd->pf_port;
-
- if (psip_fd->pf_flags & PFF_PROMISC)
- {
- /* Check if the port should still be in promiscuous mode.
- */
- psip_fd->pf_flags &= ~PFF_PROMISC;
- check_promisc(psip_fd->pf_port);
- }
-
- assert(psip_port->pp_opencnt >0);
- psip_port->pp_opencnt--;
- psip_fd->pf_flags= PFF_EMPTY;
- ipps_get(psip_port->pp_ipdev);
-
-}
-
-static int psip_cancel(fd, which_operation)
-int fd;
-int which_operation;
-{
- psip_port_t *psip_port;
- psip_fd_t *psip_fd, *prev_fd, *tmp_fd;
- int result;
-
- DBLOCK(1, printf("psip_cancel(%d, %d)\n", fd, which_operation));
-
- assert(fd >= 0 && fd < PSIP_FD_NR);
- psip_fd= &psip_fd_table[fd];
- psip_port= psip_fd->pf_port;
-
- switch(which_operation)
- {
- case SR_CANCEL_IOCTL:
- ip_panic(( "should not be here" ));
- case SR_CANCEL_READ:
- assert(psip_fd->pf_flags & PFF_READ_IP);
- for (prev_fd= NULL, tmp_fd= psip_port->pp_rd_head; tmp_fd;
- prev_fd= tmp_fd, tmp_fd= tmp_fd->pf_rd_next)
- {
- if (tmp_fd == psip_fd)
- break;
- }
- if (tmp_fd == NULL)
- ip_panic(( "unable to find to request to cancel" ));
- if (prev_fd == NULL)
- psip_port->pp_rd_head= psip_fd->pf_rd_next;
- else
- prev_fd->pf_rd_next= psip_fd->pf_rd_next;
- if (psip_fd->pf_rd_next == NULL)
- psip_port->pp_rd_tail= prev_fd;
- psip_fd->pf_flags &= ~PFF_READ_IP;
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)EINTR, NULL, FALSE);
- assert(result == NW_OK);
- break;
- case SR_CANCEL_WRITE:
- ip_panic(( "should not be here" ));
- default:
- ip_panic(( "invalid operation for cancel" ));
- }
- return NW_OK;
-}
-
-static void promisc_restart_read(psip_port)
-psip_port_t *psip_port;
-{
- psip_fd_t *psip_fd, *prev, *next;
- acc_t *pack;
- size_t buf_size;
- int result, result1;
-
- /* Overkill at the moment: just one reader in promiscious mode is
- * allowed.
- */
- pack= psip_port->pp_promisc_head;
- if (!pack)
- return;
- assert(pack->acc_ext_link == NULL);
-
- for(psip_fd= psip_port->pp_rd_head, prev= NULL; psip_fd;
- prev= psip_fd, psip_fd= psip_fd->pf_rd_next)
- {
-again:
- if (!(psip_fd->pf_flags & PFF_PROMISC))
- continue;
- next= psip_fd->pf_rd_next;
- if (prev)
- prev->pf_rd_next= next;
- else
- psip_port->pp_rd_head= next;
- if (!next)
- psip_port->pp_rd_tail= prev;
-
- assert(psip_fd->pf_flags & PFF_READ_IP);
- psip_fd->pf_flags &= ~PFF_READ_IP;
-
- buf_size= bf_bufsize(pack);
- if (buf_size <= psip_fd->pf_rd_count)
- {
- psip_port->pp_promisc_head= pack->acc_ext_link;
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)0, pack, FALSE);
- if (result == NW_OK)
- result= buf_size;
- }
- else
- result= EPACKSIZE;
-
- result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
- (size_t)result, NULL, FALSE);
- assert(result1 == NW_OK);
-
- if (psip_port->pp_promisc_head)
- {
- /* Restart from the beginning */
- assert(result == EPACKSIZE);
- psip_fd= psip_port->pp_rd_head;
- prev= NULL;
- goto again;
- }
- break;
- }
-}
-
-static int psip_setopt(psip_fd, newoptp)
-psip_fd_t *psip_fd;
-nwio_psipopt_t *newoptp;
-{
- nwio_psipopt_t oldopt;
- unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags;
- unsigned long new_flags;
-
- oldopt= psip_fd->pf_psipopt;
-
- old_en_flags= oldopt.nwpo_flags & 0xffff;
- old_di_flags= (oldopt.nwpo_flags >> 16) & 0xffff;
-
- new_en_flags= newoptp->nwpo_flags & 0xffff;
- new_di_flags= (newoptp->nwpo_flags >> 16) & 0xffff;
-
- if (new_en_flags & new_di_flags)
- return EBADMODE;
-
- /* NWUO_LOCADDR_MASK */
- if (!((new_en_flags | new_di_flags) & NWPO_PROMISC_MASK))
- {
- new_en_flags |= (old_en_flags & NWPO_PROMISC_MASK);
- new_di_flags |= (old_di_flags & NWPO_PROMISC_MASK);
- }
-
- new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
- if ((new_flags & NWPO_EN_PROMISC) &&
- (psip_fd->pf_port->pp_flags & PPF_PROMISC))
- {
- printf("psip_setopt: EBUSY for port %d, flags 0x%x\n",
- psip_fd->pf_port - psip_port_table,
- psip_fd->pf_port->pp_flags);
- /* We can support only one at a time. */
- return EBUSY;
- }
-
- psip_fd->pf_psipopt= *newoptp;
- psip_fd->pf_psipopt.nwpo_flags= new_flags;
-
- return NW_OK;
-}
-
-static void check_promisc(psip_port)
-psip_port_t *psip_port;
-{
- int i;
- psip_fd_t *psip_fd;
- acc_t *acc, *acc_next;
-
- /* Check if the port should still be in promiscuous mode. Overkill
- * at the moment.
- */
- if (!(psip_port->pp_flags & PPF_PROMISC))
- return;
-
- psip_port->pp_flags &= ~PPF_PROMISC;
- for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
- {
- if ((psip_fd->pf_flags & (PFF_INUSE|PFF_PROMISC)) !=
- (PFF_INUSE|PFF_PROMISC))
- {
- continue;
- }
- if (psip_fd->pf_port != psip_port)
- continue;
- printf("check_promisc: setting PROMISC for port %d\n",
- psip_port-psip_port_table);
- psip_port->pp_flags |= PPF_PROMISC;
- break;
- }
- if (!(psip_port->pp_flags & PPF_PROMISC))
- {
- /* Delete queued packets. */
- acc= psip_port->pp_promisc_head;
- psip_port->pp_promisc_head= NULL;
- while (acc)
- {
- acc_next= acc->acc_ext_link;
- bf_afree(acc);
- acc= acc_next;
- }
- }
-}
-
-static void psip_buffree (priority)
-int priority;
-{
- int i;
- psip_port_t *psip_port;
- acc_t *tmp_acc, *next_acc;
-
- if (priority == PSIP_PRI_EXP_PROMISC)
- {
- for (i=0, psip_port= psip_port_table; i<psip_conf_nr;
- i++, psip_port++)
- {
- if (!(psip_port->pp_flags & PPF_CONFIGURED) )
- continue;
- if (psip_port->pp_promisc_head)
- {
- tmp_acc= psip_port->pp_promisc_head;
- while(tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- psip_port->pp_promisc_head= NULL;
- }
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void psip_bufcheck()
-{
- int i;
- psip_port_t *psip_port;
- acc_t *tmp_acc;
-
- for (i= 0, psip_port= psip_port_table; i<psip_conf_nr;
- i++, psip_port++)
- {
- for (tmp_acc= psip_port->pp_promisc_head; tmp_acc;
- tmp_acc= tmp_acc->acc_ext_link)
- {
- bf_check_acc(tmp_acc);
- }
- }
-}
-#endif
-
-/*
-reply_thr_put
-*/
-
-static void reply_thr_put(psip_fd, reply, for_ioctl)
-psip_fd_t *psip_fd;
-int reply;
-int for_ioctl;
-{
- int result;
-
- result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, reply,
- (acc_t *)0, for_ioctl);
- assert(result == NW_OK);
-}
-
-/*
-reply_thr_get
-*/
-
-static void reply_thr_get(psip_fd, reply, for_ioctl)
-psip_fd_t *psip_fd;
-int reply;
-int for_ioctl;
-{
- acc_t *result;
- result= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, reply,
- (size_t)0, for_ioctl);
- assert (!result);
-}
-
-
-/*
- * $PchId: psip.c,v 1.15 2005/06/28 14:19:29 philip Exp $
- */
+++ /dev/null
-/*
-generic/psip.h
-
-Public interface to the pseudo IP module
-
-Created: Apr 22, 1993 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef PSIP_H
-#define PSIP_H
-
-void psip_prep ARGS(( void ));
-void psip_init ARGS(( void ));
-int psip_enable ARGS(( int port_nr, int ip_port_nr ));
-int psip_send ARGS(( int port_nr, ipaddr_t dest, acc_t *pack ));
-
-#endif /* PSIP_H */
-
-/*
- * $PchId: psip.h,v 1.6 2001/04/19 21:16:22 philip Exp $
- */
+++ /dev/null
-/*
-rand256.c
-
-Created: Oct 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Generate 256-bit random numbers
-*/
-
-#include <sys/sha2.h>
-#include "inet.h"
-#include "rand256.h"
-
-static u32_t base_bits[8];
-
-void init_rand256(bits)
-u8_t bits[32];
-{
- memcpy(base_bits, bits, sizeof(base_bits));
-}
-
-void rand256(bits)
-u8_t bits[32];
-{
- u32_t a;
- SHA256_CTX ctx;
-
- a= ++base_bits[0];
- if (a == 0)
- base_bits[1]++;
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, (unsigned char *)base_bits, sizeof(base_bits));
- SHA256_Final(bits, &ctx);
-}
-
-/*
- * $PchId: rand256.c,v 1.1 2005/06/28 14:13:43 philip Exp $
- */
+++ /dev/null
-/*
-rand256.h
-
-Created: Oct 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Provide 256-bit random numbers
-*/
-
-#define RAND256_BUFSIZE 32
-
-void init_rand256 ARGS(( u8_t bits[RAND256_BUFSIZE] ));
-void rand256 ARGS(( u8_t bits[RAND256_BUFSIZE] ));
-
-/*
- * $PchId: rand256.h,v 1.1 2005/06/28 14:14:05 philip Exp $
- */
+++ /dev/null
-/*
-sr.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef SR_H
-#define SR_H
-
-#define MAX_IOCTL_S 512
-
-#define SR_CANCEL_IOCTL 1
-#define SR_CANCEL_READ 2
-#define SR_CANCEL_WRITE 3
-
-#define SR_SELECT_READ 0x01
-#define SR_SELECT_WRITE 0x02
-#define SR_SELECT_EXCEPTION 0x04
-#define SR_SELECT_POLL 0x10
-
-/* Forward struct declarations */
-
-struct acc;
-
-/* prototypes */
-
-typedef int (*sr_open_t) ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t select_res ));
-typedef void (*sr_close_t) ARGS(( int fd ));
-typedef int (*sr_read_t) ARGS(( int fd, size_t count ));
-typedef int (*sr_write_t) ARGS(( int fd, size_t count ));
-typedef int (*sr_ioctl_t) ARGS(( int fd, ioreq_t req ));
-typedef int (*sr_cancel_t) ARGS(( int fd, int which_operation ));
-typedef int (*sr_select_t) ARGS(( int fd, unsigned operations ));
-
-void sr_init ARGS(( void ));
-void sr_add_minor ARGS(( int minor, int port, sr_open_t openf,
- sr_close_t closef, sr_read_t sr_read, sr_write_t sr_write,
- sr_ioctl_t ioctlf, sr_cancel_t cancelf, sr_select_t selectf ));
-
-#endif /* SR_H */
-
-/* Track TCP connections back into sr (for lsof, identd, etc.) */
-EXTERN sr_cancel_t tcp_cancel_f;
-
-/*
- * $PchId: sr.h,v 1.9 2005/06/28 14:19:51 philip Exp $
- */
+++ /dev/null
-/*
-tcp.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "type.h"
-
-#include "io.h"
-#include "ip.h"
-#include "sr.h"
-#include "assert.h"
-#include "rand256.h"
-#include "tcp.h"
-#include "tcp_int.h"
-
-THIS_FILE
-
-tcp_port_t *tcp_port_table;
-tcp_fd_t tcp_fd_table[TCP_FD_NR];
-tcp_conn_t tcp_conn_table[TCP_CONN_NR];
-sr_cancel_t tcp_cancel_f;
-
-static void tcp_main ARGS(( tcp_port_t *port ));
-static int tcp_select ARGS(( int fd, unsigned operations ));
-static acc_t *tcp_get_data ARGS(( int fd, size_t offset,
- size_t count, int for_ioctl ));
-static int tcp_put_data ARGS(( int fd, size_t offset,
- acc_t *data, int for_ioctl ));
-static void tcp_put_pkt ARGS(( int fd, acc_t *data, size_t datalen ));
-static void read_ip_packets ARGS(( tcp_port_t *port ));
-static int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));
-static int tcp_setopt ARGS(( tcp_fd_t *tcp_fd ));
-static int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));
-static int tcp_listen ARGS(( tcp_fd_t *tcp_fd, int do_listenq ));
-static int tcp_acceptto ARGS(( tcp_fd_t *tcp_fd ));
-static tcpport_t find_unused_port ARGS(( int fd ));
-static int is_unused_port ARGS(( tcpport_t port ));
-static int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply,
- int for_ioctl ));
-static void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply,
- int for_ioctl ));
-static tcp_conn_t *find_conn_entry ARGS(( tcpport_t locport,
- ipaddr_t locaddr, tcpport_t remport, ipaddr_t readaddr ));
-static tcp_conn_t *find_empty_conn ARGS(( void ));
-static tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr,
- tcp_hdr_t *tcp_hdr ));
-static tcp_conn_t *new_conn_for_queue ARGS(( tcp_fd_t *tcp_fd ));
-static int maybe_listen ARGS(( ipaddr_t locaddr, tcpport_t locport,
- ipaddr_t remaddr, tcpport_t remport ));
-static int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));
-static void tcp_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void tcp_bufcheck ARGS(( void ));
-#endif
-static void tcp_setup_conn ARGS(( tcp_port_t *tcp_port,
- tcp_conn_t *tcp_conn ));
-static u32_t tcp_rand32 ARGS(( void ));
-
-void tcp_prep()
-{
- tcp_port_table= alloc(tcp_conf_nr * sizeof(tcp_port_table[0]));
-}
-
-void tcp_init()
-{
- int i, j, k, ifno;
- tcp_fd_t *tcp_fd;
- tcp_port_t *tcp_port;
- tcp_conn_t *tcp_conn;
-
- assert (BUF_S >= sizeof(struct nwio_ipopt));
- assert (BUF_S >= sizeof(struct nwio_ipconf));
- assert (BUF_S >= sizeof(struct nwio_tcpconf));
- assert (BUF_S >= IP_MAX_HDR_SIZE + TCP_MAX_HDR_SIZE);
-
- for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
- {
- tcp_fd->tf_flags= TFF_EMPTY;
- }
-
- for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
- tcp_fd++)
- {
- tcp_conn->tc_flags= TCF_EMPTY;
- tcp_conn->tc_busy= 0;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(tcp_buffree);
-#else
- bf_logon(tcp_buffree, tcp_bufcheck);
-#endif
-
- for (i=0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
- {
- tcp_port->tp_ipdev= tcp_conf[i].tc_port;
-
- tcp_port->tp_flags= TPF_EMPTY;
- tcp_port->tp_state= TPS_EMPTY;
- tcp_port->tp_snd_head= NULL;
- tcp_port->tp_snd_tail= NULL;
- ev_init(&tcp_port->tp_snd_event);
- for (j= 0; j<TCP_CONN_HASH_NR; j++)
- {
- for (k= 0; k<4; k++)
- {
- tcp_port->tp_conn_hash[j][k]=
- &tcp_conn_table[0];
- }
- }
-
- ifno= ip_conf[tcp_port->tp_ipdev].ic_ifno;
- sr_add_minor(if2minor(ifno, TCP_DEV_OFF),
- i, tcp_open, tcp_close, tcp_read,
- tcp_write, tcp_ioctl, tcp_cancel, tcp_select);
-
- tcp_main(tcp_port);
- }
- tcp_cancel_f= tcp_cancel;
-}
-
-static void tcp_main(tcp_port)
-tcp_port_t *tcp_port;
-{
- int result, i;
- tcp_conn_t *tcp_conn;
- tcp_fd_t *tcp_fd;
-
- switch (tcp_port->tp_state)
- {
- case TPS_EMPTY:
- tcp_port->tp_state= TPS_SETPROTO;
- tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,
- tcp_port->tp_ipdev, tcp_get_data,
- tcp_put_data, tcp_put_pkt, 0 /* no select_res */);
- if (tcp_port->tp_ipfd < 0)
- {
- tcp_port->tp_state= TPS_ERROR;
- DBLOCK(1, printf("%s, %d: unable to open ip port\n",
- __FILE__, __LINE__));
- return;
- }
-
- result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);
- if (result == NW_SUSPEND)
- tcp_port->tp_flags |= TPF_SUSPEND;
- if (result < 0)
- {
- return;
- }
- if (tcp_port->tp_state != TPS_GETCONF)
- return;
- /* drops through */
- case TPS_GETCONF:
- tcp_port->tp_flags &= ~TPF_SUSPEND;
-
- result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);
- if (result == NW_SUSPEND)
- tcp_port->tp_flags |= TPF_SUSPEND;
- if (result < 0)
- {
- return;
- }
- if (tcp_port->tp_state != TPS_MAIN)
- return;
- /* drops through */
- case TPS_MAIN:
- tcp_port->tp_flags &= ~TPF_SUSPEND;
- tcp_port->tp_pack= 0;
-
- tcp_conn= &tcp_conn_table[tcp_port->tp_ipdev];
- tcp_conn->tc_flags= TCF_INUSE;
- assert(!tcp_conn->tc_busy);
- tcp_conn->tc_locport= 0;
- tcp_conn->tc_locaddr= tcp_port->tp_ipaddr;
- tcp_conn->tc_remport= 0;
- tcp_conn->tc_remaddr= 0;
- tcp_conn->tc_state= TCS_CLOSED;
- tcp_conn->tc_fd= 0;
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_orglisten= FALSE;
- tcp_conn->tc_senddis= 0;
- tcp_conn->tc_ISS= 0;
- tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
- tcp_conn->tc_IRS= 0;
- tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
- tcp_conn->tc_port= tcp_port;
- tcp_conn->tc_rcvd_data= NULL;
- tcp_conn->tc_adv_data= NULL;
- tcp_conn->tc_send_data= 0;
- tcp_conn->tc_remipopt= NULL;
- tcp_conn->tc_tcpopt= NULL;
- tcp_conn->tc_frag2send= 0;
- tcp_conn->tc_tos= TCP_DEF_TOS;
- tcp_conn->tc_ttl= IP_MAX_TTL;
- tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_0wnd_to= 0;
- tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
- tcp_conn->tc_drtt= 0;
- tcp_conn->tc_rtt= TCP_DEF_RTT;
- tcp_conn->tc_max_mtu= tcp_port->tp_mtu;
- tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
- tcp_conn->tc_mtutim= 0;
- tcp_conn->tc_error= NW_OK;
- tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
- tcp_conn->tc_snd_cinc=
- (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
-
- tcp_conn->tc_rt_time= 0;
- tcp_conn->tc_rt_seq= 0;
- tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
-
- for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
- tcp_fd++)
- {
- if (!(tcp_fd->tf_flags & TFF_INUSE))
- continue;
- if (tcp_fd->tf_port != tcp_port)
- continue;
- if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
- {
- tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
- tcp_ioctl(i, tcp_fd->tf_ioreq);
- }
- }
- read_ip_packets(tcp_port);
- return;
-
- default:
- ip_panic(( "unknown state" ));
- break;
- }
-}
-
-static int tcp_select(fd, operations)
-int fd;
-unsigned operations;
-{
- int i;
- unsigned resops;
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- tcp_fd= &tcp_fd_table[fd];
- assert (tcp_fd->tf_flags & TFF_INUSE);
-
- resops= 0;
- if (tcp_fd->tf_flags & TFF_LISTENQ)
- {
- /* Special case for LISTENQ */
- if (operations & SR_SELECT_READ)
- {
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- if (tcp_fd->tf_listenq[i] == NULL)
- continue;
- if (tcp_fd->tf_listenq[i]->tc_connInprogress
- == 0)
- {
- break;
- }
- }
- if (i >= TFL_LISTEN_MAX)
- tcp_fd->tf_flags |= TFF_SEL_READ;
- else
- resops |= SR_SELECT_READ;
- }
- if (operations & SR_SELECT_WRITE)
- {
- /* We can't handles writes. Just return the error
- * when the user tries to write.
- */
- resops |= SR_SELECT_WRITE;
- }
- return resops;
- }
- if (tcp_fd->tf_flags & TFF_CONNECTING)
- {
- /* Special case for CONNECTING */
- if (operations & SR_SELECT_WRITE)
- tcp_fd->tf_flags |= TFF_SEL_WRITE;
- return 0;
- }
- if (operations & SR_SELECT_READ)
- {
- tcp_conn= tcp_fd->tf_conn;
-
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- /* We can't handle reads until a connection has been
- * established. Return the error when the user tries
- * to read.
- */
- resops |= SR_SELECT_READ;
- }
- else if (tcp_conn->tc_state == TCS_CLOSED ||
- tcp_sel_read(tcp_conn))
- {
- resops |= SR_SELECT_READ;
- }
- else if (!(operations & SR_SELECT_POLL))
- tcp_fd->tf_flags |= TFF_SEL_READ;
- }
- if (operations & SR_SELECT_WRITE)
- {
- tcp_conn= tcp_fd->tf_conn;
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- /* We can't handle writes until a connection has been
- * established. Return the error when the user tries
- * to write.
- */
- resops |= SR_SELECT_WRITE;
- }
- else if (tcp_conn->tc_state == TCS_CLOSED ||
- tcp_conn->tc_flags & TCF_FIN_SENT ||
- tcp_sel_write(tcp_conn))
- {
- resops |= SR_SELECT_WRITE;
- }
- else if (!(operations & SR_SELECT_POLL))
- tcp_fd->tf_flags |= TFF_SEL_WRITE;
- }
- if (operations & SR_SELECT_EXCEPTION)
- {
- /* Should add code for exceptions */
- }
- return resops;
-}
-
-static acc_t *tcp_get_data (port, offset, count, for_ioctl)
-int port;
-size_t offset;
-size_t count;
-int for_ioctl;
-{
- tcp_port_t *tcp_port;
- int result;
-
- tcp_port= &tcp_port_table[port];
-
- switch (tcp_port->tp_state)
- {
- case TPS_SETPROTO:
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- {
- tcp_port->tp_state= TPS_ERROR;
- break;
- }
- tcp_port->tp_state= TPS_GETCONF;
- if (tcp_port->tp_flags & TPF_SUSPEND)
- tcp_main(tcp_port);
- return NW_OK;
- }
-assert (!offset);
-assert (count == sizeof(struct nwio_ipopt));
- {
- struct nwio_ipopt *ipopt;
- acc_t *acc;
-
- acc= bf_memreq(sizeof(*ipopt));
- ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
- ipopt->nwio_flags= NWIO_COPY |
- NWIO_EN_LOC | NWIO_DI_BROAD |
- NWIO_REMANY | NWIO_PROTOSPEC |
- NWIO_HDR_O_ANY | NWIO_RWDATALL;
- ipopt->nwio_proto= IPPROTO_TCP;
- return acc;
- }
- case TPS_MAIN:
- assert(tcp_port->tp_flags & TPF_WRITE_IP);
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- {
- if (result == EHOSTUNREACH ||
- result == ENETUNREACH ||
- result == ENETDOWN)
- {
- if (tcp_port->tp_snd_head)
- {
- tcp_notreach(tcp_port->
- tp_snd_head, result);
- }
- }
- else
- {
- ip_warning((
- "ip_write failed with error: %d\n",
- result ));
- }
- }
- assert (tcp_port->tp_pack);
- bf_afree (tcp_port->tp_pack);
- tcp_port->tp_pack= 0;
-
- if (tcp_port->tp_flags & TPF_WRITE_SP)
- {
- tcp_port->tp_flags &= ~(TPF_WRITE_SP|
- TPF_WRITE_IP);
- if (tcp_port->tp_snd_head)
- tcp_port_write(tcp_port);
- }
- else
- tcp_port->tp_flags &= ~TPF_WRITE_IP;
- }
- else
- {
- return bf_cut (tcp_port->tp_pack, offset,
- count);
- }
- break;
- default:
- printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",
- port, offset, count, tcp_port->tp_state);
- break;
- }
- return NW_OK;
-}
-
-static int tcp_put_data (fd, offset, data, for_ioctl)
-int fd;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- tcp_port_t *tcp_port;
- int result;
-
- tcp_port= &tcp_port_table[fd];
-
- switch (tcp_port->tp_state)
- {
- case TPS_GETCONF:
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- tcp_port->tp_state= TPS_ERROR;
- return NW_OK;
- }
- tcp_port->tp_state= TPS_MAIN;
- if (tcp_port->tp_flags & TPF_SUSPEND)
- tcp_main(tcp_port);
- }
- else
- {
- struct nwio_ipconf *ipconf;
-
- data= bf_packIffLess(data, sizeof(*ipconf));
- ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
-assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
- tcp_port->tp_ipaddr= ipconf->nwic_ipaddr;
- tcp_port->tp_subnetmask= ipconf->nwic_netmask;
- tcp_port->tp_mtu= ipconf->nwic_mtu;
- bf_afree(data);
- }
- break;
- case TPS_MAIN:
- assert(tcp_port->tp_flags & TPF_READ_IP);
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- ip_panic(( "ip_read() failed" ));
-
- if (tcp_port->tp_flags & TPF_READ_SP)
- {
- tcp_port->tp_flags &= ~(TPF_READ_SP|
- TPF_READ_IP);
- read_ip_packets(tcp_port);
- }
- else
- tcp_port->tp_flags &= ~TPF_READ_IP;
- }
- else
- {
- assert(!offset);
- /* this is an invalid assertion but ip sends
- * only whole datagrams up */
- tcp_put_pkt(fd, data, bf_bufsize(data));
- }
- break;
- default:
- printf(
- "tcp_put_data(%d, 0x%x, %p) called but tp_state= 0x%x\n",
- fd, offset, data, tcp_port->tp_state);
- break;
- }
- return NW_OK;
-}
-
-/*
-tcp_put_pkt
-*/
-
-static void tcp_put_pkt(fd, data, datalen)
-int fd;
-acc_t *data;
-size_t datalen;
-{
- tcp_port_t *tcp_port;
- tcp_conn_t *tcp_conn, **conn_p;
- ip_hdr_t *ip_hdr;
- tcp_hdr_t *tcp_hdr;
- acc_t *ip_pack, *tcp_pack;
- size_t ip_datalen, tcp_datalen, ip_hdr_len, tcp_hdr_len;
- u16_t sum, mtu;
- u32_t bits;
- int i, hash;
- ipaddr_t srcaddr, dstaddr, ipaddr, mask;
- tcpport_t srcport, dstport;
-
- tcp_port= &tcp_port_table[fd];
-
- /* Extract the IP header. */
- ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- ip_datalen= datalen - ip_hdr_len;
- if (ip_datalen == 0)
- {
- if (ip_hdr->ih_proto == 0)
- {
- /* IP layer reports new IP address */
- ipaddr= ip_hdr->ih_src;
- mask= ip_hdr->ih_dst;
- mtu= ntohs(ip_hdr->ih_length);
- tcp_port->tp_ipaddr= ipaddr;
- tcp_port->tp_subnetmask= mask;
- tcp_port->tp_mtu= mtu;
- DBLOCK(1, printf("tcp_put_pkt: using address ");
- writeIpAddr(ipaddr);
- printf(", netmask ");
- writeIpAddr(mask);
- printf(", mtu %u\n", mtu));
- for (i= 0, tcp_conn= tcp_conn_table+i;
- i<TCP_CONN_NR; i++, tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (tcp_conn->tc_port != tcp_port)
- continue;
- tcp_conn->tc_locaddr= ipaddr;
- }
- }
- else
- DBLOCK(1, printf("tcp_put_pkt: no TCP header\n"));
- bf_afree(data);
- return;
- }
- data->acc_linkC++;
- ip_pack= data;
- ip_pack= bf_align(ip_pack, ip_hdr_len, 4);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
- data= bf_delhead(data, ip_hdr_len);
-
- /* Compute the checksum */
- sum= tcp_pack_oneCsum(ip_hdr, data);
-
- /* Extract the TCP header */
- if (ip_datalen < TCP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("truncated TCP header\n"));
- bf_afree(ip_pack);
- bf_afree(data);
- return;
- }
- data= bf_packIffLess(data, TCP_MIN_HDR_SIZE);
- tcp_hdr= (tcp_hdr_t *)ptr2acc_data(data);
- tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
- /* actualy (>> 4) << 2 */
- if (ip_datalen < tcp_hdr_len || tcp_hdr_len < TCP_MIN_HDR_SIZE)
- {
- if (tcp_hdr_len < TCP_MIN_HDR_SIZE)
- {
- DBLOCK(1, printf("strange tcp header length %d\n",
- tcp_hdr_len));
- }
- else
- {
- DBLOCK(1, printf("truncated TCP header\n"));
- }
- bf_afree(ip_pack);
- bf_afree(data);
- return;
- }
- data->acc_linkC++;
- tcp_pack= data;
- tcp_pack= bf_align(tcp_pack, tcp_hdr_len, 4);
- tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);
- if (ip_datalen == tcp_hdr_len)
- {
- bf_afree(data);
- data= NULL;
- }
- else
- data= bf_delhead(data, tcp_hdr_len);
- tcp_datalen= ip_datalen-tcp_hdr_len;
-
- if ((u16_t)~sum)
- {
- DBLOCK(1, printf("checksum error in tcp packet\n");
- printf("tcp_pack_oneCsum(...)= 0x%x length= %d\n",
- (u16_t)~sum, tcp_datalen);
- printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src);
- printf("\n"));
- bf_afree(ip_pack);
- bf_afree(tcp_pack);
- bf_afree(data);
- return;
- }
-
- srcaddr= ip_hdr->ih_src;
- dstaddr= ip_hdr->ih_dst;
- srcport= tcp_hdr->th_srcport;
- dstport= tcp_hdr->th_dstport;
- bits= srcaddr ^ dstaddr ^ srcport ^ dstport;
- bits= (bits >> 16) ^ bits;
- bits= (bits >> 8) ^ bits;
- hash= ((bits >> TCP_CONN_HASH_SHIFT) ^ bits) & (TCP_CONN_HASH_NR-1);
- conn_p= tcp_port->tp_conn_hash[hash];
- if (conn_p[0]->tc_locport == dstport &&
- conn_p[0]->tc_remport == srcport &&
- conn_p[0]->tc_remaddr == srcaddr &&
- conn_p[0]->tc_locaddr == dstaddr)
- {
- tcp_conn= conn_p[0];
- }
- else if (conn_p[1]->tc_locport == dstport &&
- conn_p[1]->tc_remport == srcport &&
- conn_p[1]->tc_remaddr == srcaddr &&
- conn_p[1]->tc_locaddr == dstaddr)
- {
- tcp_conn= conn_p[1];
- conn_p[1]= conn_p[0];
- conn_p[0]= tcp_conn;
- }
- else if (conn_p[2]->tc_locport == dstport &&
- conn_p[2]->tc_remport == srcport &&
- conn_p[2]->tc_remaddr == srcaddr &&
- conn_p[2]->tc_locaddr == dstaddr)
- {
- tcp_conn= conn_p[2];
- conn_p[2]= conn_p[1];
- conn_p[1]= conn_p[0];
- conn_p[0]= tcp_conn;
- }
- else if (conn_p[3]->tc_locport == dstport &&
- conn_p[3]->tc_remport == srcport &&
- conn_p[3]->tc_remaddr == srcaddr &&
- conn_p[3]->tc_locaddr == dstaddr)
- {
- tcp_conn= conn_p[3];
- conn_p[3]= conn_p[2];
- conn_p[2]= conn_p[1];
- conn_p[1]= conn_p[0];
- conn_p[0]= tcp_conn;
- }
- else
- tcp_conn= NULL;
- if ((tcp_conn != NULL && tcp_conn->tc_state == TCS_CLOSED) ||
- (tcp_hdr->th_flags & THF_SYN))
- {
- tcp_conn= NULL;
- }
-
- if (tcp_conn == NULL)
- {
- tcp_conn= find_best_conn(ip_hdr, tcp_hdr);
- if (!tcp_conn)
- {
- /* listen backlog hack */
- bf_afree(ip_pack);
- bf_afree(tcp_pack);
- bf_afree(data);
- return;
- }
- if (tcp_conn->tc_state != TCS_CLOSED)
- {
- conn_p[3]= conn_p[2];
- conn_p[2]= conn_p[1];
- conn_p[1]= conn_p[0];
- conn_p[0]= tcp_conn;
- }
- }
- assert(tcp_conn->tc_busy == 0);
- tcp_conn->tc_busy++;
- tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, data, tcp_datalen);
- tcp_conn->tc_busy--;
- bf_afree(ip_pack);
- bf_afree(tcp_pack);
-}
-
-
-int tcp_open (port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port;
-int srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- int i, j;
-
- tcp_fd_t *tcp_fd;
-
- for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE);
- i++);
- if (i>=TCP_FD_NR)
- {
- return EAGAIN;
- }
-
- tcp_fd= &tcp_fd_table[i];
-
- tcp_fd->tf_flags= TFF_INUSE;
- tcp_fd->tf_flags |= TFF_PUSH_DATA;
-
- tcp_fd->tf_port= &tcp_port_table[port];
- tcp_fd->tf_srfd= srfd;
- tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_CONF;
- tcp_fd->tf_tcpconf.nwtc_remaddr= 0;
- tcp_fd->tf_tcpconf.nwtc_remport= 0;
- tcp_fd->tf_tcpopt.nwto_flags= TCP_DEF_OPT;
- tcp_fd->tf_get_userdata= get_userdata;
- tcp_fd->tf_put_userdata= put_userdata;
- tcp_fd->tf_select_res= select_res;
- tcp_fd->tf_conn= 0;
- tcp_fd->tf_error= 0;
- for (j= 0; j<TFL_LISTEN_MAX; j++)
- tcp_fd->tf_listenq[j]= NULL;
- return i;
-}
-
-/*
-tcp_ioctl
-*/
-int tcp_ioctl (fd, req)
-int fd;
-ioreq_t req;
-{
- tcp_fd_t *tcp_fd;
- tcp_port_t *tcp_port;
- tcp_conn_t *tcp_conn;
- nwio_tcpconf_t *io_tcp_conf;
- nwio_tcpopt_t *tcp_opt;
- tcp_cookie_t *cookiep;
- acc_t *acc, *conf_acc, *opt_acc;
- int result, *bytesp;
- u8_t rndbits[RAND256_BUFSIZE];
-
- tcp_fd= &tcp_fd_table[fd];
-
- assert (tcp_fd->tf_flags & TFF_INUSE);
-
- tcp_port= tcp_fd->tf_port;
- tcp_fd->tf_flags |= TFF_IOCTL_IP;
- tcp_fd->tf_ioreq= req;
-
- if (tcp_port->tp_state != TPS_MAIN)
- {
- tcp_fd->tf_flags |= TFF_IOC_INIT_SP;
- return NW_SUSPEND;
- }
-
- switch (req)
- {
- case NWIOSTCPCONF:
- if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
- (tcp_fd->tf_flags & TFF_CONNECTING) ||
- (tcp_fd->tf_flags & TFF_LISTENQ))
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EISCONN, TRUE);
- result= NW_OK;
- break;
- }
- result= tcp_setconf(tcp_fd);
- break;
- case NWIOGTCPCONF:
- conf_acc= bf_memreq(sizeof(*io_tcp_conf));
-assert (conf_acc->acc_length == sizeof(*io_tcp_conf));
- io_tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);
-
- *io_tcp_conf= tcp_fd->tf_tcpconf;
- if (tcp_fd->tf_flags & TFF_CONNECTED)
- {
- tcp_conn= tcp_fd->tf_conn;
- io_tcp_conf->nwtc_locport= tcp_conn->tc_locport;
- io_tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;
- io_tcp_conf->nwtc_remport= tcp_conn->tc_remport;
- }
- io_tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;
- result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
- 0, conf_acc, TRUE);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_put(tcp_fd, result, TRUE);
- result= NW_OK;
- break;
- case NWIOSTCPOPT:
- result= tcp_setopt(tcp_fd);
- break;
- case NWIOGTCPOPT:
- opt_acc= bf_memreq(sizeof(*tcp_opt));
- assert (opt_acc->acc_length == sizeof(*tcp_opt));
- tcp_opt= (nwio_tcpopt_t *)ptr2acc_data(opt_acc);
-
- *tcp_opt= tcp_fd->tf_tcpopt;
- result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
- 0, opt_acc, TRUE);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_put(tcp_fd, result, TRUE);
- result= NW_OK;
- break;
- case NWIOTCPCONN:
- if (tcp_fd->tf_flags & TFF_CONNECTING)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EALREADY, TRUE);
- result= NW_OK;
- break;
- }
- if (tcp_fd->tf_flags & TFF_CONNECTED)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EISCONN, TRUE);
- result= NW_OK;
- break;
- }
- result= tcp_connect(tcp_fd);
- if (result == NW_OK)
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- break;
- case NWIOTCPLISTEN:
- case NWIOTCPLISTENQ:
- if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
- (tcp_fd->tf_flags & TFF_LISTENQ) ||
- (tcp_fd->tf_flags & TFF_CONNECTING))
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EISCONN, TRUE);
- result= NW_OK;
- break;
- }
- result= tcp_listen(tcp_fd, (req == NWIOTCPLISTENQ));
- break;
- case NWIOTCPSHUTDOWN:
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, ENOTCONN, TRUE);
- result= NW_OK;
- break;
- }
- tcp_fd->tf_flags |= TFF_IOCTL_IP;
- tcp_fd->tf_ioreq= req;
- tcp_conn= tcp_fd->tf_conn;
-
- tcp_conn->tc_busy++;
- tcp_fd_write(tcp_conn);
- tcp_conn->tc_busy--;
- tcp_conn_write(tcp_conn, 0);
- if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
- result= NW_OK;
- else
- result= NW_SUSPEND;
- break;
- case NWIOTCPPUSH:
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, ENOTCONN, TRUE);
- result= NW_OK;
- break;
- }
- tcp_conn= tcp_fd->tf_conn;
- tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
- tcp_conn->tc_flags &= ~TCF_NO_PUSH;
- tcp_conn->tc_flags |= TCF_PUSH_NOW;
-
- /* Start the timer (if necessary) */
- if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
- tcp_set_send_timer(tcp_conn);
-
- tcp_conn_write(tcp_conn, 0);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, NW_OK, TRUE);
- result= NW_OK;
- break;
- case NWIOGTCPCOOKIE:
- if (!(tcp_fd->tf_flags & TFF_COOKIE))
- {
- tcp_fd->tf_cookie.tc_ref= fd;
- rand256(rndbits);
- assert(sizeof(tcp_fd->tf_cookie.tc_secret) <=
- RAND256_BUFSIZE);
- memcpy(tcp_fd->tf_cookie.tc_secret,
- rndbits, sizeof(tcp_fd->tf_cookie.tc_secret));
- tcp_fd->tf_flags |= TFF_COOKIE;
- }
- acc= bf_memreq(sizeof(*cookiep));
- cookiep= (tcp_cookie_t *)ptr2acc_data(acc);
-
- *cookiep= tcp_fd->tf_cookie;
- result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
- 0, acc, TRUE);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_put(tcp_fd, result, TRUE);
- result= NW_OK;
- break;
- case NWIOTCPACCEPTTO:
- result= tcp_acceptto(tcp_fd);
- break;
- case FIONREAD:
- acc= bf_memreq(sizeof(*bytesp));
- bytesp= (int *)ptr2acc_data(acc);
- tcp_bytesavailable(tcp_fd, bytesp);
- result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
- 0, acc, TRUE);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_put(tcp_fd, result, TRUE);
- result= NW_OK;
- break;
-
- case NWIOTCPGERROR:
- acc= bf_memreq(sizeof(*bytesp));
- bytesp= (int *)ptr2acc_data(acc);
- *bytesp= -tcp_fd->tf_error; /* Errors are positive in
- * user space.
- */
- tcp_fd->tf_error= 0;
- result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
- 0, acc, TRUE);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_put(tcp_fd, result, TRUE);
- result= NW_OK;
- break;
-
- default:
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, ENOTTY, TRUE);
- result= NW_OK;
- break;
- }
- return result;
-}
-
-
-/*
-tcp_setconf
-*/
-
-static int tcp_setconf(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- nwio_tcpconf_t *tcpconf;
- nwio_tcpconf_t oldconf, newconf;
- acc_t *data;
- tcp_fd_t *fd_ptr;
- unsigned int new_en_flags, new_di_flags,
- old_en_flags, old_di_flags, all_flags, flags;
- int i;
-
- data= (*tcp_fd->tf_get_userdata)
- (tcp_fd->tf_srfd, 0,
- sizeof(nwio_tcpconf_t), TRUE);
-
- if (!data)
- return EFAULT;
-
- data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));
-assert (data->acc_length == sizeof(nwio_tcpconf_t));
-
- tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);
- oldconf= tcp_fd->tf_tcpconf;
- newconf= *tcpconf;
-
- old_en_flags= oldconf.nwtc_flags & 0xffff;
- old_di_flags= (oldconf.nwtc_flags >> 16) &
- 0xffff;
- new_en_flags= newconf.nwtc_flags & 0xffff;
- new_di_flags= (newconf.nwtc_flags >> 16) &
- 0xffff;
- if (new_en_flags & new_di_flags)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- }
-
- /* NWTC_ACC_MASK */
- if (new_di_flags & NWTC_ACC_MASK)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- /* access modes can't be disabled */
- }
-
- if (!(new_en_flags & NWTC_ACC_MASK))
- new_en_flags |= (old_en_flags & NWTC_ACC_MASK);
-
- /* NWTC_LOCPORT_MASK */
- if (new_di_flags & NWTC_LOCPORT_MASK)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- /* the loc ports can't be disabled */
- }
- if (!(new_en_flags & NWTC_LOCPORT_MASK))
- {
- new_en_flags |= (old_en_flags &
- NWTC_LOCPORT_MASK);
- newconf.nwtc_locport= oldconf.nwtc_locport;
- }
- else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)
- {
- newconf.nwtc_locport= find_unused_port(tcp_fd-
- tcp_fd_table);
- }
- else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
- {
- if (!newconf.nwtc_locport)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- }
- }
-
- /* NWTC_REMADDR_MASK */
- if (!((new_en_flags | new_di_flags) &
- NWTC_REMADDR_MASK))
- {
- new_en_flags |= (old_en_flags &
- NWTC_REMADDR_MASK);
- new_di_flags |= (old_di_flags &
- NWTC_REMADDR_MASK);
- newconf.nwtc_remaddr= oldconf.nwtc_remaddr;
- }
- else if (new_en_flags & NWTC_SET_RA)
- {
- if (!newconf.nwtc_remaddr)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- }
- }
- else
- {
-assert (new_di_flags & NWTC_REMADDR_MASK);
- newconf.nwtc_remaddr= 0;
- }
-
- /* NWTC_REMPORT_MASK */
- if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))
- {
- new_en_flags |= (old_en_flags &
- NWTC_REMPORT_MASK);
- new_di_flags |= (old_di_flags &
- NWTC_REMPORT_MASK);
- newconf.nwtc_remport=
- oldconf.nwtc_remport;
- }
- else if (new_en_flags & NWTC_SET_RP)
- {
- if (!newconf.nwtc_remport)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- bf_afree(data);
- return NW_OK;
- }
- }
- else
- {
-assert (new_di_flags & NWTC_REMPORT_MASK);
- newconf.nwtc_remport= 0;
- }
-
- newconf.nwtc_flags= ((unsigned long)new_di_flags
- << 16) | new_en_flags;
- all_flags= new_en_flags | new_di_flags;
-
- /* check the access modes */
- if ((all_flags & NWTC_LOCPORT_MASK) != NWTC_LP_UNSET)
- {
- for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)
- {
- if (fd_ptr == tcp_fd)
- continue;
- if (!(fd_ptr->tf_flags & TFF_INUSE))
- continue;
- if (fd_ptr->tf_port != tcp_fd->tf_port)
- continue;
- flags= fd_ptr->tf_tcpconf.nwtc_flags;
- if ((flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
- continue;
- if (fd_ptr->tf_tcpconf.nwtc_locport !=
- newconf.nwtc_locport)
- continue;
- if ((flags & NWTC_ACC_MASK) != (all_flags &
- NWTC_ACC_MASK) ||
- (all_flags & NWTC_ACC_MASK) == NWTC_EXCL)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EADDRINUSE, TRUE);
- bf_afree(data);
- return NW_OK;
- }
- }
- }
-
- tcp_fd->tf_tcpconf= newconf;
-
- if ((all_flags & NWTC_ACC_MASK) &&
- ((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||
- (all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&
- (all_flags & NWTC_REMADDR_MASK) &&
- (all_flags & NWTC_REMPORT_MASK))
- tcp_fd->tf_flags |= TFF_CONF_SET;
- else
- {
- tcp_fd->tf_flags &= ~TFF_CONF_SET;
- }
- bf_afree(data);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, NW_OK, TRUE);
- return NW_OK;
-}
-
-
-/*
-tcp_setopt
-*/
-
-static int tcp_setopt(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- nwio_tcpopt_t *tcpopt;
- nwio_tcpopt_t oldopt, newopt;
- acc_t *data;
- unsigned int new_en_flags, new_di_flags,
- old_en_flags, old_di_flags;
-
- data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
- sizeof(nwio_tcpopt_t), TRUE);
-
- if (!data)
- return EFAULT;
-
- data= bf_packIffLess(data, sizeof(nwio_tcpopt_t));
-assert (data->acc_length == sizeof(nwio_tcpopt_t));
-
- tcpopt= (nwio_tcpopt_t *)ptr2acc_data(data);
- oldopt= tcp_fd->tf_tcpopt;
- newopt= *tcpopt;
-
- old_en_flags= oldopt.nwto_flags & 0xffff;
- old_di_flags= (oldopt.nwto_flags >> 16) & 0xffff;
- new_en_flags= newopt.nwto_flags & 0xffff;
- new_di_flags= (newopt.nwto_flags >> 16) & 0xffff;
- if (new_en_flags & new_di_flags)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- /* NWTO_SND_URG_MASK */
- if (!((new_en_flags | new_di_flags) & NWTO_SND_URG_MASK))
- {
- new_en_flags |= (old_en_flags & NWTO_SND_URG_MASK);
- new_di_flags |= (old_di_flags & NWTO_SND_URG_MASK);
- }
-
- /* NWTO_RCV_URG_MASK */
- if (!((new_en_flags | new_di_flags) & NWTO_RCV_URG_MASK))
- {
- new_en_flags |= (old_en_flags & NWTO_RCV_URG_MASK);
- new_di_flags |= (old_di_flags & NWTO_RCV_URG_MASK);
- }
-
- /* NWTO_BSD_URG_MASK */
- if (!((new_en_flags | new_di_flags) & NWTO_BSD_URG_MASK))
- {
- new_en_flags |= (old_en_flags & NWTO_BSD_URG_MASK);
- new_di_flags |= (old_di_flags & NWTO_BSD_URG_MASK);
- }
- else
- {
- if (tcp_fd->tf_conn == NULL)
- {
- bf_afree(data);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EINVAL, TRUE);
- return NW_OK;
- }
- }
-
- /* NWTO_DEL_RST_MASK */
- if (!((new_en_flags | new_di_flags) & NWTO_DEL_RST_MASK))
- {
- new_en_flags |= (old_en_flags & NWTO_DEL_RST_MASK);
- new_di_flags |= (old_di_flags & NWTO_DEL_RST_MASK);
- }
-
- /* NWTO_BULK_MASK */
- if (!((new_en_flags | new_di_flags) & NWTO_BULK_MASK))
- {
- new_en_flags |= (old_en_flags & NWTO_BULK_MASK);
- new_di_flags |= (old_di_flags & NWTO_BULK_MASK);
- }
-
- newopt.nwto_flags= ((unsigned long)new_di_flags << 16) |
- new_en_flags;
- tcp_fd->tf_tcpopt= newopt;
- if (newopt.nwto_flags & NWTO_SND_URG)
- tcp_fd->tf_flags |= TFF_WR_URG;
- else
- tcp_fd->tf_flags &= ~TFF_WR_URG;
-
- if (newopt.nwto_flags & NWTO_RCV_URG)
- tcp_fd->tf_flags |= TFF_RECV_URG;
- else
- tcp_fd->tf_flags &= ~TFF_RECV_URG;
-
- if (tcp_fd->tf_conn)
- {
- if (newopt.nwto_flags & NWTO_BSD_URG)
- tcp_fd->tf_conn->tc_flags |= TCF_BSD_URG;
- else
- tcp_fd->tf_conn->tc_flags &= ~TCF_BSD_URG;
- }
-
- if (newopt.nwto_flags & NWTO_DEL_RST)
- tcp_fd->tf_flags |= TFF_DEL_RST;
- else
- tcp_fd->tf_flags &= ~TFF_DEL_RST;
-
- if (newopt.nwto_flags & NWTO_BULK)
- tcp_fd->tf_flags &= ~TFF_PUSH_DATA;
- else
- tcp_fd->tf_flags |= TFF_PUSH_DATA;
-
- bf_afree(data);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, NW_OK, TRUE);
- return NW_OK;
-}
-
-
-static tcpport_t find_unused_port(int fd)
-{
- tcpport_t port, nw_port;
-
- for (port= 0x8000+fd; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)
- {
- nw_port= htons(port);
- if (is_unused_port(nw_port))
- return nw_port;
- }
- for (port= 0x8000; port < 0xffff; port++)
- {
- nw_port= htons(port);
- if (is_unused_port(nw_port))
- return nw_port;
- }
- ip_panic(( "unable to find unused port (shouldn't occur)" ));
- return 0;
-}
-
-static int is_unused_port(tcpport_t port)
-{
- int i;
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
- tcp_fd++)
- {
- if (!(tcp_fd->tf_flags & TFF_CONF_SET))
- continue;
- if (tcp_fd->tf_tcpconf.nwtc_locport == port)
- return FALSE;
- }
- for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
- i<TCP_CONN_NR; i++, tcp_conn++)
- /* the first tcp_conf_nr ports are special */
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (tcp_conn->tc_locport == port)
- return FALSE;
- }
- return TRUE;
-}
-
-static int reply_thr_put(tcp_fd, reply, for_ioctl)
-tcp_fd_t *tcp_fd;
-int reply;
-int for_ioctl;
-{
- assert (tcp_fd);
-
- return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,
- (acc_t *)0, for_ioctl);
-}
-
-static void reply_thr_get(tcp_fd, reply, for_ioctl)
-tcp_fd_t *tcp_fd;
-int reply;
-int for_ioctl;
-{
- acc_t *result;
-
- result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,
- (size_t)0, for_ioctl);
- assert (!result);
-}
-
-int tcp_su4listen(tcp_fd, tcp_conn, do_listenq)
-tcp_fd_t *tcp_fd;
-tcp_conn_t *tcp_conn;
-int do_listenq;
-{
- tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
- tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
- if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)
- tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
- else
- tcp_conn->tc_remport= 0;
- if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)
- tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
- else
- tcp_conn->tc_remaddr= 0;
-
- tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
- tcp_conn->tc_fd= tcp_fd;
- tcp_conn->tc_connInprogress= 1;
- tcp_conn->tc_orglisten= TRUE;
- tcp_conn->tc_state= TCS_LISTEN;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_LISTEN;
- if (do_listenq)
- {
- tcp_fd->tf_flags |= TFF_LISTENQ;
- tcp_reply_ioctl(tcp_fd, NW_OK);
- return NW_OK;
- }
- return NW_SUSPEND;
-}
-
-/*
-find_empty_conn
-
-This function returns a connection that is not inuse.
-This includes connections that are never used, and connections without a
-user that are not used for a while.
-*/
-
-static tcp_conn_t *find_empty_conn()
-{
- int i;
- tcp_conn_t *tcp_conn;
-
- for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i;
- i<TCP_CONN_NR; i++, tcp_conn++)
- /* the first tcp_conf_nr connections are reserved for
- * RSTs
- */
- {
- if (tcp_conn->tc_flags == TCF_EMPTY)
- {
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_fd= NULL;
- return tcp_conn;
- }
- if (tcp_conn->tc_fd)
- continue;
- if (tcp_conn->tc_senddis > get_time())
- continue;
- if (tcp_conn->tc_state != TCS_CLOSED)
- {
- tcp_close_connection (tcp_conn, ENOCONN);
- }
- tcp_conn->tc_flags= 0;
- return tcp_conn;
- }
- return NULL;
-}
-
-
-/*
-find_conn_entry
-
-This function return a connection matching locport, locaddr, remport, remaddr.
-If no such connection exists NULL is returned.
-If a connection exists without mainuser it is closed.
-*/
-
-static tcp_conn_t *find_conn_entry(
- tcpport_t locport,
- ipaddr_t locaddr,
- tcpport_t remport,
- ipaddr_t remaddr
-)
-{
- tcp_conn_t *tcp_conn;
- int i, state;
-
- assert(remport);
- assert(remaddr);
- for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;
- i++, tcp_conn++)
- /* the first tcp_conf_nr connections are reserved for
- RSTs */
- {
- if (tcp_conn->tc_flags == TCF_EMPTY)
- continue;
- if (tcp_conn->tc_locport != locport ||
- tcp_conn->tc_locaddr != locaddr ||
- tcp_conn->tc_remport != remport ||
- tcp_conn->tc_remaddr != remaddr)
- continue;
- if (tcp_conn->tc_fd)
- return tcp_conn;
- state= tcp_conn->tc_state;
- if (state != TCS_CLOSED)
- {
- tcp_close_connection(tcp_conn, ENOCONN);
- }
- return tcp_conn;
- }
- return NULL;
-}
-
-static void read_ip_packets(tcp_port)
-tcp_port_t *tcp_port;
-{
- int result;
-
- do
- {
- tcp_port->tp_flags |= TPF_READ_IP;
- result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);
- if (result == NW_SUSPEND)
- {
- tcp_port->tp_flags |= TPF_READ_SP;
- return;
- }
- assert(result == NW_OK);
- tcp_port->tp_flags &= ~TPF_READ_IP;
- } while(!(tcp_port->tp_flags & TPF_READ_IP));
-}
-
-/*
-find_best_conn
-*/
-
-static tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)
-ip_hdr_t *ip_hdr;
-tcp_hdr_t *tcp_hdr;
-{
-
- int best_level, new_level;
- tcp_conn_t *best_conn, *listen_conn, *tcp_conn;
- tcp_fd_t *tcp_fd;
- int i;
- ipaddr_t locaddr;
- ipaddr_t remaddr;
- tcpport_t locport;
- tcpport_t remport;
-
- locaddr= ip_hdr->ih_dst;
- remaddr= ip_hdr->ih_src;
- locport= tcp_hdr->th_dstport;
- remport= tcp_hdr->th_srcport;
- if (!remport) /* This can interfere with a listen, so we reject it
- * by clearing the requested port
- */
- locport= 0;
-
- best_level= 0;
- best_conn= NULL;
- listen_conn= NULL;
- for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
- i<TCP_CONN_NR; i++, tcp_conn++)
- /* the first tcp_conf_nr connections are reserved for
- RSTs */
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- /* First fast check for open connections. */
- if (tcp_conn->tc_locaddr == locaddr &&
- tcp_conn->tc_locport == locport &&
- tcp_conn->tc_remport == remport &&
- tcp_conn->tc_remaddr == remaddr &&
- tcp_conn->tc_fd)
- {
- return tcp_conn;
- }
-
- /* Now check for listens and abandoned connections. */
- if (tcp_conn->tc_locaddr != locaddr)
- {
- continue;
- }
- new_level= 0;
- if (tcp_conn->tc_locport)
- {
- if (tcp_conn->tc_locport != locport)
- {
- continue;
- }
- new_level += 4;
- }
- if (tcp_conn->tc_remport)
- {
- if (tcp_conn->tc_remport != remport)
- {
- continue;
- }
- new_level += 1;
- }
- if (tcp_conn->tc_remaddr)
- {
- if (tcp_conn->tc_remaddr != remaddr)
- {
- continue;
- }
- new_level += 2;
- }
- if (new_level<best_level)
- continue;
- if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)
- continue;
- if (new_level == 7)
- /* We found an abandoned connection */
- {
- assert(!tcp_conn->tc_fd);
- if (best_conn && tcp_Lmod4G(tcp_conn->tc_ISS,
- best_conn->tc_ISS))
- {
- continue;
- }
- best_conn= tcp_conn;
- continue;
- }
- if (!(tcp_hdr->th_flags & THF_SYN))
- continue;
- best_level= new_level;
- listen_conn= tcp_conn;
- assert(listen_conn->tc_fd != NULL);
- }
-
- if (listen_conn && listen_conn->tc_fd->tf_flags & TFF_LISTENQ &&
- listen_conn->tc_fd->tf_conn == listen_conn)
- {
- /* Special processing for listen queues. Only accept the
- * connection if there is empty space in the queue and
- * there are empty connections as well.
- */
- listen_conn= new_conn_for_queue(listen_conn->tc_fd);
-
- if (listen_conn)
- return listen_conn;
- }
-
- if (!best_conn && !listen_conn)
- {
- if ((tcp_hdr->th_flags & THF_SYN) &&
- maybe_listen(locaddr, locport, remaddr, remport))
- {
- /* Quick hack to implement listen back logs:
- * if a SYN arrives and there is no listen waiting
- * for that packet, then no reply is sent.
- */
- return NULL;
- }
-
- for (i=0, tcp_conn= tcp_conn_table; i<tcp_conf_nr;
- i++, tcp_conn++)
- {
- /* find valid port to send RST */
- if ((tcp_conn->tc_flags & TCF_INUSE) &&
- tcp_conn->tc_locaddr==locaddr)
- {
- break;
- }
- }
- assert (tcp_conn);
- assert (tcp_conn->tc_state == TCS_CLOSED);
-
- tcp_conn->tc_locport= locport;
- tcp_conn->tc_locaddr= locaddr;
- tcp_conn->tc_remport= remport;
- tcp_conn->tc_remaddr= remaddr;
- assert (!tcp_conn->tc_fd);
- return tcp_conn;
- }
-
- if (best_conn)
- {
- if (!listen_conn)
- {
- assert(!best_conn->tc_fd);
- return best_conn;
- }
-
- assert(listen_conn->tc_connInprogress);
- tcp_fd= listen_conn->tc_fd;
- assert(tcp_fd);
- assert((tcp_fd->tf_flags & TFF_LISTENQ) ||
- tcp_fd->tf_conn == listen_conn);
-
- if (best_conn->tc_state != TCS_CLOSED)
- tcp_close_connection(best_conn, ENOCONN);
-
- listen_conn->tc_ISS= best_conn->tc_ISS;
- if (best_conn->tc_senddis > listen_conn->tc_senddis)
- listen_conn->tc_senddis= best_conn->tc_senddis;
- return listen_conn;
- }
- assert (listen_conn);
- return listen_conn;
-}
-
-/*
-new_conn_for_queue
-*/
-static tcp_conn_t *new_conn_for_queue(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- int i;
- tcp_conn_t *tcp_conn;
-
- assert(tcp_fd->tf_flags & TFF_LISTENQ);
-
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- if (tcp_fd->tf_listenq[i] == NULL)
- break;
- }
- if (i >= TFL_LISTEN_MAX)
- return NULL;
-
- tcp_conn= find_empty_conn();
- if (!tcp_conn)
- return NULL;
- tcp_fd->tf_listenq[i]= tcp_conn;
- (void)tcp_su4listen(tcp_fd, tcp_conn, 0 /* !do_listenq */);
- return tcp_conn;
-}
-
-/*
-maybe_listen
-*/
-static int maybe_listen(
- ipaddr_t locaddr,
- tcpport_t locport,
- ipaddr_t remaddr,
- tcpport_t remport
-)
-{
- int i;
- tcp_conn_t *tcp_conn;
- tcp_fd_t *fd;
-
- for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
- i<TCP_CONN_NR; i++, tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
-
- if (tcp_conn->tc_locaddr != locaddr)
- {
- continue;
- }
- if (tcp_conn->tc_locport != locport )
- {
- continue;
- }
- if (!tcp_conn->tc_orglisten)
- continue;
- fd= tcp_conn->tc_fd;
- if (!fd)
- continue;
- if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP) &&
- tcp_conn->tc_remport != remport)
- {
- continue;
- }
- if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA) &&
- tcp_conn->tc_remaddr != remaddr)
- {
- continue;
- }
- if (!(fd->tf_flags & TFF_DEL_RST))
- continue;
- return 1;
-
- }
- return 0;
-}
-
-
-void tcp_reply_ioctl(tcp_fd, reply)
-tcp_fd_t *tcp_fd;
-int reply;
-{
- assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
- assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN ||
- tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
- tcp_fd->tf_ioreq == NWIOTCPLISTENQ ||
- tcp_fd->tf_ioreq == NWIOTCPACCEPTTO ||
- tcp_fd->tf_ioreq == NWIOTCPCONN);
-
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, reply, TRUE);
-}
-
-void tcp_reply_write(tcp_fd, reply)
-tcp_fd_t *tcp_fd;
-size_t reply;
-{
- assert (tcp_fd->tf_flags & TFF_WRITE_IP);
-
- tcp_fd->tf_flags &= ~TFF_WRITE_IP;
- reply_thr_get (tcp_fd, reply, FALSE);
-}
-
-void tcp_reply_read(tcp_fd, reply)
-tcp_fd_t *tcp_fd;
-size_t reply;
-{
- assert (tcp_fd->tf_flags & TFF_READ_IP);
-
- tcp_fd->tf_flags &= ~TFF_READ_IP;
- reply_thr_put (tcp_fd, reply, FALSE);
-}
-
-int tcp_write(fd, count)
-int fd;
-size_t count;
-{
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- tcp_fd= &tcp_fd_table[fd];
-
- assert (tcp_fd->tf_flags & TFF_INUSE);
-
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- reply_thr_get (tcp_fd, ENOTCONN, FALSE);
- return NW_OK;
- }
- tcp_conn= tcp_fd->tf_conn;
- if (tcp_conn->tc_state == TCS_CLOSED)
- {
- reply_thr_get(tcp_fd, tcp_conn->tc_error, FALSE);
- return NW_OK;
- }
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- {
- reply_thr_get (tcp_fd, ESHUTDOWN, FALSE);
- return NW_OK;
- }
-
- tcp_fd->tf_flags |= TFF_WRITE_IP;
- tcp_fd->tf_write_offset= 0;
- tcp_fd->tf_write_count= count;
-
- /* New data may cause a segment to be sent. Clear PUSH_NOW
- * from last NWIOTCPPUSH ioctl.
- */
- tcp_conn->tc_flags &= ~(TCF_NO_PUSH|TCF_PUSH_NOW);
-
- /* Start the timer (if necessary) */
- if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
- tcp_set_send_timer(tcp_conn);
-
- assert(tcp_conn->tc_busy == 0);
- tcp_conn->tc_busy++;
- tcp_fd_write(tcp_conn);
- tcp_conn->tc_busy--;
- tcp_conn_write(tcp_conn, 0);
-
- if (!(tcp_fd->tf_flags & TFF_WRITE_IP))
- return NW_OK;
- else
- return NW_SUSPEND;
-}
-
-int
-tcp_read(fd, count)
-int fd;
-size_t count;
-{
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- tcp_fd= &tcp_fd_table[fd];
-
- assert (tcp_fd->tf_flags & TFF_INUSE);
-
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- {
- reply_thr_put (tcp_fd, ENOTCONN, FALSE);
- return NW_OK;
- }
- tcp_conn= tcp_fd->tf_conn;
-
- tcp_fd->tf_flags |= TFF_READ_IP;
- tcp_fd->tf_read_offset= 0;
- tcp_fd->tf_read_count= count;
-
- assert(tcp_conn->tc_busy == 0);
- tcp_conn->tc_busy++;
- tcp_fd_read(tcp_conn, 0);
- tcp_conn->tc_busy--;
- if (!(tcp_fd->tf_flags & TFF_READ_IP))
- return NW_OK;
- else
- return NW_SUSPEND;
-}
-
-/*
-tcp_restart_connect
-
-reply the success or failure of a connect to the user.
-*/
-
-
-void tcp_restart_connect(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_fd_t *tcp_fd;
- int reply;
-
- assert(tcp_conn->tc_connInprogress);
- tcp_conn->tc_connInprogress= 0;
-
- tcp_fd= tcp_conn->tc_fd;
- assert(tcp_fd);
- if (tcp_fd->tf_flags & TFF_LISTENQ)
- {
- /* Special code for listen queues */
- assert(tcp_conn->tc_state != TCS_CLOSED);
-
- /* Reply for select */
- if ((tcp_fd->tf_flags & TFF_SEL_READ) &&
- tcp_fd->tf_select_res)
- {
- tcp_fd->tf_flags &= ~TFF_SEL_READ;
- tcp_fd->tf_select_res(tcp_fd->tf_srfd,
- SR_SELECT_READ);
- }
-
- /* Reply for acceptto */
- if (tcp_fd->tf_flags & TFF_IOCTL_IP)
- (void) tcp_acceptto(tcp_fd);
-
- return;
- }
-
- if (tcp_conn->tc_state == TCS_CLOSED)
- {
- reply= tcp_conn->tc_error;
- assert(tcp_conn->tc_fd == tcp_fd);
- tcp_fd->tf_conn= NULL;
- tcp_conn->tc_fd= NULL;
- tcp_fd->tf_error= reply;
- }
- else
- {
- tcp_fd->tf_flags |= TFF_CONNECTED;
- reply= NW_OK;
- }
-
- if (tcp_fd->tf_flags & TFF_CONNECTING)
- {
- /* Special code for asynchronous connects */
- tcp_fd->tf_flags &= ~TFF_CONNECTING;
-
- /* Reply for select */
- if ((tcp_fd->tf_flags & TFF_SEL_WRITE) &&
- tcp_fd->tf_select_res)
- {
- tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
- tcp_fd->tf_select_res(tcp_fd->tf_srfd,
- SR_SELECT_WRITE);
- }
-
- return;
- }
-
- assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
- assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
- tcp_fd->tf_ioreq == NWIOTCPCONN);
-
- tcp_reply_ioctl (tcp_fd, reply);
-}
-
-/*
-tcp_close
-*/
-
-void tcp_close(fd)
-int fd;
-{
- int i;
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- tcp_fd= &tcp_fd_table[fd];
-
- assert (tcp_fd->tf_flags & TFF_INUSE);
- assert (!(tcp_fd->tf_flags &
- (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP)));
-
- if (tcp_fd->tf_flags & TFF_LISTENQ)
- {
- /* Special code for listen queues */
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- tcp_conn= tcp_fd->tf_listenq[i];
- if (!tcp_conn)
- continue;
-
- tcp_fd->tf_listenq[i]= NULL;
- assert(tcp_conn->tc_fd == tcp_fd);
- tcp_conn->tc_fd= NULL;
-
- if (tcp_conn->tc_connInprogress)
- {
- tcp_conn->tc_connInprogress= 0;
- tcp_close_connection(tcp_conn, ENOCONN);
- continue;
- }
-
- tcp_shutdown (tcp_conn);
- if (tcp_conn->tc_state == TCS_ESTABLISHED)
- tcp_conn->tc_state= TCS_CLOSING;
-
- /* Set the retransmission timeout a bit smaller. */
- tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
-
- /* If all data has been acknowledged, close the connection. */
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
- tcp_close_connection(tcp_conn, ENOTCONN);
- }
-
- tcp_conn= tcp_fd->tf_conn;
- assert(tcp_conn->tc_fd == tcp_fd);
- assert (tcp_conn->tc_connInprogress);
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_fd= NULL;
- tcp_fd->tf_conn= NULL;
- tcp_close_connection(tcp_conn, ENOCONN);
- }
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- assert(tcp_fd->tf_listenq[i] == NULL);
- }
-
- if (tcp_fd->tf_flags & TFF_CONNECTING)
- {
- tcp_conn= tcp_fd->tf_conn;
- assert(tcp_conn != NULL);
-
- assert (tcp_conn->tc_connInprogress);
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_fd= NULL;
- tcp_fd->tf_conn= NULL;
- tcp_close_connection(tcp_conn, ENOCONN);
-
- tcp_fd->tf_flags &= ~TFF_CONNECTING;
- }
-
- tcp_fd->tf_flags &= ~TFF_INUSE;
- if (!tcp_fd->tf_conn)
- return;
-
-
- tcp_conn= tcp_fd->tf_conn;
- assert(tcp_conn->tc_fd == tcp_fd);
- tcp_conn->tc_fd= NULL;
-
- assert (!tcp_conn->tc_connInprogress);
-
- tcp_shutdown (tcp_conn);
- if (tcp_conn->tc_state == TCS_ESTABLISHED)
- {
- tcp_conn->tc_state= TCS_CLOSING;
- }
-
- /* Set the retransmission timeout a bit smaller. */
- tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
-
- /* If all data has been acknowledged, close the connection. */
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
- tcp_close_connection(tcp_conn, ENOTCONN);
-}
-
-int tcp_cancel(fd, which_operation)
-int fd;
-int which_operation;
-{
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tcp_conn;
-
- tcp_fd= &tcp_fd_table[fd];
-
- assert (tcp_fd->tf_flags & TFF_INUSE);
-
- tcp_conn= tcp_fd->tf_conn;
-
- switch (which_operation)
- {
- case SR_CANCEL_WRITE:
- assert (tcp_fd->tf_flags & TFF_WRITE_IP);
- tcp_fd->tf_flags &= ~TFF_WRITE_IP;
-
- if (tcp_fd->tf_write_offset)
- reply_thr_get (tcp_fd, tcp_fd->tf_write_offset, FALSE);
- else
- reply_thr_get (tcp_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_READ:
- assert (tcp_fd->tf_flags & TFF_READ_IP);
- tcp_fd->tf_flags &= ~TFF_READ_IP;
- if (tcp_fd->tf_read_offset)
- reply_thr_put (tcp_fd, tcp_fd->tf_read_offset, FALSE);
- else
- reply_thr_put (tcp_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_IOCTL:
-assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
-
- if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
- {
- tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
- reply_thr_put (tcp_fd, EINTR, TRUE);
- break;
- }
-
- switch (tcp_fd->tf_ioreq)
- {
- case NWIOGTCPCONF:
- reply_thr_put (tcp_fd, EINTR, TRUE);
- break;
- case NWIOSTCPCONF:
- case NWIOTCPSHUTDOWN:
- reply_thr_get (tcp_fd, EINTR, TRUE);
- break;
- case NWIOTCPCONN:
- case NWIOTCPLISTEN:
- assert (tcp_conn->tc_connInprogress);
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_fd= NULL;
- tcp_fd->tf_conn= NULL;
- tcp_close_connection(tcp_conn, ENOCONN);
- reply_thr_get (tcp_fd, EINTR, TRUE);
- break;
- default:
- ip_warning(( "unknown ioctl inprogress: 0x%x",
- tcp_fd->tf_ioreq ));
- reply_thr_get (tcp_fd, EINTR, TRUE);
- break;
- }
- break;
- default:
- ip_panic(( "unknown cancel request" ));
- break;
- }
- return NW_OK;
-}
-
-/*
-tcp_connect
-*/
-
-static int tcp_connect(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- tcp_conn_t *tcp_conn;
- nwio_tcpcl_t *tcpcl;
- long nwtcl_flags;
- int r, do_asynch;
- acc_t *data;
-
- if (!(tcp_fd->tf_flags & TFF_CONF_SET))
- {
- tcp_reply_ioctl(tcp_fd, EBADMODE);
- return NW_OK;
- }
- assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
- !(tcp_fd->tf_flags & TFF_CONNECTING) &&
- !(tcp_fd->tf_flags & TFF_LISTENQ));
- if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
- != (NWTC_SET_RA|NWTC_SET_RP))
- {
- tcp_reply_ioctl(tcp_fd, EBADMODE);
- return NW_OK;
- }
-
- data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
- sizeof(*tcpcl), TRUE);
- if (!data)
- return EFAULT;
-
- data= bf_packIffLess(data, sizeof(*tcpcl));
- assert (data->acc_length == sizeof(*tcpcl));
- tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data);
-
- nwtcl_flags= tcpcl->nwtcl_flags;
- bf_afree(data); data= NULL; tcpcl= NULL;
-
- if (nwtcl_flags == TCF_ASYNCH)
- do_asynch= 1;
- else if (nwtcl_flags == TCF_DEFAULT)
- do_asynch= 0;
- else
- {
- tcp_reply_ioctl(tcp_fd, EINVAL);
- return NW_OK;
- }
-
- assert(!tcp_fd->tf_conn);
- tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
- tcp_fd->tf_port->tp_ipaddr,
- tcp_fd->tf_tcpconf.nwtc_remport,
- tcp_fd->tf_tcpconf.nwtc_remaddr);
- if (tcp_conn)
- {
- if (tcp_conn->tc_fd)
- {
- tcp_reply_ioctl(tcp_fd, EADDRINUSE);
- return NW_OK;
- }
- }
- else
- {
- tcp_conn= find_empty_conn();
- if (!tcp_conn)
- {
- tcp_reply_ioctl(tcp_fd, EAGAIN);
- return NW_OK;
- }
- }
- tcp_fd->tf_conn= tcp_conn;
-
- r= tcp_su4connect(tcp_fd);
- if (r == NW_SUSPEND && do_asynch)
- {
- tcp_fd->tf_flags |= TFF_CONNECTING;
- tcp_reply_ioctl(tcp_fd, EINPROGRESS);
- r= NW_OK;
- }
- return r;
-}
-
-/*
-tcp_su4connect
-*/
-
-static int tcp_su4connect(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- tcp_conn_t *tcp_conn;
-
- tcp_conn= tcp_fd->tf_conn;
-
- tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
- tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
-
- assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP);
- assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA);
- tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
- tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
-
- tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
-
- tcp_conn->tc_fd= tcp_fd;
- tcp_conn->tc_connInprogress= 1;
- tcp_conn->tc_orglisten= FALSE;
- tcp_conn->tc_state= TCS_SYN_SENT;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CONNECT;
-
- /* Start the timer (if necessary) */
- tcp_set_send_timer(tcp_conn);
-
- tcp_conn_write(tcp_conn, 0);
-
- if (tcp_conn->tc_connInprogress)
- return NW_SUSPEND;
- else
- return NW_OK;
-}
-
-
-/*
-tcp_listen
-*/
-
-static int tcp_listen(tcp_fd, do_listenq)
-tcp_fd_t *tcp_fd;
-int do_listenq;
-{
- tcp_conn_t *tcp_conn;
-
- if (!(tcp_fd->tf_flags & TFF_CONF_SET))
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get(tcp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
- assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
- !(tcp_fd->tf_flags & TFF_CONNECTING) &&
- !(tcp_fd->tf_flags & TFF_LISTENQ));
- tcp_conn= tcp_fd->tf_conn;
- assert(!tcp_conn);
-
- if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
- == (NWTC_SET_RA|NWTC_SET_RP))
- {
- tcp_conn= find_conn_entry(
- tcp_fd->tf_tcpconf.nwtc_locport,
- tcp_fd->tf_port->tp_ipaddr,
- tcp_fd->tf_tcpconf.nwtc_remport,
- tcp_fd->tf_tcpconf.nwtc_remaddr);
- if (tcp_conn)
- {
- if (tcp_conn->tc_fd)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EADDRINUSE, TRUE);
- return NW_OK;
- }
- tcp_fd->tf_conn= tcp_conn;
- return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
- }
- }
- tcp_conn= find_empty_conn();
- if (!tcp_conn)
- {
- tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
- reply_thr_get (tcp_fd, EAGAIN, TRUE);
- return NW_OK;
- }
- tcp_fd->tf_conn= tcp_conn;
- return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
-}
-
-/*
-tcp_acceptto
-*/
-
-static int tcp_acceptto(tcp_fd)
-tcp_fd_t *tcp_fd;
-{
- int i, dst_nr;
- tcp_fd_t *dst_fd;
- tcp_conn_t *tcp_conn;
- tcp_cookie_t *cookiep;
- acc_t *data;
- tcp_cookie_t cookie;
-
- if (!(tcp_fd->tf_flags & TFF_LISTENQ))
- {
- tcp_reply_ioctl(tcp_fd, EINVAL);
- return NW_OK;
- }
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- tcp_conn= tcp_fd->tf_listenq[i];
- if (tcp_conn && !tcp_conn->tc_connInprogress)
- break;
- }
- if (i >= TFL_LISTEN_MAX)
- {
- /* Nothing, suspend caller */
- return NW_SUSPEND;
- }
-
- data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
- sizeof(*cookiep), TRUE);
- if (!data)
- return EFAULT;
-
- data= bf_packIffLess(data, sizeof(*cookiep));
- cookiep= (tcp_cookie_t *)ptr2acc_data(data);
- cookie= *cookiep;
-
- bf_afree(data); data= NULL;
-
- dst_nr= cookie.tc_ref;
- if (dst_nr < 0 || dst_nr >= TCP_FD_NR)
- {
- printf("tcp_acceptto: bad fd %d\n", dst_nr);
- tcp_reply_ioctl(tcp_fd, EINVAL);
- return NW_OK;
- }
- dst_fd= &tcp_fd_table[dst_nr];
- if (!(dst_fd->tf_flags & TFF_INUSE) ||
- (dst_fd->tf_flags & (TFF_READ_IP|TFF_WRITE_IP|TFF_IOCTL_IP)) ||
- dst_fd->tf_conn != NULL ||
- !(dst_fd->tf_flags & TFF_COOKIE))
- {
- printf("tcp_acceptto: bad flags 0x%lx or conn %p for fd %d\n",
- dst_fd->tf_flags, dst_fd->tf_conn, dst_nr);
- tcp_reply_ioctl(tcp_fd, EINVAL);
- return NW_OK;
- }
- if (memcmp(&cookie, &dst_fd->tf_cookie, sizeof(cookie)) != 0)
- {
- printf("tcp_acceptto: bad cookie\n");
- return NW_OK;
- }
-
- /* Move connection */
- tcp_fd->tf_listenq[i]= NULL;
- tcp_conn->tc_fd= dst_fd;
- dst_fd->tf_conn= tcp_conn;
- dst_fd->tf_flags |= TFF_CONNECTED;
-
- tcp_reply_ioctl(tcp_fd, NW_OK);
- return NW_OK;
-}
-
-
-static void tcp_buffree (priority)
-int priority;
-{
- int i;
- tcp_conn_t *tcp_conn;
-
- if (priority == TCP_PRI_FRAG2SEND)
- {
- for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
- tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (!tcp_conn->tc_frag2send)
- continue;
- if (tcp_conn->tc_busy)
- continue;
- bf_afree(tcp_conn->tc_frag2send);
- tcp_conn->tc_frag2send= 0;
- }
- }
-
- if (priority == TCP_PRI_CONN_EXTRA)
- {
- for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
- tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (tcp_conn->tc_busy)
- continue;
- if (tcp_conn->tc_adv_data)
- {
- bf_afree(tcp_conn->tc_adv_data);
- tcp_conn->tc_adv_data= NULL;
- }
- }
- }
-
- if (priority == TCP_PRI_CONNwoUSER)
- {
- for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
- tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (tcp_conn->tc_busy)
- continue;
- if (tcp_conn->tc_fd)
- continue;
- if (tcp_conn->tc_state == TCS_CLOSED)
- continue;
- if (tcp_conn->tc_rcvd_data == NULL &&
- tcp_conn->tc_send_data == NULL)
- {
- continue;
- }
- tcp_close_connection (tcp_conn, ENOBUFS);
- }
- }
-
- if (priority == TCP_PRI_CONN_INUSE)
- {
- for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
- tcp_conn++)
- {
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- continue;
- if (tcp_conn->tc_busy)
- continue;
- if (tcp_conn->tc_state == TCS_CLOSED)
- continue;
- if (tcp_conn->tc_rcvd_data == NULL &&
- tcp_conn->tc_send_data == NULL)
- {
- continue;
- }
- tcp_close_connection (tcp_conn, ENOBUFS);
- }
- }
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void tcp_bufcheck()
-{
- int i;
- tcp_conn_t *tcp_conn;
- tcp_port_t *tcp_port;
-
- for (i= 0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
- {
- if (tcp_port->tp_pack)
- bf_check_acc(tcp_port->tp_pack);
- }
- for (i= 0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++)
- {
- assert(!tcp_conn->tc_busy);
- if (tcp_conn->tc_rcvd_data)
- bf_check_acc(tcp_conn->tc_rcvd_data);
- if (tcp_conn->tc_adv_data)
- bf_check_acc(tcp_conn->tc_adv_data);
- if (tcp_conn->tc_send_data)
- bf_check_acc(tcp_conn->tc_send_data);
- if (tcp_conn->tc_remipopt)
- bf_check_acc(tcp_conn->tc_remipopt);
- if (tcp_conn->tc_tcpopt)
- bf_check_acc(tcp_conn->tc_tcpopt);
- if (tcp_conn->tc_frag2send)
- bf_check_acc(tcp_conn->tc_frag2send);
- }
-}
-#endif
-
-void tcp_notreach(tcp_conn, error)
-tcp_conn_t *tcp_conn;
-int error;
-{
- int new_ttl;
-
- new_ttl= tcp_conn->tc_ttl;
- if (new_ttl == IP_MAX_TTL)
- {
- if (tcp_conn->tc_state == TCS_SYN_SENT)
- tcp_close_connection(tcp_conn, error);
- return;
- }
- else if (new_ttl < TCP_DEF_TTL_NEXT)
- new_ttl= TCP_DEF_TTL_NEXT;
- else
- {
- new_ttl *= 2;
- if (new_ttl> IP_MAX_TTL)
- new_ttl= IP_MAX_TTL;
- }
- tcp_conn->tc_ttl= new_ttl;
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
- tcp_conn_write(tcp_conn, 1);
-}
-
-static u32_t mtu_table[]=
-{ /* From RFC-1191 */
-/* Plateau MTU Comments Reference */
-/* ------ --- -------- --------- */
-/* 65535 Official maximum MTU RFC 791 */
-/* 65535 Hyperchannel RFC 1044 */
- 65535,
- 32000, /* Just in case */
-/* 17914 16Mb IBM Token Ring ref. [6] */
- 17914,
-/* 8166 IEEE 802.4 RFC 1042 */
- 8166,
-/* 4464 IEEE 802.5 (4Mb max) RFC 1042 */
-/* 4352 FDDI (Revised) RFC 1188 */
- 4352, /* (1%) */
-/* 2048 Wideband Network RFC 907 */
-/* 2002 IEEE 802.5 (4Mb recommended) RFC 1042 */
- 2002, /* (2%) */
-/* 1536 Exp. Ethernet Nets RFC 895 */
-/* 1500 Ethernet Networks RFC 894 */
-/* 1500 Point-to-Point (default) RFC 1134 */
-/* 1492 IEEE 802.3 RFC 1042 */
- 1492, /* (3%) */
-/* 1006 SLIP RFC 1055 */
-/* 1006 ARPANET BBN 1822 */
- 1006,
-/* 576 X.25 Networks RFC 877 */
-/* 544 DEC IP Portal ref. [10] */
-/* 512 NETBIOS RFC 1088 */
-/* 508 IEEE 802/Source-Rt Bridge RFC 1042 */
-/* 508 ARCNET RFC 1051 */
- 508, /* (13%) */
-/* 296 Point-to-Point (low delay) RFC 1144 */
- 296,
- 68, /* Official minimum MTU RFC 791 */
- 0, /* End of list */
-};
-
-void tcp_mtu_exceeded(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- u16_t mtu;
- int i;
- clock_t curr_time;
-
- if (!(tcp_conn->tc_flags & TCF_PMTU))
- {
- /* Strange, got MTU exceeded but DF is not set. Ignore
- * the error. If the problem persists, the connection will
- * time-out.
- */
- return;
- }
- curr_time= get_time();
-
- /* We get here in cases. Either were are trying to find an MTU
- * that works at all, or we are trying see how far we can increase
- * the current MTU. If the last change to the MTU was a long time
- * ago, we assume the second case.
- */
- if (curr_time >= tcp_conn->tc_mtutim + TCP_PMTU_INCR_IV)
- {
- mtu= tcp_conn->tc_mtu;
- mtu -= mtu/TCP_PMTU_INCR_FRAC;
- tcp_conn->tc_mtu= mtu;
- tcp_conn->tc_mtutim= curr_time;
- DBLOCK(1, printf(
- "tcp_mtu_exceeded: new (lowered) mtu %d for conn %d\n",
- mtu, tcp_conn-tcp_conn_table));
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
- tcp_conn_write(tcp_conn, 1);
- return;
- }
-
- tcp_conn->tc_mtutim= curr_time;
- mtu= tcp_conn->tc_mtu;
- for (i= 0; mtu_table[i] >= mtu; i++)
- ; /* Nothing to do */
- mtu= mtu_table[i];
- if (mtu >= TCP_MIN_PATH_MTU)
- {
- tcp_conn->tc_mtu= mtu;
- }
- else
- {
- /* Small MTUs can be used for denial-of-service attacks.
- * Switch-off PMTU if the MTU becomes too small.
- */
- tcp_conn->tc_flags &= ~TCF_PMTU;
- tcp_conn->tc_mtu= TCP_MIN_PATH_MTU;
- DBLOCK(1, printf(
- "tcp_mtu_exceeded: clearing TCF_PMTU for conn %d\n",
- tcp_conn-tcp_conn_table););
-
- }
- DBLOCK(1, printf("tcp_mtu_exceeded: new mtu %d for conn %d\n",
- mtu, tcp_conn-tcp_conn_table););
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
- tcp_conn_write(tcp_conn, 1);
-}
-
-void tcp_mtu_incr(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- clock_t curr_time;
- u32_t mtu;
-
- assert(tcp_conn->tc_mtu < tcp_conn->tc_max_mtu);
- if (!(tcp_conn->tc_flags & TCF_PMTU))
- {
- /* Use a much longer time-out for retrying PMTU discovery
- * after is has been disabled. Note that PMTU discovery
- * can be disabled during a short loss of connectivity.
- */
- curr_time= get_time();
- if (curr_time > tcp_conn->tc_mtutim+TCP_PMTU_EN_IV)
- {
- tcp_conn->tc_flags |= TCF_PMTU;
- DBLOCK(1, printf(
- "tcp_mtu_incr: setting TCF_PMTU for conn %d\n",
- tcp_conn-tcp_conn_table););
- }
- return;
- }
-
- mtu= tcp_conn->tc_mtu;
- mtu += mtu/TCP_PMTU_INCR_FRAC;
- if (mtu > tcp_conn->tc_max_mtu)
- mtu= tcp_conn->tc_max_mtu;
- tcp_conn->tc_mtu= mtu;
- DBLOCK(0x1, printf("tcp_mtu_incr: new mtu %u for conn %u\n",
- mtu, tcp_conn-tcp_conn_table););
-}
-
-/*
-tcp_setup_conn
-*/
-
-static void tcp_setup_conn(tcp_port, tcp_conn)
-tcp_port_t *tcp_port;
-tcp_conn_t *tcp_conn;
-{
- u16_t mss;
-
- assert(!tcp_conn->tc_connInprogress);
- tcp_conn->tc_port= tcp_port;
- if (tcp_conn->tc_flags & TCF_INUSE)
- {
- assert (tcp_conn->tc_state == TCS_CLOSED);
- assert (!tcp_conn->tc_send_data);
- if (tcp_conn->tc_senddis < get_time())
- tcp_conn->tc_ISS= 0;
- }
- else
- {
- assert(!tcp_conn->tc_busy);
- tcp_conn->tc_senddis= 0;
- tcp_conn->tc_ISS= 0;
- tcp_conn->tc_tos= TCP_DEF_TOS;
- tcp_conn->tc_ttl= TCP_DEF_TTL;
- tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
- tcp_conn->tc_fd= NULL;
- }
- if (!tcp_conn->tc_ISS)
- {
- tcp_conn->tc_ISS= tcp_rand32();
- }
- tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
- tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS+1;
- tcp_conn->tc_IRS= 0;
- tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
- tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
-
- assert(tcp_conn->tc_rcvd_data == NULL);
- assert(tcp_conn->tc_adv_data == NULL);
- assert(tcp_conn->tc_send_data == NULL);
-
- tcp_conn->tc_ka_time= TCP_DEF_KEEPALIVE;
-
- tcp_conn->tc_remipopt= NULL;
- tcp_conn->tc_tcpopt= NULL;
-
- assert(tcp_conn->tc_frag2send == NULL);
-
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
- tcp_conn->tc_0wnd_to= 0;
- tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
- tcp_conn->tc_drtt= 0;
- tcp_conn->tc_rtt= TCP_DEF_RTT;
- tcp_conn->tc_max_mtu= tcp_conn->tc_port->tp_mtu;
- tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
- tcp_conn->tc_mtutim= 0;
- tcp_conn->tc_error= NW_OK;
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
- tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*mss;
- tcp_conn->tc_snd_cthresh= TCP_MAX_SND_WND_SIZE;
- tcp_conn->tc_snd_cinc=
- (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
- tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
- tcp_conn->tc_rt_time= 0;
- tcp_conn->tc_rt_seq= 0;
- tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
- tcp_conn->tc_flags= TCF_INUSE;
- tcp_conn->tc_flags |= TCF_PMTU;
-
- clck_untimer(&tcp_conn->tc_transmit_timer);
- tcp_conn->tc_transmit_seq= 0;
-}
-
-static u32_t tcp_rand32()
-{
- u8_t bits[RAND256_BUFSIZE];
-
- rand256(bits);
- return bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24);
-}
-
-/*
- * $PchId: tcp.c,v 1.34 2005/06/28 14:20:27 philip Exp $
- */
+++ /dev/null
-/*
-tcp.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef TCP_H
-#define TCP_H
-
-#define TCP_MAX_DATAGRAM 8192
-
-#ifndef TCP_MAX_SND_WND_SIZE
-#define TCP_MAX_SND_WND_SIZE (32*1024)
-#endif
-
-#ifndef TCP_MIN_RCV_WND_SIZE
-#define TCP_MIN_RCV_WND_SIZE (4*1024)
-#endif
-
-#ifndef TCP_MAX_RCV_WND_SIZE
-#define TCP_MAX_RCV_WND_SIZE (TCP_MIN_RCV_WND_SIZE + 28*1024)
-#endif
-
-#define TCP_DEF_TOS 0
-#define TCP_DEF_TTL 5 /* hops/seconds */
-#define TCP_DEF_TTL_NEXT 30 /* hops/seconds */
-
-/* An established TCP connection times out if no communication is possible
- * for TCP_DEF_RT_DEAD clock ticks
- */
-#ifndef TCP_DEF_RT_DEAD
-#define TCP_DEF_RT_DEAD (20L*60*HZ)
-#endif
-
-#define TCP_DEF_RT_MAX_CONNECT (5L*60*HZ) /* 5 minutes in ticks */
-#define TCP_DEF_RT_MAX_LISTEN (1L*60*HZ) /* 1 minute in ticks */
-#define TCP_DEF_RT_MAX_CLOSING (1L*60*HZ) /* 1 minute in ticks */
-
-/* Minimum and maximum intervals for zero window probes. */
-#define TCP_0WND_MIN (HZ)
-#define TCP_0WND_MAX (5*60*HZ)
-
-#define TCP_DEF_RTT 15 /* initial retransmission time in
- * ticks
- */
-#define TCP_RTT_GRAN 5 /* minimal value of the rtt is
- * TCP_RTT_GRAN * CLOCK_GRAN
- */
-#define TCP_RTT_MAX (10*HZ) /* The maximum retransmission interval
- * is TCP_RTT_MAX ticks
- */
-#define TCP_RTT_SMOOTH 16 /* weight is 15/16 */
-#define TCP_DRTT_MULT 4 /* weight of the deviation */
-#define TCP_RTT_SCALE 256 /* Scaled values for more accuracy */
-
-#ifndef TCP_DEF_KEEPALIVE
-#define TCP_DEF_KEEPALIVE (20L*60*HZ) /* Keepalive interval */
-#endif
-
-#ifndef TCP_DEF_MSS
-#define TCP_DEF_MSS 1400
-#endif
-
-#define TCP_MIN_PATH_MTU 500
-#define TCP_PMTU_INCR_IV (1L*60*HZ) /* 1 minute in ticks */
-#define TCP_PMTU_EN_IV (10L*60*HZ) /* 10 minutes in ticks */
-#define TCP_PMTU_INCR_FRAC 100 /* Add 1% each time */
-#define TCP_PMTU_BLACKHOLE (10*HZ) /* Assume a PMTU blackhole
- * after 10 seconds.
- */
-
-#define TCP_DEF_CONF (NWTC_COPY | NWTC_LP_UNSET | NWTC_UNSET_RA | \
- NWTC_UNSET_RP)
-#define TCP_DEF_OPT (NWTO_NOFLAG)
-
-#define TCP_DACK_RETRANS 3 /* # dup ACKs to start fast retrans. */
-
-struct acc;
-
-void tcp_prep ARGS(( void ));
-void tcp_init ARGS(( void ));
-int tcp_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t select_res ));
-int tcp_read ARGS(( int fd, size_t count));
-int tcp_write ARGS(( int fd, size_t count));
-int tcp_ioctl ARGS(( int fd, ioreq_t req));
-int tcp_cancel ARGS(( int fd, int which_operation ));
-void tcp_close ARGS(( int fd));
-
-#endif /* TCP_H */
-
-/*
- * $PchId: tcp.h,v 1.17 2005/06/28 14:20:54 philip Exp $
- */
+++ /dev/null
-/*
-tcp_int.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef TCP_INT_H
-#define TCP_INT_H
-
-#define IP_TCP_MIN_HDR_SIZE (IP_MIN_HDR_SIZE+TCP_MIN_HDR_SIZE)
-
-#define TCP_CONN_HASH_SHIFT 4
-#define TCP_CONN_HASH_NR (1 << TCP_CONN_HASH_SHIFT)
-
-typedef struct tcp_port
-{
- int tp_ipdev;
- int tp_flags;
- int tp_state;
- int tp_ipfd;
- acc_t *tp_pack;
- ipaddr_t tp_ipaddr;
- ipaddr_t tp_subnetmask;
- u16_t tp_mtu;
- struct tcp_conn *tp_snd_head;
- struct tcp_conn *tp_snd_tail;
- event_t tp_snd_event;
- struct tcp_conn *tp_conn_hash[TCP_CONN_HASH_NR][4];
-} tcp_port_t;
-
-#define TPF_EMPTY 0x0
-#define TPF_SUSPEND 0x1
-#define TPF_READ_IP 0x2
-#define TPF_READ_SP 0x4
-#define TPF_WRITE_IP 0x8
-#define TPF_WRITE_SP 0x10
-#define TPF_DELAY_TCP 0x40
-
-#define TPS_EMPTY 0
-#define TPS_SETPROTO 1
-#define TPS_GETCONF 2
-#define TPS_MAIN 3
-#define TPS_ERROR 4
-
-#define TFL_LISTEN_MAX 5
-
-typedef struct tcp_fd
-{
- unsigned long tf_flags;
- tcp_port_t *tf_port;
- int tf_srfd;
- ioreq_t tf_ioreq;
- nwio_tcpconf_t tf_tcpconf;
- nwio_tcpopt_t tf_tcpopt;
- get_userdata_t tf_get_userdata;
- put_userdata_t tf_put_userdata;
- select_res_t tf_select_res;
- struct tcp_conn *tf_conn;
- struct tcp_conn *tf_listenq[TFL_LISTEN_MAX];
- size_t tf_write_offset;
- size_t tf_write_count;
- size_t tf_read_offset;
- size_t tf_read_count;
- int tf_error; /* Error for nonblocking connect */
- tcp_cookie_t tf_cookie;
-} tcp_fd_t;
-
-#define TFF_EMPTY 0x0
-#define TFF_INUSE 0x1
-#define TFF_READ_IP 0x2
-#define TFF_WRITE_IP 0x4
-#define TFF_IOCTL_IP 0x8
-#define TFF_CONF_SET 0x10
-#define TFF_IOC_INIT_SP 0x20
-#define TFF_LISTENQ 0x40
-#define TFF_CONNECTING 0x80
-#define TFF_CONNECTED 0x100
-#define TFF_WR_URG 0x200
-#define TFF_PUSH_DATA 0x400
-#define TFF_RECV_URG 0x800
-#define TFF_SEL_READ 0x1000
-#define TFF_SEL_WRITE 0x2000
-#define TFF_SEL_EXCEPT 0x4000
-#define TFF_DEL_RST 0x8000
-#define TFF_COOKIE 0x10000
-
-typedef struct tcp_conn
-{
- int tc_flags;
- int tc_state;
- int tc_busy; /* do not steal buffer when a connection is
- * busy
- */
- tcp_port_t *tc_port;
- tcp_fd_t *tc_fd;
-
- tcpport_t tc_locport;
- ipaddr_t tc_locaddr;
- tcpport_t tc_remport;
- ipaddr_t tc_remaddr;
-
- int tc_connInprogress;
- int tc_orglisten;
- clock_t tc_senddis;
-
- /* Sending side */
- u32_t tc_ISS; /* initial sequence number */
- u32_t tc_SND_UNA; /* least unacknowledged sequence number */
- u32_t tc_SND_TRM; /* next sequence number to be transmitted */
- u32_t tc_SND_NXT; /* next sequence number for new data */
- u32_t tc_SND_UP; /* urgent pointer, first sequence number not
- * urgent */
- u32_t tc_SND_PSH; /* push pointer, data should be pushed until
- * the push pointer is reached */
-
- u32_t tc_snd_cwnd; /* highest sequence number to be sent */
- u32_t tc_snd_cthresh; /* threshold for send window */
- u32_t tc_snd_cinc; /* increment for send window threshold */
- u16_t tc_snd_wnd; /* max send queue size */
- u16_t tc_snd_dack; /* # of duplicate ACKs */
-
- /* round trip calculation. */
- clock_t tc_rt_time;
- u32_t tc_rt_seq;
- u32_t tc_rt_threshold;
- clock_t tc_artt; /* Avg. retransmission time. Scaled. */
- clock_t tc_drtt; /* Diviation, also scaled. */
- clock_t tc_rtt; /* Computed retrans time */
-
- acc_t *tc_send_data;
- acc_t *tc_frag2send;
- struct tcp_conn *tc_send_link;
-
- /* Receiving side */
- u32_t tc_IRS;
- u32_t tc_RCV_LO;
- u32_t tc_RCV_NXT;
- u32_t tc_RCV_HI;
- u32_t tc_RCV_UP;
-
- u16_t tc_rcv_wnd;
- acc_t *tc_rcvd_data;
- acc_t *tc_adv_data;
- u32_t tc_adv_seq;
-
- /* Keep alive. Record SDN_NXT and RCV_NXT in tc_ka_snd and
- * tc_ka_rcv when setting the keepalive timer to detect
- * any activity that may have happend before the timer
- * expired.
- */
- u32_t tc_ka_snd;
- u32_t tc_ka_rcv;
- clock_t tc_ka_time;
-
- acc_t *tc_remipopt;
- acc_t *tc_tcpopt;
- u8_t tc_tos;
- u8_t tc_ttl;
- u16_t tc_max_mtu; /* Max. negotiated (or selected) MTU */
- u16_t tc_mtu; /* discovered PMTU */
- clock_t tc_mtutim; /* Last time MTU/TCF_PMTU flag was changed */
-
- minix_timer_t tc_transmit_timer;
- u32_t tc_transmit_seq;
- clock_t tc_0wnd_to;
- clock_t tc_stt; /* time of first send after last ack */
- clock_t tc_rt_dead;
-
- int tc_error;
- int tc_inconsistent;
-} tcp_conn_t;
-
-#define TCF_EMPTY 0x0
-#define TCF_INUSE 0x1
-#define TCF_FIN_RECV 0x2
-#define TCF_RCV_PUSH 0x4
-#define TCF_MORE2WRITE 0x8
-#define TCF_SEND_ACK 0x10
-#define TCF_FIN_SENT 0x20
-#define TCF_BSD_URG 0x40
-#define TCF_NO_PUSH 0x80
-#define TCF_PUSH_NOW 0x100
-#define TCF_PMTU 0x200
-
-#if DEBUG & 0x200
-#define TCF_DEBUG 0x1000
-#endif
-
-#define TCS_CLOSED 0
-#define TCS_LISTEN 1
-#define TCS_SYN_RECEIVED 2
-#define TCS_SYN_SENT 3
-#define TCS_ESTABLISHED 4
-#define TCS_CLOSING 5
-
-/* tcp_recv.c */
-void tcp_frag2conn ARGS(( tcp_conn_t *tcp_conn, ip_hdr_t *ip_hdr,
- tcp_hdr_t *tcp_hdr, acc_t *tcp_data, size_t data_len ));
-void tcp_fd_read ARGS(( tcp_conn_t *tcp_conn, int enq ));
-unsigned tcp_sel_read ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_rsel_read ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_bytesavailable ARGS(( tcp_fd_t *tcp_fd, int *bytesp ));
-
-/* tcp_send.c */
-void tcp_conn_write ARGS(( tcp_conn_t *tcp_conn, int enq ));
-void tcp_release_retrans ARGS(( tcp_conn_t *tcp_conn, u32_t seg_ack,
- u16_t new_win ));
-void tcp_fast_retrans ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_set_send_timer ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_fd_write ARGS(( tcp_conn_t *tcp_conn ));
-unsigned tcp_sel_write ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_rsel_write ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_close_connection ARGS(( tcp_conn_t *tcp_conn,
- int error ));
-void tcp_port_write ARGS(( tcp_port_t *tcp_port ));
-void tcp_shutdown ARGS(( tcp_conn_t *tcp_conn ));
-
-/* tcp_lib.c */
-void tcp_extract_ipopt ARGS(( tcp_conn_t *tcp_conn,
- ip_hdr_t *ip_hdr ));
-void tcp_extract_tcpopt ARGS(( tcp_conn_t *tcp_conn,
- tcp_hdr_t *tcp_hdr, size_t *mssp ));
-void tcp_get_ipopt ARGS(( tcp_conn_t *tcp_conn, ip_hdropt_t
- *ip_hdropt ));
-void tcp_get_tcpopt ARGS(( tcp_conn_t *tcp_conn, tcp_hdropt_t
- *tcp_hdropt ));
-acc_t *tcp_make_header ARGS(( tcp_conn_t *tcp_conn,
- ip_hdr_t **ref_ip_hdr, tcp_hdr_t **ref_tcp_hdr, acc_t *data ));
-u16_t tcp_pack_oneCsum ARGS(( ip_hdr_t *ip_hdr, acc_t *tcp_pack ));
-int tcp_check_conn ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_print_pack ARGS(( ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr ));
-void tcp_print_state ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_print_conn ARGS(( tcp_conn_t *tcp_conn ));
-int tcp_LEmod4G ARGS(( u32_t n1, u32_t n2 ));
-int tcp_Lmod4G ARGS(( u32_t n1, u32_t n2 ));
-int tcp_GEmod4G ARGS(( u32_t n1, u32_t n2 ));
-int tcp_Gmod4G ARGS(( u32_t n1, u32_t n2 ));
-
-/* tcp.c */
-void tcp_restart_connect ARGS(( tcp_conn_t *tcp_conn ));
-int tcp_su4listen ARGS(( tcp_fd_t *tcp_fd, tcp_conn_t *tcp_conn,
- int do_listenq ));
-void tcp_reply_ioctl ARGS(( tcp_fd_t *tcp_fd, int reply ));
-void tcp_reply_write ARGS(( tcp_fd_t *tcp_fd, size_t reply ));
-void tcp_reply_read ARGS(( tcp_fd_t *tcp_fd, size_t reply ));
-void tcp_notreach ARGS(( tcp_conn_t *tcp_conn, int error ));
-void tcp_mtu_exceeded ARGS(( tcp_conn_t *tcp_conn ));
-void tcp_mtu_incr ARGS(( tcp_conn_t *tcp_conn ));
-
-#define TCP_FD_NR (10*IP_PORT_MAX)
-#define TCP_CONN_NR (2*TCP_FD_NR)
-
-EXTERN tcp_port_t *tcp_port_table;
-EXTERN tcp_conn_t tcp_conn_table[TCP_CONN_NR];
-EXTERN tcp_fd_t tcp_fd_table[TCP_FD_NR];
-
-#define tcp_Lmod4G(n1,n2) (!!(((n1)-(n2)) & 0x80000000L))
-#define tcp_GEmod4G(n1,n2) (!(((n1)-(n2)) & 0x80000000L))
-#define tcp_Gmod4G(n1,n2) (!!(((n2)-(n1)) & 0x80000000L))
-#define tcp_LEmod4G(n1,n2) (!(((n2)-(n1)) & 0x80000000L))
-
-#endif /* TCP_INT_H */
-
-/*
- * $PchId: tcp_int.h,v 1.17 2005/06/28 14:21:08 philip Exp $
- */
+++ /dev/null
-/*
-tcp_lib.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "io.h"
-#include "type.h"
-
-#include "assert.h"
-#include "tcp_int.h"
-
-THIS_FILE
-
-#undef tcp_LEmod4G
-int tcp_LEmod4G(n1, n2)
-u32_t n1;
-u32_t n2;
-{
- return !((u32_t)(n2-n1) & 0x80000000L);
-}
-
-#undef tcp_GEmod4G
-int tcp_GEmod4G(n1, n2)
-u32_t n1;
-u32_t n2;
-{
- return !((u32_t)(n1-n2) & 0x80000000L);
-}
-
-#undef tcp_Lmod4G
-int tcp_Lmod4G(n1, n2)
-u32_t n1;
-u32_t n2;
-{
- return !!((u32_t)(n1-n2) & 0x80000000L);
-}
-
-#undef tcp_Gmod4G
-int tcp_Gmod4G(n1, n2)
-u32_t n1;
-u32_t n2;
-{
- return !!((u32_t)(n2-n1) & 0x80000000L);
-}
-
-void tcp_extract_ipopt(tcp_conn, ip_hdr)
-tcp_conn_t *tcp_conn;
-ip_hdr_t *ip_hdr;
-{
- int ip_hdr_len;
-
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- if (ip_hdr_len == IP_MIN_HDR_SIZE)
- return;
-
- DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
-}
-
-void tcp_extract_tcpopt(tcp_conn, tcp_hdr, mssp)
-tcp_conn_t *tcp_conn;
-tcp_hdr_t *tcp_hdr;
-size_t *mssp;
-{
- int i, tcp_hdr_len, type, len;
- u8_t *cp;
- u16_t mss;
-
- *mssp= 0; /* No mss */
-
- tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
- if (tcp_hdr_len == TCP_MIN_HDR_SIZE)
- return;
- i= TCP_MIN_HDR_SIZE;
- while (i<tcp_hdr_len)
- {
- cp= ((u8_t *)tcp_hdr)+i;
- type= cp[0];
- if (type == TCP_OPT_NOP)
- {
- i++;
- continue;
- }
- if (type == TCP_OPT_EOL)
- break;
- if (i+2 > tcp_hdr_len)
- break; /* No length field */
- len= cp[1];
- if (len < 2)
- break; /* Length too short */
- if (i+len > tcp_hdr_len)
- break; /* Truncated option */
- i += len;
- switch(type)
- {
- case TCP_OPT_MSS:
- if (len != 4)
- break;
- mss= (cp[2] << 8) | cp[3];
- DBLOCK(1, printf("tcp_extract_tcpopt: got mss %d\n",
- mss););
- *mssp= mss;
- break;
- case TCP_OPT_WSOPT: /* window scale option */
- case TCP_OPT_SACKOK: /* SACK permitted */
- case TCP_OPT_TS: /* Timestamps option */
- case TCP_OPT_CCNEW: /* new connection count */
- /* Ignore this option. */
- break;
- default:
- DBLOCK(0x1,
- printf(
- "tcp_extract_tcpopt: unknown option %d, len %d\n",
- type, len));
- break;
- }
- }
-}
-
-u16_t tcp_pack_oneCsum(ip_hdr, tcp_pack)
-ip_hdr_t *ip_hdr;
-acc_t *tcp_pack;
-{
- size_t ip_hdr_len;
- acc_t *pack;
- u16_t sum;
- u16_t word_buf[6];
- int odd_length;
- char *data_ptr;
- int length;
-
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- word_buf[0]= ip_hdr->ih_src & 0xffff;
- word_buf[1]= (ip_hdr->ih_src >> 16) & 0xffff;
- word_buf[2]= ip_hdr->ih_dst & 0xffff;
- word_buf[3]= (ip_hdr->ih_dst >> 16) & 0xffff;
- word_buf[4]= HTONS(IPPROTO_TCP);
- word_buf[5]= htons(ntohs(ip_hdr->ih_length)-ip_hdr_len);
- sum= oneC_sum(0, word_buf, sizeof(word_buf));
-
- pack= tcp_pack;
- odd_length= 0;
- for (; pack; pack= pack->acc_next)
- {
-
- data_ptr= ptr2acc_data(pack);
- length= pack->acc_length;
-
- if (!length)
- continue;
- sum= oneC_sum (sum, (u16_t *)data_ptr, length);
- if (length & 1)
- {
- odd_length= !odd_length;
- sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
- }
- }
- if (odd_length)
- {
- /* Undo the last swap */
- sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
- }
- return sum;
-}
-
-void tcp_get_ipopt(tcp_conn, ip_hdropt)
-tcp_conn_t *tcp_conn;
-ip_hdropt_t *ip_hdropt;
-{
- if (!tcp_conn->tc_remipopt)
- {
- ip_hdropt->iho_opt_siz= 0;
- return;
- }
- DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
- ip_hdropt->iho_opt_siz= 0;
- return;
-}
-
-void tcp_get_tcpopt(tcp_conn, tcp_hdropt)
-tcp_conn_t *tcp_conn;
-tcp_hdropt_t *tcp_hdropt;
-{
- int optsiz;
-
- if (!tcp_conn->tc_tcpopt)
- {
- tcp_hdropt->tho_opt_siz= 0;
- return;
- }
- tcp_conn->tc_tcpopt= bf_pack(tcp_conn->tc_tcpopt);
- optsiz= bf_bufsize(tcp_conn->tc_tcpopt);
- memcpy(tcp_hdropt->tho_data, ptr2acc_data(tcp_conn->tc_tcpopt),
- optsiz);
- if ((optsiz & 3) != 0)
- {
- tcp_hdropt->tho_data[optsiz]= TCP_OPT_EOL;
- optsiz= (optsiz+3) & ~3;
- }
- tcp_hdropt->tho_opt_siz= optsiz;
-
- return;
-}
-
-acc_t *tcp_make_header(tcp_conn, ref_ip_hdr, ref_tcp_hdr, data)
-tcp_conn_t *tcp_conn;
-ip_hdr_t **ref_ip_hdr;
-tcp_hdr_t **ref_tcp_hdr;
-acc_t *data;
-{
- ip_hdropt_t ip_hdropt;
- tcp_hdropt_t tcp_hdropt;
- ip_hdr_t *ip_hdr;
- tcp_hdr_t *tcp_hdr;
- acc_t *hdr_acc;
- char *ptr2hdr;
- int closed_connection;
-
- closed_connection= (tcp_conn->tc_state == TCS_CLOSED);
-
- if (tcp_conn->tc_remipopt || tcp_conn->tc_tcpopt)
- {
- tcp_get_ipopt (tcp_conn, &ip_hdropt);
- tcp_get_tcpopt (tcp_conn, &tcp_hdropt);
- assert (!(ip_hdropt.iho_opt_siz & 3));
- assert (!(tcp_hdropt.tho_opt_siz & 3));
-
- hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+
- ip_hdropt.iho_opt_siz+TCP_MIN_HDR_SIZE+
- tcp_hdropt.tho_opt_siz);
- ptr2hdr= ptr2acc_data(hdr_acc);
-
- ip_hdr= (ip_hdr_t *)ptr2hdr;
- ptr2hdr += IP_MIN_HDR_SIZE;
-
- if (ip_hdropt.iho_opt_siz)
- {
- memcpy(ptr2hdr, (char *)ip_hdropt.iho_data,
- ip_hdropt.iho_opt_siz);
- }
- ptr2hdr += ip_hdropt.iho_opt_siz;
-
- tcp_hdr= (tcp_hdr_t *)ptr2hdr;
- ptr2hdr += TCP_MIN_HDR_SIZE;
-
- if (tcp_hdropt.tho_opt_siz)
- {
- memcpy (ptr2hdr, (char *)tcp_hdropt.tho_data,
- tcp_hdropt.tho_opt_siz);
- }
- hdr_acc->acc_next= data;
-
- ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+
- ip_hdropt.iho_opt_siz) >> 2;
- tcp_hdr->th_data_off= (TCP_MIN_HDR_SIZE+
- tcp_hdropt.tho_opt_siz) << 2;
- }
- else
- {
- hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+TCP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(hdr_acc);
- tcp_hdr= (tcp_hdr_t *)&ip_hdr[1];
- hdr_acc->acc_next= data;
-
- ip_hdr->ih_vers_ihl= IP_MIN_HDR_SIZE >> 2;
- tcp_hdr->th_data_off= TCP_MIN_HDR_SIZE << 2;
- }
-
- if (!closed_connection && (tcp_conn->tc_state == TCS_CLOSED))
- {
- DBLOCK(1, printf("connection closed while inuse\n"));
- bf_afree(hdr_acc);
- return 0;
- }
-
- ip_hdr->ih_tos= tcp_conn->tc_tos;
- ip_hdr->ih_ttl= tcp_conn->tc_ttl;
- ip_hdr->ih_proto= IPPROTO_TCP;
- ip_hdr->ih_src= tcp_conn->tc_locaddr;
- ip_hdr->ih_dst= tcp_conn->tc_remaddr;
- ip_hdr->ih_flags_fragoff= 0;
- if (tcp_conn->tc_flags & TCF_PMTU)
- ip_hdr->ih_flags_fragoff |= HTONS(IH_DONT_FRAG);
-
- tcp_hdr->th_srcport= tcp_conn->tc_locport;
- tcp_hdr->th_dstport= tcp_conn->tc_remport;
- tcp_hdr->th_seq_nr= tcp_conn->tc_RCV_NXT;
- tcp_hdr->th_flags= 0;
- tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO);
- tcp_hdr->th_chksum= 0;
- *ref_ip_hdr= ip_hdr;
- *ref_tcp_hdr= tcp_hdr;
- return hdr_acc;
-}
-
-void tcp_print_state (tcp_conn)
-tcp_conn_t *tcp_conn;
-{
-#if DEBUG
- printf("tcp_conn_table[%d]->tc_state= ", tcp_conn-
- tcp_conn_table);
- if (!(tcp_conn->tc_flags & TCF_INUSE))
- {
- printf("not inuse\n");
- return;
- }
- switch (tcp_conn->tc_state)
- {
- case TCS_CLOSED: printf("CLOSED"); break;
- case TCS_LISTEN: printf("LISTEN"); break;
- case TCS_SYN_RECEIVED: printf("SYN_RECEIVED"); break;
- case TCS_SYN_SENT: printf("SYN_SENT"); break;
- case TCS_ESTABLISHED: printf("ESTABLISHED"); break;
- case TCS_CLOSING: printf("CLOSING"); break;
- default: printf("unknown (=%d)", tcp_conn->tc_state); break;
- }
-#endif
-}
-
-int tcp_check_conn(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- int allright;
- u32_t lo_queue, hi_queue;
- int size;
-
- allright= TRUE;
- if (tcp_conn->tc_inconsistent)
- {
- assert(tcp_conn->tc_inconsistent == 1);
- printf("tcp_check_conn: connection is inconsistent\n");
- return allright;
- }
-
- /* checking receive queue */
- lo_queue= tcp_conn->tc_RCV_LO;
- if (lo_queue == tcp_conn->tc_IRS)
- lo_queue++;
- if (lo_queue == tcp_conn->tc_RCV_NXT && (tcp_conn->tc_flags &
- TCF_FIN_RECV))
- lo_queue--;
- hi_queue= tcp_conn->tc_RCV_NXT;
- if (hi_queue == tcp_conn->tc_IRS)
- hi_queue++;
- if (tcp_conn->tc_flags & TCF_FIN_RECV)
- hi_queue--;
-
- size= hi_queue-lo_queue;
- if (size<0)
- {
- printf("rcv hi_queue-lo_queue < 0\n");
- printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n",
- (unsigned long)tcp_conn->tc_SND_NXT,
- (unsigned long)tcp_conn->tc_SND_UNA);
- printf("lo_queue= 0x%lx, hi_queue= 0x%lx\n",
- (unsigned long)lo_queue,
- (unsigned long)hi_queue);
- printf("size= %d\n", size);
- allright= FALSE;
- }
- else if (!tcp_conn->tc_rcvd_data)
- {
- if (size)
- {
- printf("RCV_NXT-RCV_LO != 0\n");
- tcp_print_conn(tcp_conn);
- printf("lo_queue= %u, hi_queue= %u\n",
- lo_queue, hi_queue);
- allright= FALSE;
- }
- }
- else if (size != bf_bufsize(tcp_conn->tc_rcvd_data))
- {
- printf("RCV_NXT-RCV_LO != sizeof tc_rcvd_data\n");
- tcp_print_conn(tcp_conn);
- printf(
- "lo_queue= %u, hi_queue= %u, sizeof tc_rcvd_data= %d\n",
- lo_queue, hi_queue, bf_bufsize(tcp_conn->tc_rcvd_data));
- allright= FALSE;
- }
- else if (size != 0 && (tcp_conn->tc_state == TCS_CLOSED ||
- tcp_conn->tc_state == TCS_LISTEN ||
- tcp_conn->tc_state == TCS_SYN_RECEIVED ||
- tcp_conn->tc_state == TCS_SYN_SENT))
- {
- printf("received data but not connected\n");
- tcp_print_conn(tcp_conn);
- allright= FALSE;
- }
- if (tcp_Lmod4G(tcp_conn->tc_RCV_HI, tcp_conn->tc_RCV_NXT))
- {
- printf("tc_RCV_HI (0x%lx) < tc_RCV_NXT (0x%lx)\n",
- (unsigned long)tcp_conn->tc_RCV_HI,
- (unsigned long)tcp_conn->tc_RCV_NXT);
- allright= FALSE;
- }
-
- /* checking send data */
- lo_queue= tcp_conn->tc_SND_UNA;
- if (lo_queue == tcp_conn->tc_ISS)
- lo_queue++;
- if (lo_queue == tcp_conn->tc_SND_NXT &&
- (tcp_conn->tc_flags & TCF_FIN_SENT))
- {
- lo_queue--;
- }
- hi_queue= tcp_conn->tc_SND_NXT;
- if (hi_queue == tcp_conn->tc_ISS)
- hi_queue++;
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- hi_queue--;
-
- size= hi_queue-lo_queue;
- if (size<0)
- {
- printf("snd hi_queue-lo_queue < 0\n");
- printf("SND_ISS= 0x%lx, SND_UNA= 0x%lx, SND_NXT= 0x%lx\n",
- (unsigned long)tcp_conn->tc_ISS,
- (unsigned long)tcp_conn->tc_SND_UNA,
- (unsigned long)tcp_conn->tc_SND_NXT);
- printf("hi_queue= 0x%lx, lo_queue= 0x%lx, size= %d\n",
- (unsigned long)hi_queue, (unsigned long)lo_queue,
- size);
- allright= FALSE;
- }
- else if (!tcp_conn->tc_send_data)
- {
- if (size)
- {
- printf("SND_NXT-SND_UNA != 0\n");
- printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n",
- (unsigned long)tcp_conn->tc_SND_NXT,
- (unsigned long)tcp_conn->tc_SND_UNA);
- printf("lo_queue= 0x%lx, hi_queue= 0x%lx\n",
- (unsigned long)lo_queue,
- (unsigned long)hi_queue);
- allright= FALSE;
- }
- }
- else if (size != bf_bufsize(tcp_conn->tc_send_data))
- {
- printf("SND_NXT-SND_UNA != sizeof tc_send_data\n");
- printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n",
- (unsigned long)tcp_conn->tc_SND_NXT,
- (unsigned long)tcp_conn->tc_SND_UNA);
- printf("lo_queue= 0x%lx, lo_queue= 0x%lx\n",
- (unsigned long)lo_queue,
- (unsigned long)hi_queue);
- printf("bf_bufsize(data)= %d\n",
- bf_bufsize(tcp_conn->tc_send_data));
-
- allright= FALSE;
- }
-
- /* checking counters */
- if (!tcp_GEmod4G(tcp_conn->tc_SND_UNA, tcp_conn->tc_ISS))
- {
- printf("SND_UNA < ISS\n");
- allright= FALSE;
- }
- if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA))
- {
- printf("SND_NXT<SND_UNA\n");
- allright= FALSE;
- }
- if (!tcp_GEmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_SND_UNA))
- {
- printf("SND_TRM<SND_UNA\n");
- allright= FALSE;
- }
- if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_TRM))
- {
- printf("SND_NXT<SND_TRM\n");
- allright= FALSE;
- }
-
- DIFBLOCK(1, (!allright), printf("tcp_check_conn: not allright\n"));
- return allright;
-}
-
-void tcp_print_pack(ip_hdr, tcp_hdr)
-ip_hdr_t *ip_hdr;
-tcp_hdr_t *tcp_hdr;
-{
- int tcp_hdr_len;
-
- assert(tcp_hdr);
- if (ip_hdr)
- writeIpAddr(ip_hdr->ih_src);
- else
- printf("???");
- printf(",%u ", ntohs(tcp_hdr->th_srcport));
- if (ip_hdr)
- writeIpAddr(ip_hdr->ih_dst);
- else
- printf("???");
- printf(",%u ", ntohs(tcp_hdr->th_dstport));
- printf(" 0x%x", ntohl(tcp_hdr->th_seq_nr));
- if (tcp_hdr->th_flags & THF_FIN)
- printf(" <FIN>");
- if (tcp_hdr->th_flags & THF_SYN)
- printf(" <SYN>");
- if (tcp_hdr->th_flags & THF_RST)
- printf(" <RST>");
- if (tcp_hdr->th_flags & THF_PSH)
- printf(" <PSH>");
- if (tcp_hdr->th_flags & THF_ACK)
- printf(" <ACK 0x%x %u>", ntohl(tcp_hdr->th_ack_nr),
- ntohs(tcp_hdr->th_window));
- if (tcp_hdr->th_flags & THF_URG)
- printf(" <URG %u>", tcp_hdr->th_urgptr);
- tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
- if (tcp_hdr_len != TCP_MIN_HDR_SIZE)
- printf(" <options %d>", tcp_hdr_len-TCP_MIN_HDR_SIZE);
-}
-
-void tcp_print_conn(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- u32_t iss, irs;
- tcp_fd_t *tcp_fd;
-
- iss= tcp_conn->tc_ISS;
- irs= tcp_conn->tc_IRS;
-
- tcp_print_state (tcp_conn);
- printf(
- " ISS 0x%x UNA +0x%x(0x%x) TRM +0x%x(0x%x) NXT +0x%x(0x%x)",
- iss, tcp_conn->tc_SND_UNA-iss, tcp_conn->tc_SND_UNA,
- tcp_conn->tc_SND_TRM-iss, tcp_conn->tc_SND_TRM,
- tcp_conn->tc_SND_NXT-iss, tcp_conn->tc_SND_NXT);
- printf(
- " UP +0x%x(0x%x) PSH +0x%x(0x%x) ",
- tcp_conn->tc_SND_UP-iss, tcp_conn->tc_SND_UP,
- tcp_conn->tc_SND_PSH-iss, tcp_conn->tc_SND_PSH);
- printf(" snd_cwnd +0x%x(0x%x)",
- tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA,
- tcp_conn->tc_snd_cwnd);
- printf(" transmit_seq ");
- if (tcp_conn->tc_transmit_seq == 0)
- printf("0");
- else
- {
- printf("+0x%x(0x%x)", tcp_conn->tc_transmit_seq-iss,
- tcp_conn->tc_transmit_seq);
- }
- printf(" IRS 0x%x LO +0x%x(0x%x) NXT +0x%x(0x%x) HI +0x%x(0x%x)",
- irs, tcp_conn->tc_RCV_LO-irs, tcp_conn->tc_RCV_LO,
- tcp_conn->tc_RCV_NXT-irs, tcp_conn->tc_RCV_NXT,
- tcp_conn->tc_RCV_HI-irs, tcp_conn->tc_RCV_HI);
- if (tcp_conn->tc_flags & TCF_INUSE)
- printf(" TCF_INUSE");
- if (tcp_conn->tc_flags & TCF_FIN_RECV)
- printf(" TCF_FIN_RECV");
- if (tcp_conn->tc_flags & TCF_RCV_PUSH)
- printf(" TCF_RCV_PUSH");
- if (tcp_conn->tc_flags & TCF_MORE2WRITE)
- printf(" TCF_MORE2WRITE");
- if (tcp_conn->tc_flags & TCF_SEND_ACK)
- printf(" TCF_SEND_ACK");
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- printf(" TCF_FIN_SENT");
- if (tcp_conn->tc_flags & TCF_BSD_URG)
- printf(" TCF_BSD_URG");
- if (tcp_conn->tc_flags & TCF_NO_PUSH)
- printf(" TCF_NO_PUSH");
- if (tcp_conn->tc_flags & TCF_PUSH_NOW)
- printf(" TCF_PUSH_NOW");
- if (tcp_conn->tc_flags & TCF_PMTU)
- printf(" TCF_PMTU");
- printf("\n");
- writeIpAddr(tcp_conn->tc_locaddr);
- printf(", %u -> ", ntohs(tcp_conn->tc_locport));
- writeIpAddr(tcp_conn->tc_remaddr);
- printf(", %u\n", ntohs(tcp_conn->tc_remport));
- tcp_fd= tcp_conn->tc_fd;
- if (!tcp_fd)
- printf("tc_fd NULL");
- else
- {
- printf("tc_fd #%d: flags 0x%lx, r %u@%u, w %u@%u",
- tcp_fd-tcp_fd_table, tcp_fd->tf_flags,
- tcp_fd->tf_read_count, tcp_fd->tf_read_offset,
- tcp_fd->tf_write_count, tcp_fd->tf_write_offset);
- }
-}
-
-/*
- * $PchId: tcp_lib.c,v 1.14 2005/01/31 21:41:38 philip Exp $
- */
+++ /dev/null
-/*
-tcp_recv.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "type.h"
-#include "sr.h"
-
-#include "io.h"
-#include "tcp_int.h"
-#include "tcp.h"
-#include "assert.h"
-
-THIS_FILE
-
-static void create_RST ARGS(( tcp_conn_t *tcp_conn,
- ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr, int data_len ));
-static void process_data ARGS(( tcp_conn_t *tcp_conn,
- tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
-static void process_advanced_data ARGS(( tcp_conn_t *tcp_conn,
- tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
-
-void tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data, data_len)
-tcp_conn_t *tcp_conn;
-ip_hdr_t *ip_hdr;
-tcp_hdr_t *tcp_hdr;
-acc_t *tcp_data;
-size_t data_len;
-{
- tcp_fd_t *connuser;
- int tcp_hdr_flags;
- u32_t seg_ack, seg_seq, rcv_hi, snd_una, snd_nxt;
- u16_t seg_wnd, mtu;
- size_t mss;
- int acceptable_ACK, segm_acceptable, send_rst, close_connection;
-
- tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
- seg_ack= ntohl(tcp_hdr->th_ack_nr);
- seg_seq= ntohl(tcp_hdr->th_seq_nr);
- seg_wnd= ntohs(tcp_hdr->th_window);
-
-#if 0
- { where(); tcp_print_conn(tcp_conn); printf("\n");
- tcp_print_pack(ip_hdr, tcp_hdr); printf("\n"); }
-#endif
-
- switch (tcp_conn->tc_state)
- {
- case TCS_CLOSED:
-/*
-CLOSED:
- discard all data.
- !RST ?
- ACK ?
- <SEQ=SEG.ACK><CTL=RST>
- exit
- :
- <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
- exit
- :
- discard packet
- exit
-*/
-
- if (!(tcp_hdr_flags & THF_RST))
- {
- create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len);
- tcp_conn_write(tcp_conn, 1);
- }
- break;
- case TCS_LISTEN:
-/*
-LISTEN:
- RST ?
- discard packet
- exit
- ACK ?
- <SEQ=SEG.ACK><CTL=RST>
- exit
- SYN ?
- BUG: no security check
- RCV.NXT= SEG.SEQ+1
- IRS= SEG.SEQ
- ISS should already be selected
- <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
- SND.NXT=ISS+1
- SND.UNA=ISS
- state= SYN-RECEIVED
- exit
- :
- shouldnot occur
- discard packet
- exit
-*/
- if (tcp_hdr_flags & THF_RST)
- break;
- if (tcp_hdr_flags & THF_ACK)
- {
- create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
- tcp_conn_write(tcp_conn, 1);
- break;
- }
- if (tcp_hdr_flags & THF_SYN)
- {
- tcp_extract_ipopt(tcp_conn, ip_hdr);
- tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
- mtu= mss+IP_TCP_MIN_HDR_SIZE;
- if (mtu < IP_MIN_MTU)
- {
- /* No or unrealistic mss, use default MTU */
- mtu= IP_DEF_MTU;
- }
- if (mtu < tcp_conn->tc_max_mtu)
- {
- tcp_conn->tc_max_mtu= mtu;
- tcp_conn->tc_mtu= mtu;
- DBLOCK(1, printf(
- "tcp[%d]: conn[%d]: mtu = %d\n",
- tcp_conn->tc_port-tcp_port_table,
- tcp_conn-tcp_conn_table,
- mtu););
- }
-
- tcp_conn->tc_RCV_LO= seg_seq+1;
- tcp_conn->tc_RCV_NXT= seg_seq+1;
- tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
- tcp_conn->tc_rcv_wnd;
- tcp_conn->tc_RCV_UP= seg_seq;
- tcp_conn->tc_IRS= seg_seq;
- tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
- tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
- tcp_conn->tc_SND_UP= tcp_conn->tc_ISS-1;
- tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS-1;
- tcp_conn->tc_state= TCS_SYN_RECEIVED;
- tcp_conn->tc_stt= 0;
- assert (tcp_check_conn(tcp_conn));
- tcp_conn->tc_locaddr= ip_hdr->ih_dst;
- tcp_conn->tc_locport= tcp_hdr->th_dstport;
- tcp_conn->tc_remaddr= ip_hdr->ih_src;
- tcp_conn->tc_remport= tcp_hdr->th_srcport;
- tcp_conn_write(tcp_conn, 1);
-
- DIFBLOCK(0x10, seg_seq == 0,
- printf("warning got 0 IRS from ");
- writeIpAddr(tcp_conn->tc_remaddr);
- printf("\n"));
-
- /* Start the timer (if necessary) */
- tcp_set_send_timer(tcp_conn);
-
- break;
- }
- /* do nothing */
- break;
- case TCS_SYN_SENT:
-/*
-SYN-SENT:
- ACK ?
- SEG.ACK <= ISS || SEG.ACK > SND.NXT ?
- RST ?
- discard packet
- exit
- :
- <SEQ=SEG.ACK><CTL=RST>
- exit
- SND.UNA <= SEG.ACK && SEG.ACK <= SND.NXT ?
- ACK is acceptable
- :
- ACK is !acceptable
- :
- ACK is !acceptable
- RST ?
- ACK acceptable ?
- discard segment
- state= CLOSED
- error "connection refused"
- exit
- :
- discard packet
- exit
- BUG: no security check
- SYN ?
- IRS= SEG.SEQ
- RCV.NXT= IRS+1
- ACK ?
- SND.UNA= SEG.ACK
- SND.UNA > ISS ?
- state= ESTABLISHED
- <SEQ=SND.NXT><ACK= RCV.NXT><CTL=ACK>
- process ev. URG and text
- exit
- :
- state= SYN-RECEIVED
- SND.WND= SEG.WND
- SND.WL1= SEG.SEQ
- SND.WL2= SEG.ACK
- <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
- exit
- :
- discard segment
- exit
-*/
- if (tcp_hdr_flags & THF_ACK)
- {
- if (tcp_LEmod4G(seg_ack, tcp_conn->tc_ISS) ||
- tcp_Gmod4G(seg_ack, tcp_conn->tc_SND_NXT)) {
- if (tcp_hdr_flags & THF_RST)
- break;
- else
- {
- /* HACK: force sending a RST,
- * normally, RSTs are not send
- * if the segment is an ACK.
- */
- create_RST (tcp_conn, ip_hdr,
- tcp_hdr, data_len+1);
- tcp_conn_write(tcp_conn, 1);
- break;
- }
- }
- acceptable_ACK= (tcp_LEmod4G(tcp_conn->tc_SND_UNA,
- seg_ack) && tcp_LEmod4G(seg_ack,
- tcp_conn->tc_SND_NXT));
- }
- else
- acceptable_ACK= FALSE;
- if (tcp_hdr_flags & THF_RST)
- {
- if (acceptable_ACK)
- {
- DBLOCK(1, printf(
- "calling tcp_close_connection\n"));
-
- tcp_close_connection(tcp_conn,
- ECONNREFUSED);
- }
- break;
- }
- if (tcp_hdr_flags & THF_SYN)
- {
- tcp_extract_ipopt(tcp_conn, ip_hdr);
- tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
- mtu= mss+IP_TCP_MIN_HDR_SIZE;
- if (mtu < IP_MIN_MTU)
- {
- /* No or unrealistic mss, use default MTU */
- mtu= IP_DEF_MTU;
- }
- if (mtu < tcp_conn->tc_max_mtu)
- {
- tcp_conn->tc_max_mtu= mtu;
- tcp_conn->tc_mtu= mtu;
- DBLOCK(1, printf(
- "tcp[%d]: conn[%d]: mtu = %d\n",
- tcp_conn->tc_port-tcp_port_table,
- tcp_conn-tcp_conn_table,
- mtu););
- }
- tcp_conn->tc_RCV_LO= seg_seq+1;
- tcp_conn->tc_RCV_NXT= seg_seq+1;
- tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
- tcp_conn->tc_rcv_wnd;
- tcp_conn->tc_RCV_UP= seg_seq;
- tcp_conn->tc_IRS= seg_seq;
- if (tcp_hdr_flags & THF_ACK)
- tcp_conn->tc_SND_UNA= seg_ack;
- if (tcp_Gmod4G(tcp_conn->tc_SND_UNA,
- tcp_conn->tc_ISS))
- {
- tcp_conn->tc_state= TCS_ESTABLISHED;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
-
- assert (tcp_check_conn(tcp_conn));
- assert(tcp_conn->tc_connInprogress);
-
- tcp_restart_connect(tcp_conn);
-
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
- if (data_len != 0)
- {
- tcp_frag2conn(tcp_conn, ip_hdr,
- tcp_hdr, tcp_data, data_len);
- /* tcp_data is already freed */
- return;
- }
- break;
- }
- tcp_conn->tc_state= TCS_SYN_RECEIVED;
-
- assert (tcp_check_conn(tcp_conn));
-
- tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
- tcp_conn_write(tcp_conn, 1);
- }
- break;
-
- case TCS_SYN_RECEIVED:
-/*
-SYN-RECEIVED:
- test if segment is acceptable:
-
- Segment Receive Test
- Length Window
- 0 0 SEG.SEQ == RCV.NXT
- 0 >0 RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND
- >0 0 not acceptable
- >0 >0 (RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND)
- || (RCV.NXT <= SEG.SEQ+SEG.LEN-1 &&
- SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND)
- for urgent data: use RCV.WND+1 for RCV.WND
-
- Special: Send RST if SEG.SEQ < IRS or SEG.SEQ > RCV.NXT+64K (and
- the packet is not a RST packet itself).
-*/
- rcv_hi= tcp_conn->tc_RCV_HI;
- if (tcp_hdr_flags & THF_URG)
- rcv_hi++;
- send_rst= tcp_Lmod4G(seg_seq, tcp_conn->tc_IRS) ||
- tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT+0x10000);
- close_connection= 0;
-
- if (!data_len)
- {
- if (rcv_hi == tcp_conn->tc_RCV_NXT)
- segm_acceptable= (seg_seq == rcv_hi);
- else
- {
- assert (tcp_Gmod4G(rcv_hi,
- tcp_conn->tc_RCV_NXT));
- segm_acceptable= (tcp_LEmod4G(tcp_conn->
- tc_RCV_NXT, seg_seq) &&
- tcp_Lmod4G(seg_seq, rcv_hi));
- }
- }
- else
- {
- if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
- {
- segm_acceptable= (tcp_LEmod4G(tcp_conn->
- tc_RCV_NXT, seg_seq) &&
- tcp_Lmod4G(seg_seq, rcv_hi)) ||
- (tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
- seg_seq+data_len-1) &&
- tcp_Lmod4G(seg_seq+data_len-1,
- rcv_hi));
- }
- else
- {
- segm_acceptable= FALSE;
- }
- }
-/*
- !segment acceptable ?
- RST ?
- discard packet
- exit
- :
- <SEG=SND.NXT><ACK=RCV.NXT><CTL=ACK>
- exit
-*/
- if (!segm_acceptable)
- {
- if (tcp_hdr_flags & THF_RST)
- ; /* do nothing */
- else if (send_rst)
- {
- create_RST(tcp_conn, ip_hdr, tcp_hdr,
- data_len);
- tcp_conn_write(tcp_conn, 1);
- }
- else
- {
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
- }
- break;
- }
-/*
- RST ?
- initiated by a LISTEN ?
- state= LISTEN
- exit
- :
- state= CLOSED
- error "connection refused"
- exit
-*/
-
- if (tcp_hdr_flags & THF_RST)
- close_connection= 1;
-
-/*
- SYN in window ?
- initiated by a LISTEN ?
- state= LISTEN
- exit
- :
- state= CLOSED
- error "connection reset"
- exit
-*/
- if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
- tcp_conn->tc_RCV_NXT))
- {
- close_connection= 1;
- }
-
- if (close_connection)
- {
- if (!tcp_conn->tc_orglisten)
- {
- tcp_close_connection(tcp_conn, ECONNREFUSED);
- break;
- }
-
- connuser= tcp_conn->tc_fd;
- assert(connuser);
- if (connuser->tf_flags & TFF_LISTENQ)
- {
- tcp_close_connection (tcp_conn,
- ECONNREFUSED);
- }
- else
- {
- tcp_conn->tc_connInprogress= 0;
- tcp_conn->tc_fd= NULL;
-
- tcp_close_connection (tcp_conn,
- ECONNREFUSED);
-
- /* Pick a new ISS next time */
- tcp_conn->tc_ISS= 0;
-
- (void)tcp_su4listen(connuser, tcp_conn,
- 0 /* !do_listenq */);
- }
- break;
- }
-/*
- !ACK ?
- discard packet
- exit
-*/
- if (!(tcp_hdr_flags & THF_ACK))
- break;
-/*
- SND.UNA < SEG.ACK <= SND.NXT ?
- state= ESTABLISHED
- :
- <SEG=SEG.ACK><CTL=RST>
- exit
-*/
- if (tcp_Lmod4G(tcp_conn->tc_SND_UNA, seg_ack) &&
- tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT))
- {
- tcp_conn->tc_state= TCS_ESTABLISHED;
- tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
-
- tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
-
- assert (tcp_check_conn(tcp_conn));
- assert(tcp_conn->tc_connInprogress);
-
- tcp_restart_connect(tcp_conn);
- tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data,
- data_len);
- /* tcp_data is already freed */
- return;
- }
- else
- {
- create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
- tcp_conn_write(tcp_conn, 1);
- break;
- }
- break;
-
- case TCS_ESTABLISHED:
- case TCS_CLOSING:
-/*
-ESTABLISHED:
-FIN-WAIT-1:
-FIN-WAIT-2:
-CLOSE-WAIT:
-CLOSING:
-LAST-ACK:
-TIME-WAIT:
- test if segment is acceptable:
- Segment Receive Test
- Length Window
- 0 0 SEG.SEQ == RCV.NXT
- 0 >0 RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND
- >0 0 not acceptable
- >0 >0 (RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND)
- || (RCV.NXT <= SEG.SEQ+SEG.LEN-1 &&
- SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND)
- for urgent data: use RCV.WND+1 for RCV.WND
-*/
- rcv_hi= tcp_conn->tc_RCV_HI;
- if (tcp_hdr_flags & THF_URG)
- rcv_hi++;
- if (!data_len)
- {
- if (rcv_hi == tcp_conn->tc_RCV_NXT)
- segm_acceptable= (seg_seq == rcv_hi);
- else
- {
- assert (tcp_Gmod4G(rcv_hi,
- tcp_conn->tc_RCV_NXT));
- segm_acceptable= (tcp_LEmod4G(tcp_conn->
- tc_RCV_NXT, seg_seq) &&
- tcp_Lmod4G(seg_seq, rcv_hi));
- }
- }
- else
- {
- if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
- {
- segm_acceptable= (tcp_LEmod4G(tcp_conn->
- tc_RCV_NXT, seg_seq) &&
- tcp_Lmod4G(seg_seq, rcv_hi)) ||
- (tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
- seg_seq+data_len-1) &&
- tcp_Lmod4G(seg_seq+data_len-1,
- rcv_hi));
- }
- else
- {
- segm_acceptable= FALSE;
- }
- }
-/*
- !segment acceptable ?
- RST ?
- discard packet
- exit
- :
- <SEG=SND.NXT><ACK=RCV.NXT><CTL=ACK>
- exit
-*/
- if (!segm_acceptable)
- {
- if (!(tcp_hdr_flags & THF_RST))
- {
- DBLOCK(0x20,
- printf("segment is not acceptable\n");
- printf("\t");
- tcp_print_pack(ip_hdr, tcp_hdr);
- printf("\n\t");
- tcp_print_conn(tcp_conn);
- printf("\n"));
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
-
- /* Sometimes, a retransmission sets the PSH
- * flag (Solaris 2.4)
- */
- if (tcp_conn->tc_rcvd_data != NULL &&
- (tcp_hdr_flags & THF_PSH))
- {
- tcp_conn->tc_flags |= TCF_RCV_PUSH;
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags &
- TFF_READ_IP))
- {
- tcp_fd_read(tcp_conn, 1);
- }
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags &
- TFF_SEL_READ))
- {
- tcp_rsel_read(tcp_conn);
- }
- }
- }
- break;
- }
-/*
- RST ?
- state == CLOSING || state == LAST-ACK ||
- state == TIME-WAIT ?
- state= CLOSED
- exit
- :
- state= CLOSED
- error "connection reset"
- exit
-*/
- if (tcp_hdr_flags & THF_RST)
- {
- if ((tcp_conn->tc_flags &
- (TCF_FIN_SENT|TCF_FIN_RECV)) ==
- (TCF_FIN_SENT|TCF_FIN_RECV) &&
- tcp_conn->tc_send_data == NULL)
- {
- /* Clean shutdown, but the other side
- * doesn't want to ACK our FIN.
- */
- tcp_close_connection (tcp_conn, 0);
- }
- else
- tcp_close_connection(tcp_conn, ECONNRESET);
- break;
- }
-/*
- SYN in window ?
- state= CLOSED
- error "connection reset"
- exit
-*/
- if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
- tcp_conn->tc_RCV_NXT))
- {
- tcp_close_connection(tcp_conn, ECONNRESET);
- break;
- }
-/*
- !ACK ?
- discard packet
- exit
-*/
- if (!(tcp_hdr_flags & THF_ACK))
- break;
-
-/*
- SND.UNA < SEG.ACK <= SND.NXT ?
- SND.UNA= SEG.ACK
- reply "send ok"
- SND.WL1 < SEG.SEQ || (SND.WL1 == SEG.SEQ &&
- SND.WL2 <= SEG.ACK ?
- SND.WND= SEG.WND
- SND.Wl1= SEG.SEQ
- SND.WL2= SEG.ACK
- SEG.ACK <= SND.UNA ?
- ignore ACK
- SEG.ACK > SND.NXT ?
- <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
- discard packet
- exit
-*/
-
- /* Always reset the send timer after a valid ack is
- * received. The assumption is that either the ack really
- * acknowledges some data (normal case), contains a zero
- * window, or the remote host has another reason not
- * to accept any data. In all cases, the remote host is
- * alive, so the connection should stay alive too.
- * Do not reset stt if the state is CLOSING, i.e. if
- * the user closed the connection and we still have
- * some data to deliver. We don't want a zero window
- * to keep us from closing the connection.
- */
- if (tcp_conn->tc_state != TCS_CLOSING)
- tcp_conn->tc_stt= 0;
-
- snd_una= tcp_conn->tc_SND_UNA;
- snd_nxt= tcp_conn->tc_SND_NXT;
- if (seg_ack == snd_una)
- {
-
- if (tcp_Gmod4G(snd_nxt, snd_una))
- {
- /* Duplicate ACK */
- if (++tcp_conn->tc_snd_dack ==
- TCP_DACK_RETRANS)
- {
- tcp_fast_retrans(tcp_conn);
- }
- }
-
- /* This ACK doesn't acknowledge any new data, this
- * is a likely situation if we are only receiving
- * data. We only update the window if we are
- * actually sending or if we currently have a
- * zero window.
- */
- if (tcp_conn->tc_snd_cwnd == snd_una &&
- seg_wnd != 0)
- {
- DBLOCK(2, printf("zero window opened\n"));
- /* The other side opened up its receive
- * window. */
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
- if (seg_wnd > 2*mss)
- seg_wnd= 2*mss;
- tcp_conn->tc_snd_cwnd= snd_una+seg_wnd;
- tcp_conn_write(tcp_conn, 1);
- }
- if (seg_wnd == 0)
- {
- tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_TRM=
- snd_una;
- }
- }
- else if (tcp_Lmod4G(snd_una, seg_ack) &&
- tcp_LEmod4G(seg_ack, snd_nxt))
- {
- tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
- if (tcp_conn->tc_state == TCS_CLOSED)
- break;
- }
- else if (tcp_Gmod4G(seg_ack,
- snd_nxt))
- {
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
- DBLOCK(1, printf(
- "got an ack of something I haven't send\n");
- printf( "seg_ack= %u, SND_NXT= %u\n",
- seg_ack, snd_nxt));
- break;
- }
-
-/*
- process data...
-*/
- tcp_extract_ipopt(tcp_conn, ip_hdr);
- tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
-
- if (data_len)
- {
- if (tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT))
- {
- process_data (tcp_conn, tcp_hdr,
- tcp_data, data_len);
- }
- else
- {
- process_advanced_data (tcp_conn,
- tcp_hdr, tcp_data, data_len);
- }
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
-
- /* Don't process a FIN if we got new data */
- break;
- }
-/*
- FIN ?
- reply pending receives
- advace RCV.NXT over the FIN
- <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
-
- state == ESTABLISHED ?
- state= CLOSE-WAIT
- state == FIN-WAIT-1 ?
- state= CLOSING
- state == FIN-WAIT-2 ?
- state= TIME-WAIT
- state == TIME-WAIT ?
- restart the TIME-WAIT timer
- exit
-*/
- if ((tcp_hdr_flags & THF_FIN) && tcp_LEmod4G(seg_seq,
- tcp_conn->tc_RCV_NXT))
- {
- if (!(tcp_conn->tc_flags & TCF_FIN_RECV) &&
- tcp_Lmod4G(tcp_conn->tc_RCV_NXT,
- tcp_conn->tc_RCV_HI))
- {
- tcp_conn->tc_RCV_NXT++;
- tcp_conn->tc_flags |= TCF_FIN_RECV;
- }
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
- {
- tcp_fd_read(tcp_conn, 1);
- }
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
- {
- tcp_rsel_read(tcp_conn);
- }
- }
- break;
- default:
- printf("tcp_frag2conn: unknown state ");
- tcp_print_state(tcp_conn);
- break;
- }
- if (tcp_data != NULL)
- bf_afree(tcp_data);
-}
-
-
-static void
-process_data(tcp_conn, tcp_hdr, tcp_data, data_len)
-tcp_conn_t *tcp_conn;
-tcp_hdr_t *tcp_hdr;
-acc_t *tcp_data;
-int data_len;
-{
- u32_t lo_seq, hi_seq, urg_seq, seq_nr, adv_seq, nxt;
- u32_t urgptr;
- int tcp_hdr_flags;
- unsigned int offset;
- acc_t *tmp_data, *rcvd_data, *adv_data;
- int len_diff;
-
- assert(tcp_conn->tc_busy);
-
- /* Note, tcp_data will be freed by the caller. */
- assert (!(tcp_hdr->th_flags & THF_SYN));
-
- seq_nr= ntohl(tcp_hdr->th_seq_nr);
- urgptr= ntohs(tcp_hdr->th_urgptr);
-
- tcp_data->acc_linkC++;
-
- lo_seq= seq_nr;
- tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
-
- if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
- {
- DBLOCK(0x10,
- printf("segment is a retransmission\n"));
- offset= tcp_conn->tc_RCV_NXT-lo_seq;
- tcp_data= bf_delhead(tcp_data, offset);
- lo_seq += offset;
- data_len -= offset;
- if (tcp_hdr_flags & THF_URG)
- {
- printf("process_data: updating urgent pointer\n");
- if (urgptr >= offset)
- urgptr -= offset;
- else
- tcp_hdr_flags &= ~THF_URG;
- }
- }
- assert (lo_seq == tcp_conn->tc_RCV_NXT);
-
- if (tcp_hdr_flags & THF_URG)
- {
- if (!(tcp_conn->tc_flags & TCF_BSD_URG))
- {
- /* Update urgent pointer to point past the urgent
- * data
- */
- urgptr++;
- }
- if (urgptr == 0)
- tcp_hdr_flags &= ~THF_URG;
- }
-
- if (tcp_hdr_flags & THF_URG)
- {
- if (urgptr > data_len)
- urgptr= data_len;
- urg_seq= lo_seq+urgptr;
-
- if (tcp_GEmod4G(urg_seq, tcp_conn->tc_RCV_HI))
- urg_seq= tcp_conn->tc_RCV_HI;
- if (tcp_conn->tc_flags & TCF_BSD_URG)
- {
- if (tcp_Gmod4G(tcp_conn->tc_RCV_NXT,
- tcp_conn->tc_RCV_LO))
- {
- DBLOCK(1, printf(
- "ignoring urgent data\n"));
-
- bf_afree(tcp_data);
- /* Should set advertised window to
- * zero */
-
- /* Flush */
- tcp_conn->tc_flags |= TCF_RCV_PUSH;
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags &
- TFF_READ_IP))
- {
- tcp_fd_read(tcp_conn, 1);
- }
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags &
- TFF_SEL_READ))
- {
- tcp_rsel_read(tcp_conn);
- }
- return;
- }
- }
- if (tcp_Gmod4G(urg_seq, tcp_conn->tc_RCV_UP))
- tcp_conn->tc_RCV_UP= urg_seq;
-#if 0
- if (urgptr < data_len)
- {
- data_len= urgptr;
- tmp_data= bf_cut(tcp_data, 0, data_len);
- bf_afree(tcp_data);
- tcp_data= tmp_data;
- tcp_hdr_flags &= ~THF_FIN;
- }
-#endif
- tcp_conn->tc_flags |= TCF_RCV_PUSH;
- }
- else
- {
- /* Normal data. */
- }
-
- if (tcp_hdr_flags & THF_PSH)
- {
- tcp_conn->tc_flags |= TCF_RCV_PUSH;
- }
-
- hi_seq= lo_seq+data_len;
- if (tcp_Gmod4G(hi_seq, tcp_conn->tc_RCV_HI))
- {
- data_len= tcp_conn->tc_RCV_HI-lo_seq;
- tmp_data= bf_cut(tcp_data, 0, data_len);
- bf_afree(tcp_data);
- tcp_data= tmp_data;
- hi_seq= lo_seq+data_len;
- tcp_hdr_flags &= ~THF_FIN;
- }
- assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
-
- rcvd_data= tcp_conn->tc_rcvd_data;
- tcp_conn->tc_rcvd_data= 0;
- tmp_data= bf_append(rcvd_data, tcp_data);
- tcp_conn->tc_rcvd_data= tmp_data;
- tcp_conn->tc_RCV_NXT= hi_seq;
-
- if ((tcp_hdr_flags & THF_FIN) &&
- tcp_Lmod4G(tcp_conn->tc_RCV_NXT, tcp_conn->tc_RCV_HI) &&
- !(tcp_conn->tc_flags & TCF_FIN_RECV))
- {
- tcp_conn->tc_RCV_NXT++;
- tcp_conn->tc_flags |= TCF_FIN_RECV;
- }
-
- if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
- tcp_fd_read(tcp_conn, 1);
- if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
- tcp_rsel_read(tcp_conn);
-
- DIFBLOCK(2, (tcp_conn->tc_RCV_NXT == tcp_conn->tc_RCV_HI),
- printf("conn[[%d] full receive buffer\n",
- tcp_conn-tcp_conn_table));
-
- if (tcp_conn->tc_adv_data == NULL)
- return;
- if (tcp_hdr_flags & THF_FIN)
- {
- printf("conn[%d]: advanced data after FIN\n",
- tcp_conn-tcp_conn_table);
- tcp_data= tcp_conn->tc_adv_data;
- tcp_conn->tc_adv_data= NULL;
- bf_afree(tcp_data);
- return;
- }
-
- lo_seq= tcp_conn->tc_adv_seq;
- if (tcp_Gmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
- return; /* Not yet */
-
- tcp_data= tcp_conn->tc_adv_data;
- tcp_conn->tc_adv_data= NULL;
-
- data_len= bf_bufsize(tcp_data);
- if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
- {
- offset= tcp_conn->tc_RCV_NXT-lo_seq;
- if (offset >= data_len)
- {
- bf_afree(tcp_data);
- return;
- }
- tcp_data= bf_delhead(tcp_data, offset);
- lo_seq += offset;
- data_len -= offset;
- }
- assert (lo_seq == tcp_conn->tc_RCV_NXT);
-
- hi_seq= lo_seq+data_len;
- assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
-
- rcvd_data= tcp_conn->tc_rcvd_data;
- tcp_conn->tc_rcvd_data= 0;
- tmp_data= bf_append(rcvd_data, tcp_data);
- tcp_conn->tc_rcvd_data= tmp_data;
- tcp_conn->tc_RCV_NXT= hi_seq;
-
- assert (tcp_conn->tc_RCV_LO + bf_bufsize(tcp_conn->tc_rcvd_data) ==
- tcp_conn->tc_RCV_NXT ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
-
- if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
- tcp_fd_read(tcp_conn, 1);
- if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
- tcp_rsel_read(tcp_conn);
-
- adv_data= tcp_conn->tc_adv_data;
- if (adv_data != NULL)
- {
- /* Try to use advanced data. */
- adv_seq= tcp_conn->tc_adv_seq;
- nxt= tcp_conn->tc_RCV_NXT;
-
- if (tcp_Gmod4G(adv_seq, nxt))
- return; /* not yet */
-
- tcp_conn->tc_adv_data= NULL;
- data_len= bf_bufsize(adv_data);
-
- if (tcp_Lmod4G(adv_seq, nxt))
- {
- if (tcp_LEmod4G(adv_seq+data_len, nxt))
- {
- /* Data is not needed anymore. */
- bf_afree(adv_data);
- return;
- }
-
- len_diff= nxt-adv_seq;
- adv_data= bf_delhead(adv_data, len_diff);
- data_len -= len_diff;
- }
-
- DBLOCK(1, printf("using advanced data\n"));
-
- /* Append data to the input buffer */
- if (tcp_conn->tc_rcvd_data == NULL)
- {
- tcp_conn->tc_rcvd_data= adv_data;
- }
- else
- {
- tcp_conn->tc_rcvd_data=
- bf_append(tcp_conn->tc_rcvd_data, adv_data);
- }
- tcp_conn->tc_SND_NXT += data_len;
- assert(tcp_check_conn(tcp_conn));
-
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
- {
- tcp_fd_read(tcp_conn, 1);
- }
- if (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
- {
- tcp_rsel_read(tcp_conn);
- }
- }
-}
-
-static void process_advanced_data(tcp_conn, tcp_hdr, tcp_data, data_len)
-tcp_conn_t *tcp_conn;
-tcp_hdr_t *tcp_hdr;
-acc_t *tcp_data;
-int data_len;
-{
- u32_t seq, adv_seq;
- acc_t *adv_data;
-
- assert(tcp_conn->tc_busy);
-
- /* Note, tcp_data will be freed by the caller. */
-
- /* Always send an ACK, this allows the sender to do a fast
- * retransmit.
- */
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- tcp_conn_write(tcp_conn, 1);
-
- if (tcp_hdr->th_flags & THF_URG)
- return; /* Urgent data is to complicated */
-
- if (tcp_hdr->th_flags & THF_PSH)
- tcp_conn->tc_flags |= TCF_RCV_PUSH;
- seq= ntohl(tcp_hdr->th_seq_nr);
-
- /* Make sure that the packet doesn't fall outside of the window
- * we offered.
- */
- if (tcp_Gmod4G(seq+data_len, tcp_conn->tc_RCV_HI))
- return;
-
- adv_data= tcp_conn->tc_adv_data;
- adv_seq= tcp_conn->tc_adv_seq;
- tcp_conn->tc_adv_data= NULL;
-
- tcp_data->acc_linkC++;
- if (adv_data == NULL)
- {
- adv_seq= seq;
- adv_data= tcp_data;
- }
- else if (seq + data_len == adv_seq)
- {
- /* New data fits right before exiting data. */
- adv_data= bf_append(tcp_data, adv_data);
- adv_seq= seq;
- }
- else if (adv_seq + bf_bufsize(adv_data) == seq)
- {
- /* New data fits right after exiting data. */
- adv_data= bf_append(adv_data, tcp_data);
- }
- else
- {
- /* New data doesn't fit. */
- bf_afree(tcp_data);
- }
- tcp_conn->tc_adv_data= adv_data;
- tcp_conn->tc_adv_seq= adv_seq;
-}
-
-static void create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len)
-tcp_conn_t *tcp_conn;
-ip_hdr_t *ip_hdr;
-tcp_hdr_t *tcp_hdr;
-int data_len;
-{
- acc_t *tmp_ipopt, *tmp_tcpopt, *tcp_pack;
- acc_t *RST_acc;
- ip_hdr_t *RST_ip_hdr;
- tcp_hdr_t *RST_tcp_hdr;
- size_t pack_size, ip_hdr_len, mss;
-
- DBLOCK(0x10, printf("in create_RST, bad pack is:\n");
- tcp_print_pack(ip_hdr, tcp_hdr); tcp_print_state(tcp_conn);
- printf("\n"));
-
- assert(tcp_conn->tc_busy);
-
- /* Only send RST packets in reponse to actual data (or SYN, FIN)
- * this solves a problem during connection shutdown. The problem
- * is the follow senario: a senders closes the connection instead
- * of doing a shutdown and waiting for the receiver to shutdown.
- * The receiver is slow in processing the last data. After the
- * sender has completely closed the connection, the receiver
- * sends a window update which triggers the sender to send a
- * RST. The receiver closes the connection in reponse to the RST.
- */
- if ((tcp_hdr->th_flags & (THF_FIN|THF_SYN)) == 0 &&
- data_len == 0)
- {
-#if DEBUG
- { printf("tcp_recv`create_RST: no data, no RST\n"); }
-#endif
- return;
- }
-
- tmp_ipopt= tcp_conn->tc_remipopt;
- if (tmp_ipopt)
- tmp_ipopt->acc_linkC++;
- tmp_tcpopt= tcp_conn->tc_tcpopt;
- if (tmp_tcpopt)
- tmp_tcpopt->acc_linkC++;
-
- tcp_extract_ipopt (tcp_conn, ip_hdr);
- tcp_extract_tcpopt (tcp_conn, tcp_hdr, &mss);
-
- RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,
- (acc_t *)0);
-
- if (tcp_conn->tc_remipopt)
- bf_afree(tcp_conn->tc_remipopt);
- tcp_conn->tc_remipopt= tmp_ipopt;
- if (tcp_conn->tc_tcpopt)
- bf_afree(tcp_conn->tc_tcpopt);
- tcp_conn->tc_tcpopt= tmp_tcpopt;
-
- RST_ip_hdr->ih_src= ip_hdr->ih_dst;
- RST_ip_hdr->ih_dst= ip_hdr->ih_src;
-
- RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport;
- RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport;
- if (tcp_hdr->th_flags & THF_ACK)
- {
- RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr;
- RST_tcp_hdr->th_flags= THF_RST;
- }
- else
- {
- RST_tcp_hdr->th_seq_nr= 0;
- RST_tcp_hdr->th_ack_nr=
- htonl(
- ntohl(tcp_hdr->th_seq_nr)+
- data_len +
- (tcp_hdr->th_flags & THF_SYN ? 1 : 0) +
- (tcp_hdr->th_flags & THF_FIN ? 1 : 0));
- RST_tcp_hdr->th_flags= THF_RST|THF_ACK;
- }
-
- pack_size= bf_bufsize(RST_acc);
- RST_ip_hdr->ih_length= htons(pack_size);
- RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd);
- RST_tcp_hdr->th_chksum= 0;
-
- RST_acc->acc_linkC++;
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- tcp_pack= bf_delhead(RST_acc, ip_hdr_len);
- RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_ip_hdr, tcp_pack);
- bf_afree(tcp_pack);
-
- DBLOCK(2, tcp_print_pack(ip_hdr, tcp_hdr); printf("\n");
- tcp_print_pack(RST_ip_hdr, RST_tcp_hdr); printf("\n"));
-
- if (tcp_conn->tc_frag2send)
- bf_afree(tcp_conn->tc_frag2send);
- tcp_conn->tc_frag2send= RST_acc;
- tcp_conn_write(tcp_conn, 1);
-}
-
-void
-tcp_fd_read(tcp_conn, enq)
-tcp_conn_t *tcp_conn;
-int enq; /* Enqueue writes. */
-{
- tcp_fd_t *tcp_fd;
- size_t data_size, read_size;
- acc_t *data;
- int fin_recv, urg, push, result;
- i32_t old_window, new_window;
- u16_t mss;
-
- assert(tcp_conn->tc_busy);
-
- tcp_fd= tcp_conn->tc_fd;
-
- assert (tcp_fd->tf_flags & TFF_READ_IP);
- if (tcp_conn->tc_state == TCS_CLOSED)
- {
- if (tcp_fd->tf_read_offset)
- tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
- else
- tcp_reply_read (tcp_fd, tcp_conn->tc_error);
- return;
- }
-
- urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
- push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
- fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
-
- data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
- if (fin_recv)
- data_size--;
- if (urg)
- {
-#if DEBUG
- printf("tcp_fd_read: RCV_UP = 0x%x, RCV_LO = 0x%x\n",
- tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
-#endif
- read_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
- }
- else
- read_size= data_size;
-
- if (read_size >= tcp_fd->tf_read_count)
- read_size= tcp_fd->tf_read_count;
- else if (!push && !fin_recv && !urg &&
- data_size < TCP_MIN_RCV_WND_SIZE)
- {
- /* Defer the copy out until later. */
- return;
- }
- else if (data_size == 0 && !fin_recv)
- {
- /* No data, and no end of file. */
- return;
- }
-
- if (read_size)
- {
- if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
- {
- if (tcp_fd->tf_read_offset)
- {
- tcp_reply_read (tcp_fd,
- tcp_fd->tf_read_offset);
- }
- else
- {
- tcp_reply_read (tcp_fd, EURG);
- }
- return;
- }
- else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
- {
- if (tcp_fd->tf_read_offset)
- {
- tcp_reply_read (tcp_fd,
- tcp_fd->tf_read_offset);
- }
- else
- {
- tcp_reply_read(tcp_fd, ENOURG);
- }
- return;
- }
-
- if (read_size == data_size)
- {
- data= tcp_conn->tc_rcvd_data;
- data->acc_linkC++;
- }
- else
- {
- data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size);
- }
- result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd,
- tcp_fd->tf_read_offset, data, FALSE);
- if (result<0)
- {
- if (tcp_fd->tf_read_offset)
- tcp_reply_read(tcp_fd, tcp_fd->
- tf_read_offset);
- else
- tcp_reply_read(tcp_fd, result);
- return;
- }
- tcp_fd->tf_read_offset += read_size;
- tcp_fd->tf_read_count -= read_size;
-
- if (data_size == read_size)
- {
- bf_afree(tcp_conn->tc_rcvd_data);
- tcp_conn->tc_rcvd_data= 0;
- }
- else
- {
- tcp_conn->tc_rcvd_data=
- bf_delhead(tcp_conn->tc_rcvd_data,
- read_size);
- }
- tcp_conn->tc_RCV_LO += read_size;
- data_size -= read_size;
- }
-
- /* Update IRS and often RCV_UP every 0.5GB */
- if (tcp_conn->tc_RCV_LO - tcp_conn->tc_IRS > 0x40000000)
- {
- tcp_conn->tc_IRS += 0x20000000;
- DBLOCK(1, printf("tcp_fd_read: updating IRS to 0x%lx\n",
- (unsigned long)tcp_conn->tc_IRS););
- if (tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_IRS))
- {
- tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
- DBLOCK(1, printf(
- "tcp_fd_read: updating RCV_UP to 0x%lx\n",
- (unsigned long)tcp_conn->tc_RCV_UP););
- }
- DBLOCK(1, printf("tcp_fd_read: RCP_LO = 0x%lx\n",
- (unsigned long)tcp_conn->tc_RCV_LO););
- }
-
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
- if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO <=
- tcp_conn->tc_rcv_wnd-mss)
- {
- old_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
- tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
- tcp_conn->tc_rcv_wnd;
- new_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
- assert(old_window >=0 && new_window >= old_window);
- if (old_window < mss && new_window >= mss)
- {
- tcp_conn->tc_flags |= TCF_SEND_ACK;
- DBLOCK(2, printf("opening window\n"));
- tcp_conn_write(tcp_conn, 1);
- }
- }
- if (tcp_conn->tc_rcvd_data == NULL &&
- tcp_conn->tc_adv_data == NULL)
- {
- /* Out of data, clear PUSH flag and reply to a read. */
- tcp_conn->tc_flags &= ~TCF_RCV_PUSH;
- }
- if (fin_recv || urg || tcp_fd->tf_read_offset ||
- !tcp_fd->tf_read_count)
- {
- tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
- return;
- }
-}
-
-unsigned
-tcp_sel_read(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- size_t data_size;
- int fin_recv, urg, push;
-
- if (tcp_conn->tc_state == TCS_CLOSED)
- return 1;
-
- fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
- if (fin_recv)
- return 1;
-
- data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
- if (data_size == 0)
- {
- /* No data, and no end of file. */
- return 0;
- }
-
- urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
- push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
-
- if (!push && !urg && data_size < TCP_MIN_RCV_WND_SIZE)
- {
- /* Defer until later. */
- return 0;
- }
-
- return 1;
-}
-
-void
-tcp_rsel_read(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_fd_t *tcp_fd;
-
- if (tcp_sel_read(tcp_conn) == 0)
- return;
-
- tcp_fd= tcp_conn->tc_fd;
- tcp_fd->tf_flags &= ~TFF_SEL_READ;
- if (tcp_fd->tf_select_res)
- tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_READ);
- else
- printf("tcp_rsel_read: no select_res\n");
-}
-
-void tcp_bytesavailable(tcp_fd, bytesp)
-tcp_fd_t *tcp_fd;
-int *bytesp;
-{
- tcp_conn_t *tcp_conn;
- size_t data_size;
- int fin_recv, urg;
-
- *bytesp= 0; /* The default is that nothing is available */
-
- if (!(tcp_fd->tf_flags & TFF_CONNECTED))
- return;
- tcp_conn= tcp_fd->tf_conn;
-
- if (tcp_conn->tc_state == TCS_CLOSED)
- return;
-
- urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
- fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
-
- data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
- if (fin_recv)
- data_size--;
- if (urg)
- data_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
-
- if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
- return;
- else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
- return;
-
- *bytesp= data_size;
-}
-
-/*
- * $PchId: tcp_recv.c,v 1.30 2005/06/28 14:21:35 philip Exp $
- */
+++ /dev/null
-/*
-tcp_send.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "buf.h"
-#include "clock.h"
-#include "event.h"
-#include "type.h"
-#include "sr.h"
-
-#include "assert.h"
-#include "io.h"
-#include "ip.h"
-#include "tcp.h"
-#include "tcp_int.h"
-
-THIS_FILE
-
-static acc_t *make_pack ARGS(( tcp_conn_t *tcp_conn ));
-static void tcp_send_timeout ARGS(( int conn, minix_timer_t *timer ));
-static void do_snd_event ARGS(( event_t *ev, ev_arg_t arg ));
-
-void tcp_conn_write (tcp_conn, enq)
-tcp_conn_t *tcp_conn;
-int enq; /* Writes need to be enqueued. */
-{
- tcp_port_t *tcp_port;
- ev_arg_t snd_arg;
-
- assert (tcp_conn->tc_flags & TCF_INUSE);
-
- tcp_port= tcp_conn->tc_port;
- if (tcp_conn->tc_flags & TCF_MORE2WRITE)
- return;
-
- /* Do we really have something to send here? */
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT &&
- !(tcp_conn->tc_flags & TCF_SEND_ACK) &&
- !tcp_conn->tc_frag2send)
- {
- return;
- }
-
- tcp_conn->tc_flags |= TCF_MORE2WRITE;
- tcp_conn->tc_send_link= NULL;
- if (!tcp_port->tp_snd_head)
- {
- tcp_port->tp_snd_head= tcp_conn;
- tcp_port->tp_snd_tail= tcp_conn;
- if (enq)
- {
- snd_arg.ev_ptr= tcp_port;
- if (!ev_in_queue(&tcp_port->tp_snd_event))
- {
- ev_enqueue(&tcp_port->tp_snd_event,
- do_snd_event, snd_arg);
- }
- }
- else
- tcp_port_write(tcp_port);
- }
- else
- {
- tcp_port->tp_snd_tail->tc_send_link= tcp_conn;
- tcp_port->tp_snd_tail= tcp_conn;
- }
-}
-
-static void do_snd_event(ev, arg)
-event_t *ev;
-ev_arg_t arg;
-{
- tcp_port_t *tcp_port;
-
- tcp_port= arg.ev_ptr;
-
- assert(ev == &tcp_port->tp_snd_event);
- tcp_port_write(tcp_port);
-}
-
-void tcp_port_write(tcp_port)
-tcp_port_t *tcp_port;
-{
- tcp_conn_t *tcp_conn;
- acc_t *pack2write;
- int r;
-
- assert (!(tcp_port->tp_flags & TPF_WRITE_IP));
-
- while(tcp_port->tp_snd_head)
- {
- tcp_conn= tcp_port->tp_snd_head;
- assert(tcp_conn->tc_flags & TCF_MORE2WRITE);
-
- for(;;)
- {
- if (tcp_conn->tc_frag2send)
- {
- pack2write= tcp_conn->tc_frag2send;
- tcp_conn->tc_frag2send= 0;
- }
- else
- {
- tcp_conn->tc_busy++;
- pack2write= make_pack(tcp_conn);
- tcp_conn->tc_busy--;
- if (!pack2write)
- break;
- }
- r= ip_send(tcp_port->tp_ipfd, pack2write,
- bf_bufsize(pack2write));
- if (r != NW_OK)
- {
- if (r == NW_WOULDBLOCK)
- break;
- if (r == EPACKSIZE)
- {
- tcp_mtu_exceeded(tcp_conn);
- continue;
- }
- if (r == EHOSTUNREACH || r == ENETUNREACH ||
- r == ENETDOWN)
- {
- tcp_notreach(tcp_conn, r);
- continue;
- }
- if (r == EAFNOSUPPORT)
- continue;
- }
- assert(r == NW_OK ||
- (printf("ip_send failed, error %d\n", r),0));
- }
-
- if (pack2write)
- {
- tcp_port->tp_flags |= TPF_WRITE_IP;
- tcp_port->tp_pack= pack2write;
-
- r= ip_write (tcp_port->tp_ipfd,
- bf_bufsize(pack2write));
- if (r == NW_SUSPEND)
- {
- tcp_port->tp_flags |= TPF_WRITE_SP;
- return;
- }
- assert(r == NW_OK);
- tcp_port->tp_flags &= ~TPF_WRITE_IP;
- assert(!(tcp_port->tp_flags &
- (TPF_WRITE_IP|TPF_WRITE_SP)));
- continue;
- }
- tcp_conn->tc_flags &= ~TCF_MORE2WRITE;
- tcp_port->tp_snd_head= tcp_conn->tc_send_link;
-
- }
-}
-
-static acc_t *make_pack(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- acc_t *pack2write, *tmp_pack, *tcp_pack;
- tcp_hdr_t *tcp_hdr = NULL;
- ip_hdr_t *ip_hdr = NULL;
- int tot_hdr_size, ip_hdr_len, no_push, head, more2write;
- u32_t seg_seq, seg_lo_data, queue_lo_data, seg_hi, seg_hi_data;
- u16_t seg_up, mss;
- u8_t seg_flags;
- size_t pack_size;
- clock_t curr_time, new_dis;
- u8_t *optptr;
-
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
-
- assert(tcp_conn->tc_busy);
- curr_time= get_time();
- switch (tcp_conn->tc_state)
- {
- case TCS_CLOSED:
- case TCS_LISTEN:
- return NULL;
- case TCS_SYN_RECEIVED:
- case TCS_SYN_SENT:
-
- if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_NXT &&
- !(tcp_conn->tc_flags & TCF_SEND_ACK))
- {
- return 0;
- }
-
- tcp_conn->tc_flags &= ~TCF_SEND_ACK;
-
- /* Advertise a mss based on the port mtu. The current mtu may
- * be lower if the other side sends a smaller mss.
- */
- mss= tcp_conn->tc_port->tp_mtu-IP_TCP_MIN_HDR_SIZE;
-
- /* Include a max segment size option. */
- assert(tcp_conn->tc_tcpopt == NULL);
- tcp_conn->tc_tcpopt= bf_memreq(4);
- optptr= (u8_t *)ptr2acc_data(tcp_conn->tc_tcpopt);
- optptr[0]= TCP_OPT_MSS;
- optptr[1]= 4;
- optptr[2]= mss >> 8;
- optptr[3]= mss & 0xFF;
-
- pack2write= tcp_make_header(tcp_conn, &ip_hdr, &tcp_hdr,
- (acc_t *)0);
-
- bf_afree(tcp_conn->tc_tcpopt);
- tcp_conn->tc_tcpopt= NULL;
-
- if (!pack2write)
- {
- DBLOCK(1, printf("connection closed while inuse\n"));
- return 0;
- }
- tot_hdr_size= bf_bufsize(pack2write);
- seg_seq= tcp_conn->tc_SND_TRM;
- if (tcp_conn->tc_state == TCS_SYN_SENT)
- seg_flags= 0;
- else
- seg_flags= THF_ACK; /* except for TCS_SYN_SENT
- * ack is always present */
-
- if (seg_seq == tcp_conn->tc_ISS)
- {
- assert(tcp_conn->tc_transmit_timer.tim_active ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
- seg_flags |= THF_SYN;
- tcp_conn->tc_SND_TRM++;
- }
-
- tcp_hdr->th_seq_nr= htonl(seg_seq);
- tcp_hdr->th_ack_nr= htonl(tcp_conn->tc_RCV_NXT);
- tcp_hdr->th_flags= seg_flags;
- tcp_hdr->th_window= htons(mss);
- /* Initially we allow one segment */
-
- ip_hdr->ih_length= htons(tot_hdr_size);
-
- pack2write->acc_linkC++;
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- tcp_pack= bf_delhead(pack2write, ip_hdr_len);
- tcp_hdr->th_chksum= ~tcp_pack_oneCsum(ip_hdr, tcp_pack);
- bf_afree(tcp_pack);
-
- new_dis= curr_time + 2*HZ*tcp_conn->tc_ttl;
- if (new_dis > tcp_conn->tc_senddis)
- tcp_conn->tc_senddis= new_dis;
- return pack2write;
-
- case TCS_ESTABLISHED:
- case TCS_CLOSING:
- seg_seq= tcp_conn->tc_SND_TRM;
-
- seg_flags= 0;
- pack2write= 0;
- seg_up= 0;
- if (tcp_conn->tc_flags & TCF_SEND_ACK)
- {
- seg_flags= THF_ACK;
- tcp_conn->tc_flags &= ~TCF_SEND_ACK;
-
- pack2write= tcp_make_header (tcp_conn, &ip_hdr,
- &tcp_hdr, (acc_t *)0);
- if (!pack2write)
- {
- return NULL;
- }
- }
-
- if (tcp_conn->tc_SND_UNA != tcp_conn->tc_SND_NXT)
- {
- assert(tcp_LEmod4G(seg_seq, tcp_conn->tc_SND_NXT));
-
- if (seg_seq == tcp_conn->tc_snd_cwnd)
- {
- DBLOCK(2,
- printf("no data: window is closed\n"));
- goto after_data;
- }
-
- /* Assert that our SYN has been ACKed. */
- assert(tcp_conn->tc_SND_UNA != tcp_conn->tc_ISS);
-
- seg_lo_data= seg_seq;
- queue_lo_data= tcp_conn->tc_SND_UNA;
-
- seg_hi= tcp_conn->tc_SND_NXT;
- seg_hi_data= seg_hi;
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- {
- if (seg_seq != seg_hi)
- seg_flags |= THF_FIN;
- if (queue_lo_data == seg_hi_data)
- queue_lo_data--;
- if (seg_lo_data == seg_hi_data)
- seg_lo_data--;
- seg_hi_data--;
- }
-
- if (!pack2write)
- {
- pack2write= tcp_make_header (tcp_conn,
- &ip_hdr, &tcp_hdr, (acc_t *)0);
- if (!pack2write)
- {
- return NULL;
- }
- }
-
- tot_hdr_size= bf_bufsize(pack2write);
-
- no_push= (tcp_LEmod4G(tcp_conn->tc_SND_PSH, seg_seq));
- head= (seg_seq == tcp_conn->tc_SND_UNA);
- if (no_push)
- {
- /* Shutdown sets SND_PSH */
- seg_flags &= ~THF_FIN;
- if (seg_hi_data-seg_lo_data <= 1)
- {
- /* Allways keep at least one byte
- * for a future push.
- */
- DBLOCK(0x20,
- printf("no data: no push\n"));
- if (head)
- {
- DBLOCK(0x1, printf(
- "no data: setting TCF_NO_PUSH\n"));
- tcp_conn->tc_flags |=
- TCF_NO_PUSH;
- }
- goto after_data;
- }
- seg_hi_data--;
- }
-
- if (tot_hdr_size != IP_TCP_MIN_HDR_SIZE)
- {
- printf(
- "tcp_write`make_pack: tot_hdr_size = %d\n",
- tot_hdr_size);
- mss= tcp_conn->tc_mtu-tot_hdr_size;
- }
- if (seg_hi_data - seg_lo_data > mss)
- {
- /* Truncate to at most one segment */
- seg_hi_data= seg_lo_data + mss;
- seg_hi= seg_hi_data;
- seg_flags &= ~THF_FIN;
- }
-
- if (no_push &&
- seg_hi_data-seg_lo_data != mss)
- {
- DBLOCK(0x20, printf(
- "no data: no push for partial segment\n"));
- more2write= (tcp_conn->tc_fd &&
- (tcp_conn->tc_fd->tf_flags &
- TFF_WRITE_IP));
- DIFBLOCK(2, more2write,
- printf(
- "tcp_send`make_pack: more2write -> !TCF_NO_PUSH\n");
- );
- if (head && !more2write)
- {
- DBLOCK(0x1, printf(
- "partial segment: setting TCF_NO_PUSH\n"));
- tcp_conn->tc_flags |= TCF_NO_PUSH;
- }
- goto after_data;
- }
-
-
- if (tcp_Gmod4G(seg_hi, tcp_conn->tc_snd_cwnd))
- {
- seg_hi_data= tcp_conn->tc_snd_cwnd;
- seg_hi= seg_hi_data;
- seg_flags &= ~THF_FIN;
- }
-
- if (!head &&
- seg_hi_data-seg_lo_data < mss)
- {
- if (tcp_conn->tc_flags & TCF_PUSH_NOW)
- {
- DBLOCK(0x20,
- printf("push: no Nagle\n"));
- }
- else
- {
- DBLOCK(0x20,
- printf("no data: partial packet\n"));
- seg_flags &= ~THF_FIN;
- goto after_data;
- }
- }
-
- if (seg_hi-seg_seq == 0)
- {
- DBLOCK(0x20,
- printf("no data: no data available\n"));
- goto after_data;
- }
-
- if (tcp_GEmod4G(tcp_conn->tc_SND_UP, seg_lo_data))
- {
- extern int killer_inet;
-
- if (tcp_GEmod4G(tcp_conn->tc_SND_UP,
- seg_hi_data))
- {
- seg_up= seg_hi_data-seg_seq;
- }
- else
- {
- seg_up= tcp_conn->tc_SND_UP-seg_seq;
- }
- seg_flags |= THF_URG;
- if (!killer_inet &&
- (tcp_conn->tc_flags & TCF_BSD_URG) &&
- seg_up == 0)
- {
- /* A zero urgent pointer doesn't mean
- * anything when BSD semantics are
- * used (urgent pointer points to the
- * first no urgent byte). The use of
- * a zero urgent pointer also crashes
- * a Solaris 2.3 kernel. If urgent
- * pointer doesn't have BSD semantics
- * then an urgent pointer of zero
- * simply indicates that there is one
- * urgent byte.
- */
- seg_flags &= ~THF_URG;
- }
- }
- else
- seg_up= 0;
-
- if (tcp_Gmod4G(tcp_conn->tc_SND_PSH, seg_lo_data) &&
- tcp_LEmod4G(tcp_conn->tc_SND_PSH, seg_hi_data))
- {
- seg_flags |= THF_PSH;
- }
-
- tcp_conn->tc_SND_TRM= seg_hi;
-
- assert(tcp_conn->tc_transmit_timer.tim_active ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
- if (tcp_conn->tc_rt_seq == 0 &&
- tcp_Gmod4G(seg_seq, tcp_conn->tc_rt_threshold))
- {
- tcp_conn->tc_rt_time= curr_time;
- tcp_conn->tc_rt_seq=
- tcp_conn->tc_rt_threshold= seg_seq;
- }
-
- if (seg_hi_data-seg_lo_data)
- {
-#if DEBUG & 0
- assert(tcp_check_conn(tcp_conn));
- assert((seg_hi_data-queue_lo_data <=
- bf_bufsize(tcp_conn->tc_send_data) &&
- seg_lo_data-queue_lo_data <=
- bf_bufsize(tcp_conn->tc_send_data) &&
- seg_hi_data>seg_lo_data)||
- (tcp_print_conn(tcp_conn),
- printf(
- " seg_hi_data= 0x%x, seg_lo_data= 0x%x, queue_lo_data= 0x%x\n",
- seg_hi_data, seg_lo_data,
- queue_lo_data), 0));
-#endif
-
- tmp_pack= pack2write;
- while (tmp_pack->acc_next)
- tmp_pack= tmp_pack->acc_next;
- tmp_pack->acc_next=
- bf_cut(tcp_conn->tc_send_data,
- (unsigned)(seg_lo_data-queue_lo_data),
- (unsigned) (seg_hi_data-seg_lo_data));
- }
- seg_flags |= THF_ACK;
- }
-
-after_data:
- if (!(seg_flags & THF_ACK))
- {
- if (pack2write)
- bf_afree(pack2write);
- return NULL;
- }
-
- assert( tcp_hdr != NULL );
- assert( ip_hdr != NULL );
- tcp_hdr->th_seq_nr= htonl(seg_seq);
- tcp_hdr->th_ack_nr= htonl(tcp_conn->tc_RCV_NXT);
- tcp_hdr->th_flags= seg_flags;
- tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI -
- tcp_conn->tc_RCV_NXT);
- tcp_hdr->th_urgptr= htons(seg_up);
-
- pack_size= bf_bufsize(pack2write);
- ip_hdr->ih_length= htons(pack_size);
-
- pack2write->acc_linkC++;
- ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- tcp_pack= bf_delhead(pack2write, ip_hdr_len);
- tcp_hdr->th_chksum= ~tcp_pack_oneCsum(ip_hdr, tcp_pack);
- bf_afree(tcp_pack);
-
- new_dis= curr_time + 2*HZ*tcp_conn->tc_ttl;
- if (new_dis > tcp_conn->tc_senddis)
- tcp_conn->tc_senddis= new_dis;
-
- return pack2write;
- default:
- DBLOCK(1, tcp_print_conn(tcp_conn); printf("\n"));
- ip_panic(( "Illegal state" ));
- }
- assert(0);
- return NULL;
-}
-
-/*
-tcp_release_retrans
-*/
-
-void tcp_release_retrans(
- tcp_conn_t *tcp_conn,
- u32_t seg_ack,
- u16_t new_win
-)
-{
- tcp_fd_t *tcp_fd;
- size_t size, offset;
- acc_t *pack;
- clock_t retrans_time, curr_time, rtt, artt, drtt, srtt;
- u32_t queue_lo, queue_hi;
- u16_t mss, cthresh, new_cthresh;
- unsigned window;
-
- DBLOCK(0x10, printf("tcp_release_retrans, conn[%d]: ack %lu, win %u\n",
- tcp_conn-tcp_conn_table, (unsigned long)seg_ack, new_win););
-
- assert(tcp_conn->tc_busy);
- assert (tcp_GEmod4G(seg_ack, tcp_conn->tc_SND_UNA));
- assert (tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT));
-
- tcp_conn->tc_snd_dack= 0;
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
-
- curr_time= get_time();
- if (tcp_conn->tc_rt_seq != 0 &&
- tcp_Gmod4G(seg_ack, tcp_conn->tc_rt_seq))
- {
- assert(curr_time >= tcp_conn->tc_rt_time);
- retrans_time= curr_time-tcp_conn->tc_rt_time;
- rtt= tcp_conn->tc_rtt;
-
- tcp_conn->tc_rt_seq= 0;
-
- if (rtt == TCP_RTT_GRAN*CLOCK_GRAN &&
- retrans_time <= TCP_RTT_GRAN*CLOCK_GRAN)
- {
- /* Common in fast networks. Nothing to do. */
- }
- else
- {
- srtt= retrans_time * TCP_RTT_SCALE;
-
- artt= tcp_conn->tc_artt;
- artt= ((TCP_RTT_SMOOTH-1)*artt+srtt)/TCP_RTT_SMOOTH;
-
- if (srtt < artt)
- srtt = artt - srtt;
- else
- srtt -= artt;
- drtt= tcp_conn->tc_drtt;
- drtt= ((TCP_RTT_SMOOTH-1)*drtt+srtt)/TCP_RTT_SMOOTH;
-
- rtt= (artt+TCP_DRTT_MULT*drtt-1)/TCP_RTT_SCALE+1;
- if (rtt < TCP_RTT_GRAN*CLOCK_GRAN)
- {
- rtt= TCP_RTT_GRAN*CLOCK_GRAN;
- }
- else if (rtt > TCP_RTT_MAX)
- {
-#if DEBUG
- static int warned /* = 0 */;
-
- if (!warned)
- {
- printf(
-"tcp_release_retrans: warning retransmission time is limited to %d ms\n",
- TCP_RTT_MAX*1000/HZ);
- warned= 1;
- }
-#endif
- rtt= TCP_RTT_MAX;
- }
- DBLOCK(0x10, printf(
- "tcp_release_retrans, conn[%i]: retrans_time= %u ms, rtt = %u ms\n",
- tcp_conn-tcp_conn_table,
- retrans_time*1000/HZ,
- rtt*1000/HZ));
-
- DBLOCK(0x10, printf(
- "tcp_release_retrans: artt= %u -> %u, drtt= %u -> %u\n",
- tcp_conn->tc_artt, artt,
- tcp_conn->tc_drtt, drtt));
-
- tcp_conn->tc_artt= artt;
- tcp_conn->tc_drtt= drtt;
- tcp_conn->tc_rtt= rtt;
- }
-
- if (tcp_conn->tc_mtu != tcp_conn->tc_max_mtu &&
- curr_time > tcp_conn->tc_mtutim+TCP_PMTU_INCR_IV)
- {
- tcp_mtu_incr(tcp_conn);
- }
- }
-
- /* Update the current window. */
- window= tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA;
- assert(seg_ack != tcp_conn->tc_SND_UNA);
-
- /* For every real ACK we try to increase the current window
- * with 1 mss.
- */
- window += mss;
-
- /* If the window becomes larger than the current threshold,
- * increment the threshold by a small amount and set the
- * window to the threshold.
- */
- cthresh= tcp_conn->tc_snd_cthresh;
- if (window > cthresh)
- {
- new_cthresh= cthresh + tcp_conn->tc_snd_cinc;
- if (new_cthresh < cthresh)
- new_cthresh= cthresh; /* overflow */
- tcp_conn->tc_snd_cthresh= new_cthresh;
- window= new_cthresh;
- }
-
- /* If the window is larger than the window advertised by the
- * receiver, set the window size to the advertisement.
- */
- if (window > new_win)
- window= new_win;
-
- tcp_conn->tc_snd_cwnd= seg_ack+window;
-
- /* Release data queued for retransmissions. */
- queue_lo= tcp_conn->tc_SND_UNA;
- queue_hi= tcp_conn->tc_SND_NXT;
-
- tcp_conn->tc_SND_UNA= seg_ack;
- if (tcp_Lmod4G(tcp_conn->tc_SND_TRM, seg_ack))
- {
- tcp_conn->tc_SND_TRM= seg_ack;
- }
- assert(tcp_GEmod4G(tcp_conn->tc_snd_cwnd, seg_ack));
-
- /* Advance ISS every 0.5GB to avoid problem with wrap around */
- if (tcp_conn->tc_SND_UNA - tcp_conn->tc_ISS > 0x40000000)
- {
- tcp_conn->tc_ISS += 0x20000000;
- DBLOCK(1, printf(
- "tcp_release_retrans: updating ISS to 0x%lx\n",
- (unsigned long)tcp_conn->tc_ISS););
- if (tcp_Lmod4G(tcp_conn->tc_SND_UP, tcp_conn->tc_ISS))
- {
- tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
- DBLOCK(1, printf(
- "tcp_release_retrans: updating SND_UP to 0x%lx\n",
- (unsigned long)tcp_conn->tc_SND_UP););
- }
- }
-
- if (queue_lo == tcp_conn->tc_ISS)
- queue_lo++;
-
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- {
- if (seg_ack == queue_hi)
- seg_ack--;
- if (queue_lo == queue_hi)
- queue_lo--;
- queue_hi--;
- }
-
- offset= seg_ack - queue_lo;
- size= queue_hi - seg_ack;
- pack= tcp_conn->tc_send_data;
- tcp_conn->tc_send_data= 0;
-
- if (!size)
- {
- bf_afree(pack);
- }
- else
- {
- pack= bf_delhead(pack, offset);
- tcp_conn->tc_send_data= pack;
- }
-
- if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
- tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
-
- /* Copy in new data if an ioctl is pending or if a write request is
- * pending and either the write can be completed or at least one
- * mss buffer space is available.
- */
- tcp_fd= tcp_conn->tc_fd;
- if (tcp_fd)
- {
- if (tcp_fd->tf_flags & TFF_IOCTL_IP)
- {
- tcp_fd_write(tcp_conn);
- }
- if ((tcp_fd->tf_flags & TFF_WRITE_IP) &&
- (size+tcp_fd->tf_write_count <= TCP_MAX_SND_WND_SIZE ||
- size <= TCP_MAX_SND_WND_SIZE-mss))
- {
- tcp_fd_write(tcp_conn);
- }
- if (tcp_fd->tf_flags & TFF_SEL_WRITE)
- tcp_rsel_write(tcp_conn);
- }
- else
- {
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
- {
- assert(tcp_conn->tc_state == TCS_CLOSING);
- DBLOCK(0x10,
- printf("all data sent in abondoned connection\n"));
- tcp_close_connection(tcp_conn, ENOTCONN);
- return;
- }
- }
-
- if (!size && !tcp_conn->tc_send_data)
- {
- /* Reset window if a write is completed */
- tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss;
- }
-
- DIFBLOCK(2, (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_TRM),
- printf("not sending: zero window\n"));
-
- if (tcp_conn->tc_snd_cwnd != tcp_conn->tc_SND_TRM &&
- tcp_conn->tc_SND_NXT != tcp_conn->tc_SND_TRM)
- {
- tcp_conn_write(tcp_conn, 1);
- }
-
-}
-
-/*
-tcp_fast_retrans
-*/
-
-void tcp_fast_retrans(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- u16_t mss, mss2;
-
- /* Update threshold sequence number for retransmission calculation. */
- if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_rt_threshold))
- tcp_conn->tc_rt_threshold= tcp_conn->tc_SND_TRM;
-
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
-
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
- mss2= 2*mss;
-
- if (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_UNA)
- tcp_conn->tc_snd_cwnd++;
- if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_UNA + mss2))
- {
- tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss2;
- if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
- tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
-
- tcp_conn->tc_snd_cthresh /= 2;
- if (tcp_conn->tc_snd_cthresh < mss2)
- tcp_conn->tc_snd_cthresh= mss2;
- }
-
- tcp_conn_write(tcp_conn, 1);
-}
-
-#if 0
-void do_tcp_timeout(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_send_timeout(tcp_conn-tcp_conn_table,
- &tcp_conn->tc_transmit_timer);
-}
-#endif
-
-/*
-tcp_send_timeout
-*/
-
-static void tcp_send_timeout(conn, timer)
-int conn;
-minix_timer_t *timer;
-{
- tcp_conn_t *tcp_conn;
- u16_t mss, mss2;
- u32_t snd_una, snd_nxt;
- clock_t curr_time, rtt, stt, timeout;
- acc_t *pkt;
- int new_ttl, no_push;
-
- DBLOCK(0x20, printf("tcp_send_timeout: conn[%d]\n", conn));
-
- curr_time= get_time();
-
- tcp_conn= &tcp_conn_table[conn];
- assert(tcp_conn->tc_flags & TCF_INUSE);
- assert(tcp_conn->tc_state != TCS_CLOSED);
- assert(tcp_conn->tc_state != TCS_LISTEN);
-
- snd_una= tcp_conn->tc_SND_UNA;
- snd_nxt= tcp_conn->tc_SND_NXT;
- no_push= (tcp_conn->tc_flags & TCF_NO_PUSH);
- if (snd_nxt == snd_una || no_push)
- {
- /* Nothing more to send */
- assert(tcp_conn->tc_SND_TRM == snd_una || no_push);
-
- /* A new write sets the timer if tc_transmit_seq == SND_UNA */
- tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_0wnd_to= 0;
- assert(!tcp_conn->tc_fd ||
- !(tcp_conn->tc_fd->tf_flags & TFF_WRITE_IP) ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
-
- if (snd_nxt != snd_una)
- {
- assert(no_push);
- DBLOCK(1, printf("not setting keepalive timer\n"););
-
- /* No point in setting the keepalive timer if we
- * still have to send more data.
- */
- return;
- }
-
- assert(tcp_conn->tc_send_data == NULL);
- DBLOCK(0x20, printf("keep alive timer\n"));
- if (tcp_conn->tc_ka_snd != tcp_conn->tc_SND_NXT ||
- tcp_conn->tc_ka_rcv != tcp_conn->tc_RCV_NXT)
- {
- tcp_conn->tc_ka_snd= tcp_conn->tc_SND_NXT;
- tcp_conn->tc_ka_rcv= tcp_conn->tc_RCV_NXT;
- DBLOCK(0x20, printf(
-"tcp_send_timeout: conn[%i] setting keepalive timer (+%u ms)\n",
- tcp_conn-tcp_conn_table,
- tcp_conn->tc_ka_time*1000/HZ));
- clck_timer(&tcp_conn->tc_transmit_timer,
- curr_time+tcp_conn->tc_ka_time,
- tcp_send_timeout,
- tcp_conn-tcp_conn_table);
- return;
- }
- DBLOCK(0x10, printf(
- "tcp_send_timeout, conn[%d]: triggering keep alive probe\n",
- tcp_conn-tcp_conn_table));
- tcp_conn->tc_ka_snd--;
- if (!(tcp_conn->tc_flags & TCF_FIN_SENT))
- {
- pkt= bf_memreq(1);
- *ptr2acc_data(pkt)= '\xff'; /* a random char */
- tcp_conn->tc_send_data= pkt; pkt= NULL;
- }
- tcp_conn->tc_SND_UNA--;
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_ISS)
- {
- /* We didn't send anything so far. Retrying the
- * SYN is too hard. Decrement ISS and hope
- * that the other side doesn't care.
- */
- tcp_conn->tc_ISS--;
- }
-
- /* Set tc_transmit_seq and tc_stt to trigger packet */
- tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
- tcp_conn->tc_stt= curr_time;
-
- /* Set tc_rt_seq for round trip measurements */
- tcp_conn->tc_rt_time= curr_time;
- tcp_conn->tc_rt_seq= tcp_conn->tc_SND_UNA;
-
- /* Set PSH to make sure that data gets sent */
- tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
- assert(tcp_check_conn(tcp_conn));
-
- /* Fall through */
- }
-
- rtt= tcp_conn->tc_rtt;
-
- if (tcp_conn->tc_transmit_seq != tcp_conn->tc_SND_UNA)
- {
- /* Some data has been acknowledged since the last time the
- * timer was set, set the timer again. */
- tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
- tcp_conn->tc_stt= 0;
- tcp_conn->tc_0wnd_to= 0;
-
- DBLOCK(0x20, printf(
- "tcp_send_timeout: conn[%i] setting timer to %u ms (+%u ms)\n",
- tcp_conn-tcp_conn_table,
- (curr_time+rtt)*1000/HZ, rtt*1000/HZ));
-
- clck_timer(&tcp_conn->tc_transmit_timer,
- curr_time+rtt, tcp_send_timeout,
- tcp_conn-tcp_conn_table);
- return;
- }
-
- stt= tcp_conn->tc_stt;
- if (stt == 0)
- {
- /* Some packet arrived but did not acknowledge any data.
- * Apparently, the other side is still alive and has a
- * reason to transmit. We can asume a zero window.
- */
-
- DBLOCK(0x10, printf("conn[%d] setting zero window timer\n",
- tcp_conn-tcp_conn_table));
-
- if (tcp_conn->tc_0wnd_to < TCP_0WND_MIN)
- tcp_conn->tc_0wnd_to= TCP_0WND_MIN;
- else if (tcp_conn->tc_0wnd_to < rtt)
- tcp_conn->tc_0wnd_to= rtt;
- else
- {
- tcp_conn->tc_0wnd_to *= 2;
- if (tcp_conn->tc_0wnd_to > TCP_0WND_MAX)
- tcp_conn->tc_0wnd_to= TCP_0WND_MAX;
- }
- tcp_conn->tc_stt= curr_time;
- tcp_conn->tc_rt_seq= 0;
-
- DBLOCK(0x10, printf(
- "tcp_send_timeout: conn[%i] setting timer to %u ms (+%u ms)\n",
- tcp_conn-tcp_conn_table,
- (curr_time+tcp_conn->tc_0wnd_to)*1000/HZ,
- tcp_conn->tc_0wnd_to*1000/HZ));
-
- clck_timer(&tcp_conn->tc_transmit_timer,
- curr_time+tcp_conn->tc_0wnd_to,
- tcp_send_timeout, tcp_conn-tcp_conn_table);
- return;
- }
- assert(stt <= curr_time);
-
- DIFBLOCK(0x10, (tcp_conn->tc_fd == 0),
- printf("conn[%d] timeout in abondoned connection\n",
- tcp_conn-tcp_conn_table));
-
- /* At this point, we have do a retransmission, or send a zero window
- * probe, which is almost the same.
- */
-
- DBLOCK(0x20, printf("tcp_send_timeout: conn[%i] una= %lu, rtt= %u ms\n",
- tcp_conn-tcp_conn_table,
- (unsigned long)tcp_conn->tc_SND_UNA, rtt*1000/HZ));
-
- /* Update threshold sequence number for retransmission calculation. */
- if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_rt_threshold))
- tcp_conn->tc_rt_threshold= tcp_conn->tc_SND_TRM;
-
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
-
- if (tcp_conn->tc_flags & TCF_PMTU &&
- curr_time > stt+TCP_PMTU_BLACKHOLE)
- {
- /* We can't tell the difference between a PMTU blackhole
- * and a broken link. Assume a PMTU blackhole, and switch
- * off PMTU discovery.
- */
- DBLOCK(1, printf(
- "tcp[%d]: PMTU blackhole (or broken link) on route to ",
- tcp_conn-tcp_conn_table);
- writeIpAddr(tcp_conn->tc_remaddr);
- printf(", max mtu = %u\n", tcp_conn->tc_max_mtu););
- tcp_conn->tc_flags &= ~TCF_PMTU;
- tcp_conn->tc_mtutim= curr_time;
- if (tcp_conn->tc_max_mtu > IP_DEF_MTU)
- tcp_conn->tc_mtu= IP_DEF_MTU;
- }
-
- mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
- mss2= 2*mss;
-
- if (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_UNA)
- tcp_conn->tc_snd_cwnd++;
- if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_UNA + mss2))
- {
- tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss2;
- if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
- tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
-
- tcp_conn->tc_snd_cthresh /= 2;
- if (tcp_conn->tc_snd_cthresh < mss2)
- tcp_conn->tc_snd_cthresh= mss2;
- }
-
- if (curr_time-stt > tcp_conn->tc_rt_dead)
- {
- tcp_close_connection(tcp_conn, ETIMEDOUT);
- return;
- }
-
- timeout= (curr_time-stt) >> 3;
- if (timeout < rtt)
- timeout= rtt;
- timeout += curr_time;
-
- DBLOCK(0x20, printf(
- "tcp_send_timeout: conn[%i] setting timer to %u ms (+%u ms)\n",
- tcp_conn-tcp_conn_table, timeout*1000/HZ,
- (timeout-curr_time)*1000/HZ));
-
- clck_timer(&tcp_conn->tc_transmit_timer, timeout,
- tcp_send_timeout, tcp_conn-tcp_conn_table);
-
-#if 0
- if (tcp_conn->tc_rt_seq == 0)
- {
- printf("tcp_send_timeout: conn[%d]: setting tc_rt_time\n",
- tcp_conn-tcp_conn_table);
- tcp_conn->tc_rt_time= curr_time-rtt;
- tcp_conn->tc_rt_seq= tcp_conn->tc_SND_UNA;
- }
-#endif
-
- if (tcp_conn->tc_state == TCS_SYN_SENT ||
- (curr_time-stt >= tcp_conn->tc_ttl*HZ))
- {
- new_ttl= tcp_conn->tc_ttl+1;
- if (new_ttl> IP_MAX_TTL)
- new_ttl= IP_MAX_TTL;
- tcp_conn->tc_ttl= new_ttl;
- }
-
- tcp_conn_write(tcp_conn, 0);
-}
-
-
-void tcp_fd_write(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_fd_t *tcp_fd;
- int urg, nourg, push;
- u32_t max_seq;
- size_t max_trans, write_count;
- acc_t *data, *send_data;
-
- assert(tcp_conn->tc_busy);
- tcp_fd= tcp_conn->tc_fd;
-
- if ((tcp_fd->tf_flags & TFF_IOCTL_IP) &&
- !(tcp_fd->tf_flags & TFF_WRITE_IP))
- {
- if (tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN)
- return;
- DBLOCK(0x10, printf("NWIOTCPSHUTDOWN\n"));
- if (tcp_conn->tc_state == TCS_CLOSED)
- {
- tcp_reply_ioctl (tcp_fd, tcp_conn->tc_error);
- return;
- }
- if (!(tcp_conn->tc_flags & TCF_FIN_SENT))
- {
- DBLOCK(0x10, printf("calling tcp_shutdown\n"));
- tcp_shutdown (tcp_conn);
- }
- else
- {
- if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
- {
- tcp_reply_ioctl (tcp_fd, NW_OK);
- DBLOCK(0x10, printf("shutdown completed\n"));
- }
- else
- {
- DBLOCK(0x10,
- printf("shutdown still inprogress\n"));
- }
- }
- return;
- }
-
- assert (tcp_fd->tf_flags & TFF_WRITE_IP);
- if (tcp_conn->tc_state == TCS_CLOSED)
- {
- if (tcp_fd->tf_write_offset)
- {
- tcp_reply_write(tcp_fd,
- tcp_fd->tf_write_offset);
- }
- else
- tcp_reply_write(tcp_fd, tcp_conn->tc_error);
- return;
- }
-
- urg= (tcp_fd->tf_flags & TFF_WR_URG);
- push= (tcp_fd->tf_flags & TFF_PUSH_DATA);
-
- max_seq= tcp_conn->tc_SND_UNA + TCP_MAX_SND_WND_SIZE;
- max_trans= max_seq - tcp_conn->tc_SND_NXT;
- if (tcp_fd->tf_write_count <= max_trans)
- write_count= tcp_fd->tf_write_count;
- else
- write_count= max_trans;
- if (write_count)
- {
- if (tcp_conn->tc_flags & TCF_BSD_URG)
- {
- if (tcp_Gmod4G(tcp_conn->tc_SND_NXT,
- tcp_conn->tc_SND_UNA))
- {
- nourg= tcp_LEmod4G(tcp_conn->tc_SND_UP,
- tcp_conn->tc_SND_UNA);
- if ((urg && nourg) || (!urg && !nourg))
- {
- DBLOCK(0x20,
- printf("not sending\n"));
- return;
- }
- }
- }
- data= (*tcp_fd->tf_get_userdata)
- (tcp_fd->tf_srfd, tcp_fd->tf_write_offset,
- write_count, FALSE);
-
- if (!data)
- {
- if (tcp_fd->tf_write_offset)
- {
- tcp_reply_write(tcp_fd,
- tcp_fd->tf_write_offset);
- }
- else
- tcp_reply_write(tcp_fd, EFAULT);
- return;
- }
- tcp_fd->tf_write_offset += write_count;
- tcp_fd->tf_write_count -= write_count;
-
- send_data= tcp_conn->tc_send_data;
- tcp_conn->tc_send_data= 0;
- send_data= bf_append(send_data, data);
- tcp_conn->tc_send_data= send_data;
- tcp_conn->tc_SND_NXT += write_count;
- if (urg)
- {
- if (tcp_conn->tc_flags & TCF_BSD_URG)
- tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT;
- else
- tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT-1;
- }
- if (push && !tcp_fd->tf_write_count)
- tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
- }
- if (!tcp_fd->tf_write_count)
- {
- tcp_reply_write(tcp_fd, tcp_fd->tf_write_offset);
- }
-}
-
-unsigned tcp_sel_write(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_fd_t *tcp_fd;
- int urg, nourg;
- u32_t max_seq;
- size_t max_trans;
-
- tcp_fd= tcp_conn->tc_fd;
-
- if (tcp_conn->tc_state == TCS_CLOSED)
- return 1;
-
- urg= (tcp_fd->tf_flags & TFF_WR_URG);
-
- max_seq= tcp_conn->tc_SND_UNA + TCP_MAX_SND_WND_SIZE;
- max_trans= max_seq - tcp_conn->tc_SND_NXT;
- if (max_trans)
- {
- if (tcp_conn->tc_flags & TCF_BSD_URG)
- {
- if (tcp_Gmod4G(tcp_conn->tc_SND_NXT,
- tcp_conn->tc_SND_UNA))
- {
- nourg= tcp_LEmod4G(tcp_conn->tc_SND_UP,
- tcp_conn->tc_SND_UNA);
- if ((urg && nourg) || (!urg && !nourg))
- {
- DBLOCK(0x20,
- printf("not sending\n"));
- return 0;
- }
- }
- }
- return 1;
- }
-
- return 0;
-}
-
-void
-tcp_rsel_write(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- tcp_fd_t *tcp_fd;
-
- if (tcp_sel_write(tcp_conn) == 0)
- return;
-
- tcp_fd= tcp_conn->tc_fd;
- tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
- if (tcp_fd->tf_select_res)
- tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_WRITE);
- else
- printf("tcp_rsel_write: no select_res\n");
-}
-
-/*
-tcp_shutdown
-*/
-
-void tcp_shutdown(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- switch (tcp_conn->tc_state)
- {
- case TCS_CLOSED:
- case TCS_LISTEN:
- case TCS_SYN_SENT:
- case TCS_SYN_RECEIVED:
- tcp_close_connection(tcp_conn, ENOTCONN);
- return;
- }
-
- if (tcp_conn->tc_flags & TCF_FIN_SENT)
- return;
- tcp_conn->tc_flags |= TCF_FIN_SENT;
- tcp_conn->tc_flags &= ~TCF_NO_PUSH;
- tcp_conn->tc_SND_NXT++;
- tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
-
- assert (tcp_check_conn(tcp_conn) ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
-
- tcp_conn_write(tcp_conn, 1);
-
- /* Start the timer */
- tcp_set_send_timer(tcp_conn);
-}
-
-void tcp_set_send_timer(tcp_conn)
-tcp_conn_t *tcp_conn;
-{
- clock_t curr_time;
- clock_t rtt;
-
- assert(tcp_conn->tc_state != TCS_CLOSED);
- assert(tcp_conn->tc_state != TCS_LISTEN);
-
- curr_time= get_time();
- rtt= tcp_conn->tc_rtt;
-
- DBLOCK(0x20, printf(
- "tcp_set_send_timer: conn[%i] setting timer to %u ms (+%u ms)\n",
- tcp_conn-tcp_conn_table,
- (curr_time+rtt)*1000/HZ, rtt*1000/HZ));
-
- /* Start the timer */
- clck_timer(&tcp_conn->tc_transmit_timer,
- curr_time+rtt, tcp_send_timeout, tcp_conn-tcp_conn_table);
- tcp_conn->tc_stt= curr_time;
-}
-
-/*
-tcp_close_connection
-
-*/
-
-void tcp_close_connection(tcp_conn, error)
-tcp_conn_t *tcp_conn;
-int error;
-{
- int i;
- tcp_port_t *tcp_port;
- tcp_fd_t *tcp_fd;
- tcp_conn_t *tc;
-
- assert (tcp_check_conn(tcp_conn) ||
- (tcp_print_conn(tcp_conn), printf("\n"), 0));
- assert (tcp_conn->tc_flags & TCF_INUSE);
-
- tcp_conn->tc_error= error;
- tcp_port= tcp_conn->tc_port;
- tcp_fd= tcp_conn->tc_fd;
- if (tcp_conn->tc_state == TCS_CLOSED)
- return;
-
- tcp_conn->tc_state= TCS_CLOSED;
- DBLOCK(0x10, tcp_print_state(tcp_conn); printf("\n"));
-
- if (tcp_fd && (tcp_fd->tf_flags & TFF_LISTENQ))
- {
- for (i= 0; i<TFL_LISTEN_MAX; i++)
- {
- if (tcp_fd->tf_listenq[i] == tcp_conn)
- break;
- }
- assert(i < TFL_LISTEN_MAX);
- tcp_fd->tf_listenq[i]= NULL;
-
- tcp_conn->tc_connInprogress= 0;
-
- tcp_conn->tc_fd= NULL;
- tcp_fd= NULL;
- }
- else if (tcp_fd)
- {
-
- tcp_conn->tc_busy++;
- assert(tcp_fd->tf_conn == tcp_conn);
-
- if (tcp_fd->tf_flags & TFF_READ_IP)
- tcp_fd_read (tcp_conn, 1);
- assert (!(tcp_fd->tf_flags & TFF_READ_IP));
- if (tcp_fd->tf_flags & TFF_SEL_READ)
- tcp_rsel_read (tcp_conn);
-
- if (tcp_fd->tf_flags & TFF_WRITE_IP)
- {
- tcp_fd_write(tcp_conn);
- tcp_conn_write(tcp_conn, 1);
- }
- assert (!(tcp_fd->tf_flags & TFF_WRITE_IP));
- if (tcp_fd->tf_flags & TFF_IOCTL_IP)
- {
- tcp_fd_write(tcp_conn);
- tcp_conn_write(tcp_conn, 1);
- }
- if (tcp_fd->tf_flags & TFF_IOCTL_IP)
- assert(tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN);
- if (tcp_fd->tf_flags & TFF_SEL_WRITE)
- tcp_rsel_write(tcp_conn);
-
- if (tcp_conn->tc_connInprogress)
- tcp_restart_connect(tcp_conn);
- assert(!tcp_conn->tc_connInprogress);
- assert (!(tcp_fd->tf_flags & TFF_IOCTL_IP) ||
- (printf("req= 0x%lx\n",
- (unsigned long)tcp_fd->tf_ioreq), 0));
- tcp_conn->tc_busy--;
- }
-
- if (tcp_conn->tc_rcvd_data)
- {
- bf_afree(tcp_conn->tc_rcvd_data);
- tcp_conn->tc_rcvd_data= NULL;
- }
- tcp_conn->tc_flags &= ~TCF_FIN_RECV;
- tcp_conn->tc_RCV_LO= tcp_conn->tc_RCV_NXT;
-
- if (tcp_conn->tc_adv_data)
- {
- bf_afree(tcp_conn->tc_adv_data);
- tcp_conn->tc_adv_data= NULL;
- }
-
- if (tcp_conn->tc_send_data)
- {
- bf_afree(tcp_conn->tc_send_data);
- tcp_conn->tc_send_data= NULL;
- tcp_conn->tc_SND_TRM=
- tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA;
- }
- tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA;
-
- if (tcp_conn->tc_remipopt)
- {
- bf_afree(tcp_conn->tc_remipopt);
- tcp_conn->tc_remipopt= NULL;
- }
-
- if (tcp_conn->tc_tcpopt)
- {
- bf_afree(tcp_conn->tc_tcpopt);
- tcp_conn->tc_tcpopt= NULL;
- }
-
- if (tcp_conn->tc_frag2send)
- {
- bf_afree(tcp_conn->tc_frag2send);
- tcp_conn->tc_frag2send= NULL;
- }
- if (tcp_conn->tc_flags & TCF_MORE2WRITE)
- {
- for (tc= tcp_port->tp_snd_head; tc; tc= tc->tc_send_link)
- {
- if (tc->tc_send_link == tcp_conn)
- break;
- }
- if (tc == NULL)
- {
- assert(tcp_port->tp_snd_head == tcp_conn);
- tcp_port->tp_snd_head= tcp_conn->tc_send_link;
- }
- else
- {
- tc->tc_send_link= tcp_conn->tc_send_link;
- if (tc->tc_send_link == NULL)
- tcp_port->tp_snd_tail= tc;
- }
- tcp_conn->tc_flags &= ~TCF_MORE2WRITE;
- }
-
- clck_untimer (&tcp_conn->tc_transmit_timer);
- tcp_conn->tc_transmit_seq= 0;
-
- /* clear all flags but TCF_INUSE */
- tcp_conn->tc_flags &= TCF_INUSE;
- assert (tcp_check_conn(tcp_conn));
-}
-
-/*
- * $PchId: tcp_send.c,v 1.32 2005/06/28 14:21:52 philip Exp $
- */
+++ /dev/null
-/*
-type.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET_TYPE_H
-#define INET_TYPE_H
-
-typedef struct acc *(*get_userdata_t) ARGS(( int fd, size_t offset,
- size_t count, int for_ioctl ));
-typedef int (*put_userdata_t) ARGS(( int fd, size_t offset,
- struct acc *data, int for_ioctl ));
-typedef void (*put_pkt_t) ARGS(( int fd, struct acc *data, size_t datalen ));
-typedef void (*select_res_t) ARGS(( int fd, unsigned ops ));
-
-#endif /* INET_TYPE_H */
-
-/*
- * $PchId: type.h,v 1.6 2005/06/28 14:22:04 philip Exp $
- */
+++ /dev/null
-/*
-udp.c
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "type.h"
-
-#include "assert.h"
-#include "buf.h"
-#include "clock.h"
-#include "icmp_lib.h"
-#include "io.h"
-#include "ip.h"
-#include "sr.h"
-#include "udp.h"
-#include "udp_int.h"
-
-THIS_FILE
-
-static void read_ip_packets ARGS(( udp_port_t *udp_port ));
-static void udp_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void udp_bufcheck ARGS(( void ));
-#endif
-static void udp_main ARGS(( udp_port_t *udp_port ));
-static int udp_select ARGS(( int fd, unsigned operations ));
-static acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count,
- int for_ioctl ));
-static int udp_put_data ARGS(( int fd, size_t offset, acc_t *data,
- int for_ioctl ));
-static int udp_peek ARGS(( udp_fd_t * ));
-static int udp_sel_read ARGS(( udp_fd_t * ));
-static void udp_restart_write_port ARGS(( udp_port_t *udp_port ));
-static void udp_ip_arrived ARGS(( int port, acc_t *pack, size_t pack_size ));
-static void reply_thr_put ARGS(( udp_fd_t *udp_fd, int reply,
- int for_ioctl ));
-static void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,
- int for_ioctl ));
-static int udp_setopt ARGS(( udp_fd_t *udp_fd ));
-static udpport_t find_unused_port ARGS(( int fd ));
-static int is_unused_port ARGS(( udpport_t port ));
-static int udp_packet2user ARGS(( udp_fd_t *udp_fd ));
-static void restart_write_fd ARGS(( udp_fd_t *udp_fd ));
-static u16_t pack_oneCsum ARGS(( acc_t *pack ));
-static void udp_rd_enqueue ARGS(( udp_fd_t *udp_fd, acc_t *pack,
- clock_t exp_tim ));
-static void hash_fd ARGS(( udp_fd_t *udp_fd ));
-static void unhash_fd ARGS(( udp_fd_t *udp_fd ));
-
-udp_port_t *udp_port_table;
-udp_fd_t udp_fd_table[UDP_FD_NR];
-
-void udp_prep()
-{
- udp_port_table= alloc(udp_conf_nr * sizeof(udp_port_table[0]));
-}
-
-void udp_init()
-{
- udp_fd_t *udp_fd;
- udp_port_t *udp_port;
- int i, j, ifno;
-
- assert (BUF_S >= sizeof(struct nwio_ipopt));
- assert (BUF_S >= sizeof(struct nwio_ipconf));
- assert (BUF_S >= sizeof(struct nwio_udpopt));
- assert (BUF_S >= sizeof(struct udp_io_hdr));
- assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));
- assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));
-
- for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
- {
- udp_fd->uf_flags= UFF_EMPTY;
- udp_fd->uf_rdbuf_head= NULL;
- }
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(udp_buffree);
-#else
- bf_logon(udp_buffree, udp_bufcheck);
-#endif
-
- for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
- {
- udp_port->up_ipdev= udp_conf[i].uc_port;
-
- udp_port->up_flags= UPF_EMPTY;
- udp_port->up_state= UPS_EMPTY;
- udp_port->up_next_fd= udp_fd_table;
- udp_port->up_write_fd= NULL;
- udp_port->up_wr_pack= NULL;
- udp_port->up_port_any= NULL;
- for (j= 0; j<UDP_PORT_HASH_NR; j++)
- udp_port->up_port_hash[j]= NULL;
-
- ifno= ip_conf[udp_port->up_ipdev].ic_ifno;
- sr_add_minor(if2minor(ifno, UDP_DEV_OFF),
- i, udp_open, udp_close, udp_read,
- udp_write, udp_ioctl, udp_cancel, udp_select);
-
- udp_main(udp_port);
- }
-}
-
-int udp_open (port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port;
-int srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- int i;
- udp_fd_t *udp_fd;
-
- for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);
- i++);
-
- if (i>= UDP_FD_NR)
- {
- DBLOCK(1, printf("out of fds\n"));
- return EAGAIN;
- }
-
- udp_fd= &udp_fd_table[i];
-
- udp_fd->uf_flags= UFF_INUSE;
- udp_fd->uf_port= &udp_port_table[port];
- udp_fd->uf_srfd= srfd;
- udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;
- udp_fd->uf_get_userdata= get_userdata;
- udp_fd->uf_put_userdata= put_userdata;
- udp_fd->uf_select_res= select_res;
- assert(udp_fd->uf_rdbuf_head == NULL);
- udp_fd->uf_port_next= NULL;
-
- return i;
-
-}
-
-int udp_ioctl (fd, req)
-int fd;
-ioreq_t req;
-{
- udp_fd_t *udp_fd;
- udp_port_t *udp_port;
- nwio_udpopt_t *udp_opt;
- acc_t *opt_acc;
- int result;
-
- udp_fd= &udp_fd_table[fd];
-
-assert (udp_fd->uf_flags & UFF_INUSE);
-
- udp_port= udp_fd->uf_port;
- udp_fd->uf_flags |= UFF_IOCTL_IP;
- udp_fd->uf_ioreq= req;
-
- if (udp_port->up_state != UPS_MAIN)
- return NW_SUSPEND;
-
- switch(req)
- {
- case NWIOSUDPOPT:
- result= udp_setopt(udp_fd);
- break;
- case NWIOGUDPOPT:
- opt_acc= bf_memreq(sizeof(*udp_opt));
-assert (opt_acc->acc_length == sizeof(*udp_opt));
- udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);
-
- *udp_opt= udp_fd->uf_udpopt;
- udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,
- TRUE);
- if (result == NW_OK)
- reply_thr_put(udp_fd, NW_OK, TRUE);
- break;
- case NWIOUDPPEEK:
- result= udp_peek(udp_fd);
- break;
- default:
- reply_thr_get(udp_fd, ENOTTY, TRUE);
- result= NW_OK;
- break;
- }
- if (result != NW_SUSPEND)
- udp_fd->uf_flags &= ~UFF_IOCTL_IP;
- return result;
-}
-
-int udp_read (fd, count)
-int fd;
-size_t count;
-{
- udp_fd_t *udp_fd;
- acc_t *tmp_acc, *next_acc;
-
- udp_fd= &udp_fd_table[fd];
- if (!(udp_fd->uf_flags & UFF_OPTSET))
- {
- reply_thr_put(udp_fd, EBADMODE, FALSE);
- return NW_OK;
- }
-
- udp_fd->uf_rd_count= count;
-
- if (udp_fd->uf_rdbuf_head)
- {
- if (get_time() <= udp_fd->uf_exp_tim)
- return udp_packet2user (udp_fd);
- tmp_acc= udp_fd->uf_rdbuf_head;
- while (tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- udp_fd->uf_rdbuf_head= NULL;
- }
- udp_fd->uf_flags |= UFF_READ_IP;
- return NW_SUSPEND;
-}
-
-static void udp_main(udp_port)
-udp_port_t *udp_port;
-{
- udp_fd_t *udp_fd;
- int result, i;
-
- switch (udp_port->up_state)
- {
- case UPS_EMPTY:
- udp_port->up_state= UPS_SETPROTO;
-
- udp_port->up_ipfd= ip_open(udp_port->up_ipdev,
- udp_port->up_ipdev, udp_get_data, udp_put_data,
- udp_ip_arrived, 0 /* no select_res */);
- if (udp_port->up_ipfd < 0)
- {
- udp_port->up_state= UPS_ERROR;
- DBLOCK(1, printf("%s, %d: unable to open ip port\n",
- __FILE__, __LINE__));
- return;
- }
-
- result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);
- if (result == NW_SUSPEND)
- udp_port->up_flags |= UPF_SUSPEND;
- if (result<0)
- {
- return;
- }
- if (udp_port->up_state != UPS_GETCONF)
- return;
- /* drops through */
- case UPS_GETCONF:
- udp_port->up_flags &= ~UPF_SUSPEND;
-
- result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);
- if (result == NW_SUSPEND)
- udp_port->up_flags |= UPF_SUSPEND;
- if (result<0)
- {
- return;
- }
- if (udp_port->up_state != UPS_MAIN)
- return;
- /* drops through */
- case UPS_MAIN:
- udp_port->up_flags &= ~UPF_SUSPEND;
-
- for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
- {
- if (!(udp_fd->uf_flags & UFF_INUSE))
- continue;
- if (udp_fd->uf_port != udp_port)
- continue;
- if (udp_fd->uf_flags & UFF_IOCTL_IP)
- udp_ioctl(i, udp_fd->uf_ioreq);
- }
- read_ip_packets(udp_port);
- return;
- default:
- DBLOCK(1, printf("udp_port_table[%d].up_state= %d\n",
- udp_port->up_ipdev, udp_port->up_state));
- ip_panic(( "unknown state" ));
- break;
- }
-}
-
-static int udp_select(fd, operations)
-int fd;
-unsigned operations;
-{
- unsigned resops;
- udp_fd_t *udp_fd;
-
- udp_fd= &udp_fd_table[fd];
- assert (udp_fd->uf_flags & UFF_INUSE);
-
- resops= 0;
-
- if (operations & SR_SELECT_READ)
- {
- if (udp_sel_read(udp_fd))
- resops |= SR_SELECT_READ;
- else if (!(operations & SR_SELECT_POLL))
- udp_fd->uf_flags |= UFF_SEL_READ;
- }
- if (operations & SR_SELECT_WRITE)
- {
- /* Should handle special case when the interface is down */
- resops |= SR_SELECT_WRITE;
- }
- if (operations & SR_SELECT_EXCEPTION)
- {
- /* Nothing */
- }
- return resops;
-}
-
-static acc_t *udp_get_data (port, offset, count, for_ioctl)
-int port;
-size_t offset;
-size_t count;
-int for_ioctl;
-{
- udp_port_t *udp_port;
- udp_fd_t *udp_fd;
- int result;
-
- udp_port= &udp_port_table[port];
-
- switch(udp_port->up_state)
- {
- case UPS_SETPROTO:
-assert (for_ioctl);
- if (!count)
- {
- result= (int)offset;
- if (result<0)
- {
- udp_port->up_state= UPS_ERROR;
- break;
- }
- udp_port->up_state= UPS_GETCONF;
- if (udp_port->up_flags & UPF_SUSPEND)
- udp_main(udp_port);
- return NULL;
- }
- else
- {
- struct nwio_ipopt *ipopt;
- acc_t *acc;
-
-assert (!offset);
-assert (count == sizeof(*ipopt));
-
- acc= bf_memreq(sizeof(*ipopt));
- ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
- ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |
- NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC |
- NWIO_HDR_O_ANY | NWIO_RWDATALL;
- ipopt->nwio_proto= IPPROTO_UDP;
- return acc;
- }
- case UPS_MAIN:
-assert (!for_ioctl);
-assert (udp_port->up_flags & UPF_WRITE_IP);
- if (!count)
- {
- result= (int)offset;
-assert (udp_port->up_wr_pack);
- bf_afree(udp_port->up_wr_pack);
- udp_port->up_wr_pack= 0;
- if (udp_port->up_flags & UPF_WRITE_SP)
- {
- if (udp_port->up_write_fd)
- {
- udp_fd= udp_port->up_write_fd;
- udp_port->up_write_fd= NULL;
- udp_fd->uf_flags &= ~UFF_WRITE_IP;
- reply_thr_get(udp_fd, result, FALSE);
- }
- udp_port->up_flags &= ~(UPF_WRITE_SP |
- UPF_WRITE_IP);
- if (udp_port->up_flags & UPF_MORE2WRITE)
- {
- udp_restart_write_port(udp_port);
- }
- }
- else
- udp_port->up_flags &= ~UPF_WRITE_IP;
- }
- else
- {
- return bf_cut (udp_port->up_wr_pack, offset, count);
- }
- break;
- default:
- printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",
- port, offset, count, udp_port->up_state);
- break;
- }
- return NULL;
-}
-
-static int udp_put_data (fd, offset, data, for_ioctl)
-int fd;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- udp_port_t *udp_port;
- int result;
-
- udp_port= &udp_port_table[fd];
-
- switch (udp_port->up_state)
- {
- case UPS_GETCONF:
- if (!data)
- {
- result= (int)offset;
- if (result<0)
- {
- udp_port->up_state= UPS_ERROR;
- return NW_OK;
- }
- udp_port->up_state= UPS_MAIN;
- if (udp_port->up_flags & UPF_SUSPEND)
- udp_main(udp_port);
- }
- else
- {
- struct nwio_ipconf *ipconf;
-
- data= bf_packIffLess(data, sizeof(*ipconf));
- ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
-assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
- udp_port->up_ipaddr= ipconf->nwic_ipaddr;
- bf_afree(data);
- }
- break;
- case UPS_MAIN:
- assert(0);
-
- assert (udp_port->up_flags & UPF_READ_IP);
- if (!data)
- {
- result= (int)offset;
- compare (result, >=, 0);
- if (udp_port->up_flags & UPF_READ_SP)
- {
- udp_port->up_flags &= ~(UPF_READ_SP|
- UPF_READ_IP);
- read_ip_packets(udp_port);
- }
- else
- udp_port->up_flags &= ~UPF_READ_IP;
- }
- else
- {
-assert (!offset); /* This isn't a valid assertion but ip sends only
- * whole datagrams up */
- udp_ip_arrived(fd, data, bf_bufsize(data));
- }
- break;
- default:
- ip_panic((
- "udp_put_data(%d, 0x%x, %p) called but up_state= 0x%x\n",
- fd, offset, data, udp_port->up_state ));
- }
- return NW_OK;
-}
-
-static int udp_setopt(udp_fd)
-udp_fd_t *udp_fd;
-{
- udp_fd_t *fd_ptr;
- nwio_udpopt_t oldopt, newopt;
- acc_t *data;
- unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,
- all_flags, flags;
- unsigned long new_flags;
- int i;
-
- data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
- sizeof(nwio_udpopt_t), TRUE);
-
- if (!data)
- return EFAULT;
-
- data= bf_packIffLess(data, sizeof(nwio_udpopt_t));
-assert (data->acc_length == sizeof(nwio_udpopt_t));
-
- newopt= *(nwio_udpopt_t *)ptr2acc_data(data);
- bf_afree(data);
- oldopt= udp_fd->uf_udpopt;
-
- old_en_flags= oldopt.nwuo_flags & 0xffff;
- old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;
-
- new_en_flags= newopt.nwuo_flags & 0xffff;
- new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;
-
- if (new_en_flags & new_di_flags)
- {
- DBLOCK(1, printf("returning EBADMODE\n"));
-
- reply_thr_get(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- /* NWUO_ACC_MASK */
- if (new_di_flags & NWUO_ACC_MASK)
- {
- DBLOCK(1, printf("returning EBADMODE\n"));
-
- reply_thr_get(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- /* access modes can't be disabled */
- }
-
- if (!(new_en_flags & NWUO_ACC_MASK))
- new_en_flags |= (old_en_flags & NWUO_ACC_MASK);
-
- /* NWUO_LOCPORT_MASK */
- if (new_di_flags & NWUO_LOCPORT_MASK)
- {
- DBLOCK(1, printf("returning EBADMODE\n"));
-
- reply_thr_get(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- /* the loc ports can't be disabled */
- }
- if (!(new_en_flags & NWUO_LOCPORT_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_LOCPORT_MASK);
- newopt.nwuo_locport= oldopt.nwuo_locport;
- }
- else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL)
- {
- newopt.nwuo_locport= find_unused_port(udp_fd-udp_fd_table);
- }
- else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
- {
- if (!newopt.nwuo_locport)
- {
- DBLOCK(1, printf("returning EBADMODE\n"));
-
- reply_thr_get(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
- }
-
- /* NWUO_LOCADDR_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_LOCADDR_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_LOCADDR_MASK);
- new_di_flags |= (old_di_flags & NWUO_LOCADDR_MASK);
- }
-
- /* NWUO_BROAD_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_BROAD_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_BROAD_MASK);
- new_di_flags |= (old_di_flags & NWUO_BROAD_MASK);
- }
-
- /* NWUO_REMPORT_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_REMPORT_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_REMPORT_MASK);
- new_di_flags |= (old_di_flags & NWUO_REMPORT_MASK);
- newopt.nwuo_remport= oldopt.nwuo_remport;
- }
-
- /* NWUO_REMADDR_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_REMADDR_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_REMADDR_MASK);
- new_di_flags |= (old_di_flags & NWUO_REMADDR_MASK);
- newopt.nwuo_remaddr= oldopt.nwuo_remaddr;
- }
-
- /* NWUO_RW_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_RW_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_RW_MASK);
- new_di_flags |= (old_di_flags & NWUO_RW_MASK);
- }
-
- /* NWUO_IPOPT_MASK */
- if (!((new_en_flags | new_di_flags) & NWUO_IPOPT_MASK))
- {
- new_en_flags |= (old_en_flags & NWUO_IPOPT_MASK);
- new_di_flags |= (old_di_flags & NWUO_IPOPT_MASK);
- }
-
- new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
- if ((new_flags & NWUO_RWDATONLY) &&
- ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY ||
- (new_flags & (NWUO_RP_ANY|NWUO_RA_ANY|NWUO_EN_IPOPT))))
- {
- DBLOCK(1, printf("returning EBADMODE\n"));
-
- reply_thr_get(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- /* Check the access modes */
- if ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL ||
- (new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
- {
- for (i= 0, fd_ptr= udp_fd_table; i<UDP_FD_NR; i++, fd_ptr++)
- {
- if (fd_ptr == udp_fd)
- continue;
- if (!(fd_ptr->uf_flags & UFF_INUSE))
- continue;
- if (fd_ptr->uf_port != udp_fd->uf_port)
- continue;
- flags= fd_ptr->uf_udpopt.nwuo_flags;
- if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&
- (flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)
- continue;
- if (fd_ptr->uf_udpopt.nwuo_locport !=
- newopt.nwuo_locport)
- {
- continue;
- }
- if ((flags & NWUO_ACC_MASK) !=
- (new_flags & NWUO_ACC_MASK))
- {
- DBLOCK(1, printf(
- "address inuse: new fd= %d, old_fd= %d, port= %u\n",
- udp_fd-udp_fd_table,
- fd_ptr-udp_fd_table,
- newopt.nwuo_locport));
-
- reply_thr_get(udp_fd, EADDRINUSE, TRUE);
- return NW_OK;
- }
- }
- }
-
- if (udp_fd->uf_flags & UFF_OPTSET)
- unhash_fd(udp_fd);
-
- newopt.nwuo_flags= new_flags;
- udp_fd->uf_udpopt= newopt;
-
- all_flags= new_en_flags | new_di_flags;
- if ((all_flags & NWUO_ACC_MASK) && (all_flags & NWUO_LOCPORT_MASK) &&
- (all_flags & NWUO_LOCADDR_MASK) &&
- (all_flags & NWUO_BROAD_MASK) &&
- (all_flags & NWUO_REMPORT_MASK) &&
- (all_flags & NWUO_REMADDR_MASK) &&
- (all_flags & NWUO_RW_MASK) &&
- (all_flags & NWUO_IPOPT_MASK))
- udp_fd->uf_flags |= UFF_OPTSET;
- else
- {
- udp_fd->uf_flags &= ~UFF_OPTSET;
- }
-
- if (udp_fd->uf_flags & UFF_OPTSET)
- hash_fd(udp_fd);
-
- reply_thr_get(udp_fd, NW_OK, TRUE);
- return NW_OK;
-}
-
-static udpport_t find_unused_port(int fd)
-{
- udpport_t port, nw_port;
-
- for (port= 0x8000+fd; port < 0xffff-UDP_FD_NR; port+= UDP_FD_NR)
- {
- nw_port= htons(port);
- if (is_unused_port(nw_port))
- return nw_port;
- }
- for (port= 0x8000; port < 0xffff; port++)
- {
- nw_port= htons(port);
- if (is_unused_port(nw_port))
- return nw_port;
- }
- ip_panic(( "unable to find unused port (shouldn't occur)" ));
- return 0;
-}
-
-/*
-reply_thr_put
-*/
-
-static void reply_thr_put(udp_fd, reply, for_ioctl)
-udp_fd_t *udp_fd;
-int reply;
-int for_ioctl;
-{
- int result;
-
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,
- (acc_t *)0, for_ioctl);
- assert(result == NW_OK);
-}
-
-/*
-reply_thr_get
-*/
-
-static void reply_thr_get(udp_fd, reply, for_ioctl)
-udp_fd_t *udp_fd;
-int reply;
-int for_ioctl;
-{
- acc_t *result;
- result= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, reply,
- (size_t)0, for_ioctl);
- assert (!result);
-}
-
-static int is_unused_port(udpport_t port)
-{
- int i;
- udp_fd_t *udp_fd;
-
- for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++,
- udp_fd++)
- {
- if (!(udp_fd->uf_flags & UFF_OPTSET))
- continue;
- if (udp_fd->uf_udpopt.nwuo_locport == port)
- return FALSE;
- }
- return TRUE;
-}
-
-static void read_ip_packets(udp_port)
-udp_port_t *udp_port;
-{
- int result;
-
- do
- {
- udp_port->up_flags |= UPF_READ_IP;
- result= ip_read(udp_port->up_ipfd, UDP_MAX_DATAGRAM);
- if (result == NW_SUSPEND)
- {
- udp_port->up_flags |= UPF_READ_SP;
- return;
- }
-assert(result == NW_OK);
- udp_port->up_flags &= ~UPF_READ_IP;
- } while(!(udp_port->up_flags & UPF_READ_IP));
-}
-
-
-static int udp_peek (udp_fd)
-udp_fd_t *udp_fd;
-{
- acc_t *pack, *tmp_acc, *next_acc;
- int result;
-
- if (!(udp_fd->uf_flags & UFF_OPTSET))
- {
- udp_fd->uf_flags &= ~UFF_IOCTL_IP;
- reply_thr_put(udp_fd, EBADMODE, TRUE);
- return NW_OK;
- }
-
- if (udp_fd->uf_rdbuf_head)
- {
- if (get_time() <= udp_fd->uf_exp_tim)
- {
- pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
- sizeof(udp_io_hdr_t));
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
- (size_t)0, pack, TRUE);
-
- udp_fd->uf_flags &= ~UFF_IOCTL_IP;
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
- result, (acc_t *)0, TRUE);
- assert (result == 0);
- return result;
- }
- tmp_acc= udp_fd->uf_rdbuf_head;
- while (tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- udp_fd->uf_rdbuf_head= NULL;
- }
- udp_fd->uf_flags |= UFF_PEEK_IP;
- return NW_SUSPEND;
-}
-
-static int udp_sel_read (udp_fd_t *udp_fd)
-{
- acc_t *tmp_acc, *next_acc;
-
- if (!(udp_fd->uf_flags & UFF_OPTSET))
- return 1; /* Read will not block */
-
- if (udp_fd->uf_rdbuf_head)
- {
- if (get_time() <= udp_fd->uf_exp_tim)
- return 1;
-
- tmp_acc= udp_fd->uf_rdbuf_head;
- while (tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- udp_fd->uf_rdbuf_head= NULL;
- }
- return 0;
-}
-
-static int udp_packet2user (udp_fd)
-udp_fd_t *udp_fd;
-{
- acc_t *pack, *tmp_pack;
- udp_io_hdr_t *hdr;
- int result, hdr_len;
- size_t size, transf_size;
-
- pack= udp_fd->uf_rdbuf_head;
- udp_fd->uf_rdbuf_head= pack->acc_ext_link;
-
- size= bf_bufsize (pack);
-
- if (udp_fd->uf_udpopt.nwuo_flags & NWUO_RWDATONLY)
- {
-
- pack= bf_packIffLess (pack, UDP_IO_HDR_SIZE);
- assert (pack->acc_length >= UDP_IO_HDR_SIZE);
-
- hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
-#if CONF_UDP_IO_NW_BYTE_ORDER
- hdr_len= UDP_IO_HDR_SIZE+NTOHS(hdr->uih_ip_opt_len);
-#else
- hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;
-#endif
-
- assert (size>= hdr_len);
- size -= hdr_len;
- tmp_pack= bf_cut(pack, hdr_len, size);
- bf_afree(pack);
- pack= tmp_pack;
- }
-
- if (size>udp_fd->uf_rd_count)
- {
- tmp_pack= bf_cut (pack, 0, udp_fd->uf_rd_count);
- bf_afree(pack);
- pack= tmp_pack;
- transf_size= udp_fd->uf_rd_count;
- }
- else
- transf_size= size;
-
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
- (size_t)0, pack, FALSE);
-
- if (result >= 0) {
- if (size > transf_size)
- result= EPACKSIZE;
- else
- result= transf_size;
- }
-
- udp_fd->uf_flags &= ~UFF_READ_IP;
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result,
- (acc_t *)0, FALSE);
- assert (result == 0);
-
- return result;
-}
-
-static void udp_ip_arrived(port, pack, pack_size)
-int port;
-acc_t *pack;
-size_t pack_size;
-{
- udp_port_t *udp_port;
- udp_fd_t *udp_fd, *share_fd;
- acc_t *ip_hdr_acc, *udp_acc, *ipopt_pack, *no_ipopt_pack, *tmp_acc;
- ip_hdr_t *ip_hdr;
- udp_hdr_t *udp_hdr;
- udp_io_hdr_t *udp_io_hdr;
- size_t ip_hdr_size, udp_size, data_size, opt_size;
- ipaddr_t src_addr, dst_addr, ipaddr;
- udpport_t src_port, dst_port;
- u8_t u16[2];
- u16_t chksum;
- unsigned long dst_type, flags;
- clock_t exp_tim;
- int i, delivered, hash;
-
- udp_port= &udp_port_table[port];
-
- ip_hdr_acc= bf_cut(pack, 0, IP_MIN_HDR_SIZE);
- ip_hdr_acc= bf_packIffLess(ip_hdr_acc, IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
- ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
- if (ip_hdr_size != IP_MIN_HDR_SIZE)
- {
- bf_afree(ip_hdr_acc);
- ip_hdr_acc= bf_cut(pack, 0, ip_hdr_size);
- ip_hdr_acc= bf_packIffLess(ip_hdr_acc, ip_hdr_size);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
- }
-
- pack_size -= ip_hdr_size;
- if (pack_size < UDP_HDR_SIZE)
- {
- if (pack_size == 0 && ip_hdr->ih_proto == 0)
- {
- /* IP layer reports new IP address */
- ipaddr= ip_hdr->ih_src;
- udp_port->up_ipaddr= ipaddr;
- DBLOCK(1, printf("udp_ip_arrived: using address ");
- writeIpAddr(ipaddr); printf("\n"));
- }
- else
- DBLOCK(1, printf("packet too small\n"));
-
- bf_afree(ip_hdr_acc);
- bf_afree(pack);
- return;
- }
-
- udp_acc= bf_delhead(pack, ip_hdr_size);
- pack= NULL;
-
-
- udp_acc= bf_packIffLess(udp_acc, UDP_HDR_SIZE);
- udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_acc);
- udp_size= ntohs(udp_hdr->uh_length);
- if (udp_size > pack_size)
- {
- DBLOCK(1, printf("packet too large\n"));
-
- bf_afree(ip_hdr_acc);
- bf_afree(udp_acc);
- return;
- }
-
- src_addr= ip_hdr->ih_src;
- dst_addr= ip_hdr->ih_dst;
-
- if (udp_hdr->uh_chksum)
- {
- u16[0]= 0;
- u16[1]= ip_hdr->ih_proto;
- chksum= pack_oneCsum(udp_acc);
- chksum= oneC_sum(chksum, (u16_t *)&src_addr, sizeof(ipaddr_t));
- chksum= oneC_sum(chksum, (u16_t *)&dst_addr, sizeof(ipaddr_t));
- chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
- chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length,
- sizeof(udp_hdr->uh_length));
- if (~chksum & 0xffff)
- {
- DBLOCK(1, printf("checksum error in udp packet\n");
- printf("src ip_addr= ");
- writeIpAddr(src_addr);
- printf(" dst ip_addr= ");
- writeIpAddr(dst_addr);
- printf("\n");
- printf("packet chksum= 0x%x, sum= 0x%x\n",
- udp_hdr->uh_chksum, chksum));
-
- bf_afree(ip_hdr_acc);
- bf_afree(udp_acc);
- return;
- }
- }
-
- exp_tim= get_time() + UDP_READ_EXP_TIME;
- src_port= udp_hdr->uh_src_port;
- dst_port= udp_hdr->uh_dst_port;
-
- /* Send an ICMP port unreachable if the packet could not be
- * delivered.
- */
- delivered= 0;
-
- if (dst_addr == udp_port->up_ipaddr)
- dst_type= NWUO_EN_LOC;
- else
- {
- dst_type= NWUO_EN_BROAD;
-
- /* Don't send ICMP error packets for broadcast packets */
- delivered= 1;
- }
-
- DBLOCK(0x20, printf("udp: got packet from ");
- writeIpAddr(src_addr);
- printf(".%u to ", ntohs(src_port));
- writeIpAddr(dst_addr);
- printf(".%u\n", ntohs(dst_port)));
-
- no_ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
- udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(no_ipopt_pack);
- udp_io_hdr->uih_src_addr= src_addr;
- udp_io_hdr->uih_dst_addr= dst_addr;
- udp_io_hdr->uih_src_port= src_port;
- udp_io_hdr->uih_dst_port= dst_port;
- data_size = udp_size-UDP_HDR_SIZE;
-#if CONF_UDP_IO_NW_BYTE_ORDER
- udp_io_hdr->uih_ip_opt_len= HTONS(0);
- udp_io_hdr->uih_data_len= htons(data_size);
-#else
- udp_io_hdr->uih_ip_opt_len= 0;
- udp_io_hdr->uih_data_len= data_size;
-#endif
- no_ipopt_pack->acc_next= bf_cut(udp_acc, UDP_HDR_SIZE, data_size);
-
- if (ip_hdr_size == IP_MIN_HDR_SIZE)
- {
- ipopt_pack= no_ipopt_pack;
- ipopt_pack->acc_linkC++;
- }
- else
- {
- ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
- *(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)= *udp_io_hdr;
- udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(ipopt_pack);
- opt_size = ip_hdr_size-IP_MIN_HDR_SIZE;
-#if CONF_UDP_IO_NW_BYTE_ORDER
- udp_io_hdr->uih_ip_opt_len= htons(opt_size);
-#else
- udp_io_hdr->uih_ip_opt_len= opt_size;
-#endif
- tmp_acc= bf_cut(ip_hdr_acc, (size_t)IP_MIN_HDR_SIZE, opt_size);
- assert(tmp_acc->acc_linkC == 1);
- assert(tmp_acc->acc_next == NULL);
- ipopt_pack->acc_next= tmp_acc;
-
- tmp_acc->acc_next= no_ipopt_pack->acc_next;
- if (tmp_acc->acc_next)
- tmp_acc->acc_next->acc_linkC++;
- }
-
- hash= dst_port;
- hash ^= (hash >> 8);
- hash &= (UDP_PORT_HASH_NR-1);
-
- for (i= 0; i<2; i++)
- {
- share_fd= NULL;
-
- udp_fd= (i == 0) ? udp_port->up_port_any :
- udp_port->up_port_hash[hash];
- for (; udp_fd; udp_fd= udp_fd->uf_port_next)
- {
- if (i && udp_fd->uf_udpopt.nwuo_locport != dst_port)
- continue;
-
- assert(udp_fd->uf_flags & UFF_INUSE);
- assert(udp_fd->uf_flags & UFF_OPTSET);
-
- if (udp_fd->uf_port != udp_port)
- continue;
-
- flags= udp_fd->uf_udpopt.nwuo_flags;
- if (!(flags & dst_type))
- continue;
-
- if ((flags & NWUO_RP_SET) &&
- udp_fd->uf_udpopt.nwuo_remport != src_port)
- {
- continue;
- }
-
- if ((flags & NWUO_RA_SET) &&
- udp_fd->uf_udpopt.nwuo_remaddr != src_addr)
- {
- continue;
- }
-
- if (i)
- {
- /* Packet is considdered to be delivered */
- delivered= 1;
- }
-
- if ((flags & NWUO_ACC_MASK) == NWUO_SHARED &&
- (!share_fd || !udp_fd->uf_rdbuf_head))
- {
- share_fd= udp_fd;
- continue;
- }
-
- if (flags & NWUO_EN_IPOPT)
- pack= ipopt_pack;
- else
- pack= no_ipopt_pack;
-
- pack->acc_linkC++;
- udp_rd_enqueue(udp_fd, pack, exp_tim);
- if (udp_fd->uf_flags & UFF_READ_IP)
- udp_packet2user(udp_fd);
- }
-
- if (share_fd)
- {
- flags= share_fd->uf_udpopt.nwuo_flags;
- if (flags & NWUO_EN_IPOPT)
- pack= ipopt_pack;
- else
- pack= no_ipopt_pack;
-
- pack->acc_linkC++;
- udp_rd_enqueue(share_fd, pack, exp_tim);
- if (share_fd->uf_flags & UFF_READ_IP)
- udp_packet2user(share_fd);
- }
- }
-
- if (ipopt_pack)
- bf_afree(ipopt_pack);
- if (no_ipopt_pack)
- bf_afree(no_ipopt_pack);
-
- if (!delivered)
- {
- DBLOCK(0x2, printf("udp: could not deliver packet from ");
- writeIpAddr(src_addr);
- printf(".%u to ", ntohs(src_port));
- writeIpAddr(dst_addr);
- printf(".%u\n", ntohs(dst_port)));
-
- pack= bf_append(ip_hdr_acc, udp_acc);
- ip_hdr_acc= NULL;
- udp_acc= NULL;
- icmp_snd_unreachable(udp_port->up_ipdev, pack,
- ICMP_PORT_UNRCH);
- return;
- }
-
- assert (ip_hdr_acc);
- bf_afree(ip_hdr_acc);
- assert (udp_acc);
- bf_afree(udp_acc);
-}
-
-void udp_close(fd)
-int fd;
-{
- udp_fd_t *udp_fd;
- acc_t *tmp_acc, *next_acc;
-
- udp_fd= &udp_fd_table[fd];
-
- assert (udp_fd->uf_flags & UFF_INUSE);
-
- if (udp_fd->uf_flags & UFF_OPTSET)
- unhash_fd(udp_fd);
-
- udp_fd->uf_flags= UFF_EMPTY;
- tmp_acc= udp_fd->uf_rdbuf_head;
- while (tmp_acc)
- {
- next_acc= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- tmp_acc= next_acc;
- }
- udp_fd->uf_rdbuf_head= NULL;
-}
-
-int udp_write(int fd, size_t count)
-{
- udp_fd_t *udp_fd;
-
- udp_fd= &udp_fd_table[fd];
-
- if (!(udp_fd->uf_flags & UFF_OPTSET))
- {
- reply_thr_get (udp_fd, EBADMODE, FALSE);
- return NW_OK;
- }
-
-assert (!(udp_fd->uf_flags & UFF_WRITE_IP));
-
- udp_fd->uf_wr_count= count;
-
- udp_fd->uf_flags |= UFF_WRITE_IP;
-
- restart_write_fd(udp_fd);
-
- if (udp_fd->uf_flags & UFF_WRITE_IP)
- {
- DBLOCK(1, printf("replying NW_SUSPEND\n"));
-
- return NW_SUSPEND;
- }
- else
- {
- return NW_OK;
- }
-}
-
-static void restart_write_fd(udp_fd)
-udp_fd_t *udp_fd;
-{
- udp_port_t *udp_port;
- acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data;
- udp_hdr_t *udp_hdr;
- udp_io_hdr_t *udp_io_hdr;
- ip_hdr_t *ip_hdr;
- size_t ip_opt_size, user_data_size;
- unsigned long flags;
- u16_t chksum;
- u8_t u16[2];
- int result;
-
- udp_port= udp_fd->uf_port;
-
- if (udp_port->up_flags & UPF_WRITE_IP)
- {
- udp_port->up_flags |= UPF_MORE2WRITE;
- return;
- }
-
-assert (udp_fd->uf_flags & UFF_WRITE_IP);
- udp_fd->uf_flags &= ~UFF_WRITE_IP;
-
-assert (!udp_port->up_wr_pack);
-
- pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
- udp_fd->uf_wr_count, FALSE);
- if (!pack)
- {
- udp_fd->uf_flags &= ~UFF_WRITE_IP;
- reply_thr_get (udp_fd, EFAULT, FALSE);
- return;
- }
-
- flags= udp_fd->uf_udpopt.nwuo_flags;
-
- ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE);
- ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack);
-
- udp_hdr_pack= bf_memreq(UDP_HDR_SIZE);
- udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack);
-
- if (flags & NWUO_RWDATALL)
- {
- pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE);
- udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
-#if CONF_UDP_IO_NW_BYTE_ORDER
- ip_opt_size= ntohs(udp_io_hdr->uih_ip_opt_len);
-#else
- ip_opt_size= udp_io_hdr->uih_ip_opt_len;
-#endif
- if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count)
- {
- bf_afree(ip_hdr_pack);
- bf_afree(udp_hdr_pack);
- bf_afree(pack);
- reply_thr_get (udp_fd, EINVAL, FALSE);
- return;
- }
- if (ip_opt_size & 3)
- {
- bf_afree(ip_hdr_pack);
- bf_afree(udp_hdr_pack);
- bf_afree(pack);
- reply_thr_get (udp_fd, EFAULT, FALSE);
- return;
- }
- if (ip_opt_size)
- ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size);
- else
- ip_opt_pack= 0;
- user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE-
- ip_opt_size;
- user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size,
- user_data_size);
- bf_afree(pack);
- }
- else
- {
- udp_io_hdr= 0;
- ip_opt_size= 0;
- user_data_size= udp_fd->uf_wr_count;
- ip_opt_pack= 0;
- user_data= pack;
- }
-
- ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2;
- ip_hdr->ih_tos= UDP_TOS;
- ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS);
- ip_hdr->ih_ttl= IP_DEF_TTL;
- ip_hdr->ih_proto= IPPROTO_UDP;
- if (flags & NWUO_RA_SET)
- {
- ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr;
- }
- else
- {
-assert (udp_io_hdr);
- ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr;
- }
-
- if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY)
- udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport;
- else
- {
-assert (udp_io_hdr);
- udp_hdr->uh_src_port= udp_io_hdr->uih_src_port;
- }
-
- if (flags & NWUO_RP_SET)
- udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport;
- else
- {
-assert (udp_io_hdr);
- udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port;
- }
-
- udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size);
- udp_hdr->uh_chksum= 0;
-
- udp_hdr_pack->acc_next= user_data;
- chksum= pack_oneCsum(udp_hdr_pack);
- chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr,
- sizeof(ipaddr_t));
- chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t));
- u16[0]= 0;
- u16[1]= IPPROTO_UDP;
- chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
- chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t));
- if (~chksum)
- chksum= ~chksum;
- udp_hdr->uh_chksum= chksum;
-
- if (ip_opt_pack)
- {
- ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size);
- ip_opt_pack->acc_next= udp_hdr_pack;
- udp_hdr_pack= ip_opt_pack;
- }
- ip_hdr_pack->acc_next= udp_hdr_pack;
-
-assert (!udp_port->up_wr_pack);
-assert (!(udp_port->up_flags & UPF_WRITE_IP));
-
- udp_port->up_wr_pack= ip_hdr_pack;
- udp_port->up_flags |= UPF_WRITE_IP;
- result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack));
- if (result == NW_SUSPEND)
- {
- udp_port->up_flags |= UPF_WRITE_SP;
- udp_fd->uf_flags |= UFF_WRITE_IP;
- udp_port->up_write_fd= udp_fd;
- }
- else if (result<0)
- reply_thr_get(udp_fd, result, FALSE);
- else
- reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);
-}
-
-static u16_t pack_oneCsum(pack)
-acc_t *pack;
-{
- u16_t prev;
- int odd_byte;
- char *data_ptr;
- int length;
- char byte_buf[2];
-
- assert (pack);
-
- prev= 0;
-
- odd_byte= FALSE;
- for (; pack; pack= pack->acc_next)
- {
-
- data_ptr= ptr2acc_data(pack);
- length= pack->acc_length;
-
- if (!length)
- continue;
- if (odd_byte)
- {
- byte_buf[1]= *data_ptr;
- prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
- data_ptr++;
- length--;
- odd_byte= FALSE;
- }
- if (length & 1)
- {
- odd_byte= TRUE;
- length--;
- byte_buf[0]= data_ptr[length];
- }
- if (!length)
- continue;
- prev= oneC_sum (prev, (u16_t *)data_ptr, length);
- }
- if (odd_byte)
- {
- byte_buf[1]= 0;
- prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
- }
- return prev;
-}
-
-static void udp_restart_write_port(udp_port )
-udp_port_t *udp_port;
-{
- udp_fd_t *udp_fd;
- int i;
-
-assert (!udp_port->up_wr_pack);
-assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP)));
-
- while (udp_port->up_flags & UPF_MORE2WRITE)
- {
- udp_port->up_flags &= ~UPF_MORE2WRITE;
-
- for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR;
- i++, udp_fd++)
- {
- if (udp_fd == &udp_fd_table[UDP_FD_NR])
- udp_fd= udp_fd_table;
-
- if (!(udp_fd->uf_flags & UFF_INUSE))
- continue;
- if (!(udp_fd->uf_flags & UFF_WRITE_IP))
- continue;
- if (udp_fd->uf_port != udp_port)
- continue;
- restart_write_fd(udp_fd);
- if (udp_port->up_flags & UPF_WRITE_IP)
- {
- udp_port->up_next_fd= udp_fd+1;
- udp_port->up_flags |= UPF_MORE2WRITE;
- return;
- }
- }
- }
-}
-
-int udp_cancel(fd, which_operation)
-int fd;
-int which_operation;
-{
- udp_fd_t *udp_fd;
-
- DBLOCK(0x10, printf("udp_cancel(%d, %d)\n", fd, which_operation));
-
- udp_fd= &udp_fd_table[fd];
-
- switch (which_operation)
- {
- case SR_CANCEL_READ:
-assert (udp_fd->uf_flags & UFF_READ_IP);
- udp_fd->uf_flags &= ~UFF_READ_IP;
- reply_thr_put(udp_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_WRITE:
-assert (udp_fd->uf_flags & UFF_WRITE_IP);
- udp_fd->uf_flags &= ~UFF_WRITE_IP;
- if (udp_fd->uf_port->up_write_fd == udp_fd)
- udp_fd->uf_port->up_write_fd= NULL;
- reply_thr_get(udp_fd, EINTR, FALSE);
- break;
- case SR_CANCEL_IOCTL:
-assert (udp_fd->uf_flags & UFF_IOCTL_IP);
- udp_fd->uf_flags &= ~UFF_IOCTL_IP;
- udp_fd->uf_flags &= ~UFF_PEEK_IP;
- reply_thr_get(udp_fd, EINTR, TRUE);
- break;
- default:
- ip_panic(( "got unknown cancel request" ));
- }
- return NW_OK;
-}
-
-static void udp_buffree (priority)
-int priority;
-{
- int i;
- udp_fd_t *udp_fd;
- acc_t *tmp_acc;
-
- if (priority == UDP_PRI_FDBUFS_EXTRA)
- {
- for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
- {
- while (udp_fd->uf_rdbuf_head &&
- udp_fd->uf_rdbuf_head->acc_ext_link)
- {
- tmp_acc= udp_fd->uf_rdbuf_head;
- udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- }
- }
- }
-
- if (priority == UDP_PRI_FDBUFS)
- {
- for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
- {
- while (udp_fd->uf_rdbuf_head)
- {
- tmp_acc= udp_fd->uf_rdbuf_head;
- udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
- bf_afree(tmp_acc);
- }
- }
- }
-}
-
-static void udp_rd_enqueue(udp_fd, pack, exp_tim)
-udp_fd_t *udp_fd;
-acc_t *pack;
-clock_t exp_tim;
-{
- acc_t *tmp_acc;
- int result;
-
- if (pack->acc_linkC != 1)
- {
- tmp_acc= bf_dupacc(pack);
- bf_afree(pack);
- pack= tmp_acc;
- }
- pack->acc_ext_link= NULL;
- if (udp_fd->uf_rdbuf_head == NULL)
- {
- udp_fd->uf_exp_tim= exp_tim;
- udp_fd->uf_rdbuf_head= pack;
- }
- else
- udp_fd->uf_rdbuf_tail->acc_ext_link= pack;
- udp_fd->uf_rdbuf_tail= pack;
-
- if (udp_fd->uf_flags & UFF_PEEK_IP)
- {
- pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
- sizeof(udp_io_hdr_t));
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
- (size_t)0, pack, TRUE);
-
- udp_fd->uf_flags &= ~UFF_IOCTL_IP;
- udp_fd->uf_flags &= ~UFF_PEEK_IP;
- result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
- result, (acc_t *)0, TRUE);
- assert (result == 0);
- }
-
- if (udp_fd->uf_flags & UFF_SEL_READ)
- {
- udp_fd->uf_flags &= ~UFF_SEL_READ;
- if (udp_fd->uf_select_res)
- udp_fd->uf_select_res(udp_fd->uf_srfd, SR_SELECT_READ);
- else
- printf("udp_rd_enqueue: no select_res\n");
- }
-}
-
-static void hash_fd(udp_fd)
-udp_fd_t *udp_fd;
-{
- udp_port_t *udp_port;
- int hash;
-
- udp_port= udp_fd->uf_port;
- if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
- NWUO_LP_ANY)
- {
- udp_fd->uf_port_next= udp_port->up_port_any;
- udp_port->up_port_any= udp_fd;
- }
- else
- {
- hash= udp_fd->uf_udpopt.nwuo_locport;
- hash ^= (hash >> 8);
- hash &= (UDP_PORT_HASH_NR-1);
-
- udp_fd->uf_port_next= udp_port->up_port_hash[hash];
- udp_port->up_port_hash[hash]= udp_fd;
- }
-}
-
-static void unhash_fd(udp_fd)
-udp_fd_t *udp_fd;
-{
- udp_port_t *udp_port;
- udp_fd_t *prev, *curr, **udp_fd_p;
- int hash;
-
- udp_port= udp_fd->uf_port;
- if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
- NWUO_LP_ANY)
- {
- udp_fd_p= &udp_port->up_port_any;
- }
- else
- {
- hash= udp_fd->uf_udpopt.nwuo_locport;
- hash ^= (hash >> 8);
- hash &= (UDP_PORT_HASH_NR-1);
-
- udp_fd_p= &udp_port->up_port_hash[hash];
- }
- for (prev= NULL, curr= *udp_fd_p; curr;
- prev= curr, curr= curr->uf_port_next)
- {
- if (curr == udp_fd)
- break;
- }
- assert(curr);
- if (prev)
- prev->uf_port_next= curr->uf_port_next;
- else
- *udp_fd_p= curr->uf_port_next;
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void udp_bufcheck()
-{
- int i;
- udp_port_t *udp_port;
- udp_fd_t *udp_fd;
- acc_t *tmp_acc;
-
- for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
- {
- if (udp_port->up_wr_pack)
- bf_check_acc(udp_port->up_wr_pack);
- }
-
- for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
- {
- for (tmp_acc= udp_fd->uf_rdbuf_head; tmp_acc;
- tmp_acc= tmp_acc->acc_ext_link)
- {
- bf_check_acc(tmp_acc);
- }
- }
-}
-#endif
-
-/*
- * $PchId: udp.c,v 1.25 2005/06/28 14:14:44 philip Exp $
- */
+++ /dev/null
-/*
-udp.h
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef UDP_H
-#define UDP_H
-
-#define UDP_DEF_OPT NWUO_NOFLAGS
-#define UDP_MAX_DATAGRAM 40000 /* 8192 */
-#define UDP_READ_EXP_TIME (10L * HZ)
-#define UDP_TOS 0
-#define UDP_IP_FLAGS 0
-
-#define UDP0 0
-
-struct acc;
-
-void udp_prep ARGS(( void ));
-void udp_init ARGS(( void ));
-int udp_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t select_res ));
-int udp_ioctl ARGS(( int fd, ioreq_t req ));
-int udp_read ARGS(( int fd, size_t count ));
-int udp_write ARGS(( int fd, size_t count ));
-void udp_close ARGS(( int fd ));
-int udp_cancel ARGS(( int fd, int which_operation ));
-
-#endif /* UDP_H */
-
-
-/*
- * $PchId: udp.h,v 1.9 2005/06/28 14:12:05 philip Exp $
- */
+++ /dev/null
-/*
-generic/udp_int.h
-
-Created: March 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Some internals of the UDP module
-*/
-
-#define UDP_FD_NR (4*IP_PORT_MAX)
-#define UDP_PORT_HASH_NR 16 /* Must be a power of 2 */
-
-typedef struct udp_port
-{
- int up_flags;
- int up_state;
- int up_ipfd;
- int up_ipdev;
- acc_t *up_wr_pack;
- ipaddr_t up_ipaddr;
- struct udp_fd *up_next_fd;
- struct udp_fd *up_write_fd;
- struct udp_fd *up_port_any;
- struct udp_fd *up_port_hash[UDP_PORT_HASH_NR];
-} udp_port_t;
-
-#define UPF_EMPTY 0x0
-#define UPF_WRITE_IP 0x1
-#define UPF_WRITE_SP 0x2
-#define UPF_READ_IP 0x4
-#define UPF_READ_SP 0x8
-#define UPF_SUSPEND 0x10
-#define UPF_MORE2WRITE 0x20
-
-#define UPS_EMPTY 0
-#define UPS_SETPROTO 1
-#define UPS_GETCONF 2
-#define UPS_MAIN 3
-#define UPS_ERROR 4
-
-typedef struct udp_fd
-{
- int uf_flags;
- udp_port_t *uf_port;
- ioreq_t uf_ioreq;
- int uf_srfd;
- nwio_udpopt_t uf_udpopt;
- get_userdata_t uf_get_userdata;
- put_userdata_t uf_put_userdata;
- select_res_t uf_select_res;
- acc_t *uf_rdbuf_head;
- acc_t *uf_rdbuf_tail;
- size_t uf_rd_count;
- size_t uf_wr_count;
- clock_t uf_exp_tim;
- struct udp_fd *uf_port_next;
-} udp_fd_t;
-
-#define UFF_EMPTY 0x0
-#define UFF_INUSE 0x1
-#define UFF_IOCTL_IP 0x2
-#define UFF_READ_IP 0x4
-#define UFF_WRITE_IP 0x8
-#define UFF_OPTSET 0x10
-#define UFF_PEEK_IP 0x20
-#define UFF_SEL_READ 0x40
-#define UFF_SEL_WRITE 0x80
-
-EXTERN udp_port_t *udp_port_table;
-EXTERN udp_fd_t udp_fd_table[UDP_FD_NR];
-
-/*
- * $PchId: udp_int.h,v 1.4 2004/08/03 11:12:01 philip Exp $
- */
+++ /dev/null
-.TH INET 8
-.SH NAME
-inet, inet.conf \- TCP/IP server
-.SH SYNOPSIS
-.B inet
-.SH DESCRIPTION
-.de SP
-.if t .sp 0.4
-.if n .sp
-..
-.B Inet
-is the TCP/IP server. It is a device driver that interfaces between the
-file server and the low level ethernet device driver. The interface to this
-server is described in
-.BR ip (4).
-.PP
-.B Inet
-starts as a normal process, reads a the configuration file
-.B /etc/inet.conf
-to see what it should do, and uses a few special low level system calls
-to turn itself into a server. The format of the configuration file is as
-follows:
-.SS Configuration
-The inet configuration file is fairly simple, here is an example:
-.PP
-.RS
-.ft C
-.nf
-eth0 DP8390 0 { default; };
-psip1;
-.fi
-.ft P
-.RS
-.PP
-It tells that network 0 (the one containing devices
-.BR eth0 ,
-.BR ip0 ,
-.BR tcp0
-and
-.BR udp0 )
-uses the ethernet device driver handled
-by driver "DP8390" instance 0. This network is marked as the default
-network, so most programs use it through the unnumbered devices like
-.B /dev/tcp
-or
-.BR /dev/udp .
-Network 1 is a Pseudo IP network that can be used for
-a serial IP over a modem for instance.
-.PP
-The configuration file uses a simple line-based format.
-Each network definition has to be fully on its own line.
-Empty lines and lines that start with a `#' symbol are ignored.
-The following network definitions are possible:
-.PP
-.BI eth N
-.I driver instance
-.RI { options };
-.RS
-This sets up an ethernet with device name
-.BI /dev/eth N\fR,
-built on the given ethernet device driver with the given instance number.
-(If there are two network cards of the same type
-then they will be managed by instance 0 and 1 of the corresponding driver.)
-.br
-.RE
-.PP
-.BI eth N
-.B vlan
-.I id
-.BI eth M
-.RI { options };
-\0\0\0\0
-.RS
-The ethernet
-.BI eth N
-uses VLAN number
-.I id
-and is built on ethernet
-.BI eth M\fR.
-A packet given to this network has a VLAN tag prefixed to it and is then
-handed over to another ethernet for transmission. Likewise a packet on
-that ethernet carrying the appropriate VLAN tag has this tag removed and is
-sent on to this network. The VLAN ethernet behaves like an ordinary ethernet
-as far as applications are concerned.
-.RE
-.PP
-.BI psip N
-.RI { options };
-.RS
-Creates pseudo IP network
-.BI /dev/psip N\fR,
-usable for IP over serial lines, tunnels and whatnot.
-.RE
-.SH OPTIONS
-Some options can be given between braces.
-.PP
-.BR default ;
-.RS
-Mark this network as the default network. Exactly one of the networks must
-be so marked.
-When
-.B inet
-is started it will check and create all the necessary network devices before
-becoming a server. To know what major device number to use it checks
-.BR /dev/ip ,
-so that device must already exist. It can be created by
-.B MAKEDEV
-if need be.
-.RE
-.PP
-.BR "no ip" ;
-.br
-.BR "no tcp" ;
-.br
-.BR "no udp" ;
-.RS
-These options turn the IP, TCP, or UDP layer off. Inet will not enable the
-devices for these layers, and will deactivate code for these layers.
-Disabling IP will also disable TCP or UDP, because they need IP to function.
-An ethernet without an IP layer can be used as for stealth listening. An IP
-network without TCP or UDP can be used to pester students into creating the
-missing functionality. Keeps them off the streets, and maybe they'll learn
-something.
-.RE
-.SH "SEE ALSO"
-.BR ip (4),
-.BR boot (8).
-.SH NOTES
-The number of networks that can be defined are 2 (Minix-86), 4 (Minix-386)
-or 16 (Minix-vmd). This limits both the total number and the highest
-device number you can use.
-.PP
-Getting a network administrator to give you a trunk or multi-VLAN port to
-run multiple networks on can be a challenge. It questions their idea that
-VLANs are separate networks, while in reality it is just one big ethernet.
-.SH ACKNOWLEDGMENTS
-Cindy Crawford, for providing invaluable help debugging this server.
-.SH AUTHOR
-.ta \w'Manual:'u+2n
-Code: Philip Homburg <philip@cs.vu.nl>
-.br
-Manual: Kees J. Bot <kjb@cs.vu.nl>
-
-.\"
-.\" $PchId: inet.8,v 1.6 2001/10/08 19:01:35 philip Exp $
+++ /dev/null
-/* this file contains the interface of the network software with rest of
- minix. Furthermore it contains the main loop of the network task.
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <minix/ds.h>
-#include <minix/endpoint.h>
-#include <minix/chardriver.h>
-#include <minix/rs.h>
-#include <minix/rmib.h>
-#include <sys/types.h>
-#include <pwd.h>
-
-#include "mq.h"
-#include "qp.h"
-#include "proto.h"
-#include "generic/type.h"
-
-#include "generic/arp.h"
-#include "generic/assert.h"
-#include "generic/buf.h"
-#include "generic/clock.h"
-#include "generic/eth.h"
-#include "generic/event.h"
-#include "generic/ip.h"
-#include "generic/psip.h"
-#include "generic/rand256.h"
-#include "generic/sr.h"
-#include "generic/tcp.h"
-#include "generic/udp.h"
-
-THIS_FILE
-
-#define RANDOM_DEV_NAME "/dev/random"
-
-endpoint_t this_proc; /* Process number of this server. */
-
-/* Killing Solaris */
-int killer_inet= 0;
-
-#ifdef BUF_CONSISTENCY_CHECK
-extern int inet_buf_debug;
-#endif
-
-#if HZ_DYNAMIC
-u32_t system_hz;
-#endif
-
-static void nw_conf(void);
-static void nw_init(void);
-static void ds_event(void);
-
-/* SEF functions and variables. */
-static void sef_local_startup(void);
-static int sef_cb_init_fresh(int type, sef_init_info_t *info);
-
-int main(int argc, char *argv[])
-{
- message mess;
- int ipc_status;
- int r;
-
- /* SEF local startup. */
- sef_local_startup();
-
- while (TRUE)
- {
-#ifdef BUF_CONSISTENCY_CHECK
- if (inet_buf_debug)
- {
- static int buf_debug_count= 0;
-
- if (++buf_debug_count >= inet_buf_debug)
- {
- buf_debug_count= 0;
- if (!bf_consistency_check())
- break;
- }
- }
-#endif
- if (ev_head)
- {
- ev_process();
- continue;
- }
- if (clck_call_expire)
- {
- clck_expire_timers();
- continue;
- }
-
- r= sef_receive_status(ANY, &mess, &ipc_status);
- if (r<0)
- {
- ip_panic(("unable to receive: %d", r));
- }
- reset_time();
- if (mess.m_source == VFS_PROC_NR)
- {
- sr_rec(&mess, ipc_status);
- }
- else if (is_ipc_notify(ipc_status))
- {
- if (mess.m_source == CLOCK)
- {
- clck_tick(&mess);
- }
- else if (mess.m_source == DS_PROC_NR)
- {
- /* DS notifies us of an event. */
- ds_event();
- }
- else
- {
- printf("inet: got unexpected notify from %d\n",
- mess.m_source);
- }
- }
- else if (mess.m_source == MIB_PROC_NR)
- {
- rmib_process(&mess, ipc_status);
- }
- else if (mess.m_type == DL_CONF_REPLY ||
- mess.m_type == DL_TASK_REPLY ||
- mess.m_type == DL_STAT_REPLY)
- {
- eth_rec(&mess);
- }
- else
- {
- printf("inet: got bad message type 0x%x from %d\n",
- mess.m_type, mess.m_source);
- }
- }
- ip_panic(("task is not allowed to terminate"));
- return 1;
-}
-
-/*===========================================================================*
- * sef_local_startup *
- *===========================================================================*/
-static void sef_local_startup()
-{
- /* Register init callbacks. */
- sef_setcb_init_fresh(sef_cb_init_fresh);
- sef_setcb_init_restart(sef_cb_init_fresh);
-
- /* Let SEF perform startup. */
- sef_startup();
-}
-
-/*===========================================================================*
- * sef_cb_init_fresh *
- *===========================================================================*/
-static int sef_cb_init_fresh(int type, sef_init_info_t *info)
-{
-/* Initialize the inet server. */
- int r;
- int timerand, fd;
- u8_t randbits[32];
- struct timeval tv;
-
-#if DEBUG
- printf("Starting inet...\n");
- printf("%s\n", version);
-#endif
-
-#if HZ_DYNAMIC
- system_hz = sys_hz();
-#endif
-
- /* Read configuration. */
- nw_conf();
-
- /* Get a random number */
- timerand= 1;
- fd= open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK);
- if (fd != -1)
- {
- r= read(fd, randbits, sizeof(randbits));
- if (r == sizeof(randbits))
- timerand= 0;
- else
- {
- printf("inet: unable to read random data from %s: %s\n",
- RANDOM_DEV_NAME, r == -1 ? strerror(errno) :
- r == 0 ? "EOF" : "not enough data");
- }
- close(fd);
- }
- else
- {
- printf("inet: unable to open random device %s: %s\n",
- RANDOM_DEV_NAME, strerror(errno));
- }
- if (timerand)
- {
- printf("inet: using current time for random-number seed\n");
- r= gettimeofday(&tv, NULL);
- if (r == -1)
- {
- printf("sysutime failed: %s\n", strerror(errno));
- exit(1);
- }
- memcpy(randbits, &tv, sizeof(tv));
- }
- init_rand256(randbits);
-
- /* Our new identity as a server. */
- this_proc= info->endpoint;
-
-#ifdef BUF_CONSISTENCY_CHECK
- inet_buf_debug= (getenv("inetbufdebug") &&
- (strcmp(getenv("inetbufdebug"), "on") == 0));
- inet_buf_debug= 100;
- if (inet_buf_debug)
- {
- ip_warning(( "buffer consistency check enabled" ));
- }
-#endif
-
- if (getenv("killerinet"))
- {
- ip_warning(( "killer inet active" ));
- killer_inet= 1;
- }
-
- nw_init();
-
- /* Subscribe to driver events for network drivers. */
- r = ds_subscribe("drv\\.net\\..*", DSF_INITIAL | DSF_OVERWRITE);
- if(r != OK) {
- ip_panic(("inet: can't subscribe to driver events"));
- }
-
- /* Drop privileges. */
- if (setuid(SERVICE_UID) != 0)
- printf("inet: warning, unable to drop privileges\n");
-
- /* Announce we are up. INET announces its presence to VFS just like
- * any other character driver.
- */
- chardriver_announce();
-
- /* Register net.route RMIB subtree with the MIB service. */
- rtinfo_init();
-
- return(OK);
-}
-
-static void nw_conf()
-{
- read_conf();
- eth_prep();
- arp_prep();
- psip_prep();
- ip_prep();
- tcp_prep();
- udp_prep();
-}
-
-static void nw_init()
-{
- mq_init();
- bf_init();
- clck_init();
- sr_init();
- qp_init();
- eth_init();
- arp_init();
- psip_init();
- ip_init();
- tcp_init();
- udp_init();
-}
-
-/*===========================================================================*
- * ds_event *
- *===========================================================================*/
-static void ds_event()
-{
- char key[DS_MAX_KEYLEN];
- char *driver_prefix = (char *) "drv.net.";
- char *label;
- u32_t value;
- int type;
- endpoint_t owner_endpoint;
- int r;
- int prefix_len;
-
- prefix_len = strlen(driver_prefix);
-
- /* We may get one notification for multiple updates from DS. Get events
- * and owners from DS, until DS tells us that there are no more.
- */
- while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
- r = ds_retrieve_u32(key, &value);
- if(r != OK) {
- printf("inet: ds_event: ds_retrieve_u32 failed\n");
- return;
- }
-
- /* Only check for network driver up events. */
- if(strncmp(key, driver_prefix, prefix_len)
- || value != DS_DRIVER_UP) {
- return;
- }
-
- /* The driver label comes after the prefix. */
- label = key + prefix_len;
-
- /* A driver is (re)started. */
- eth_check_driver(label, owner_endpoint);
- }
-
- if(r != ENOENT)
- printf("inet: ds_event: ds_check failed: %d\n", r);
-}
-
-void panic0(file, line)
-char *file;
-int line;
-{
- printf("panic at %s, %d: ", file, line);
-}
-
-__dead
-void inet_panic(void)
-{
- printf("\ninet stacktrace: ");
- util_stacktrace();
- (panic)("aborted due to a panic");
- for(;;);
-}
-
-#if !NDEBUG
-__dead
-void bad_assertion(file, line, what)
-char *file;
-int line;
-char *what;
-{
- panic0(file, line);
- printf("assertion \"%s\" failed", what);
- panic("help");
-}
-
-
-__dead
-void bad_compare(file, line, lhs, what, rhs)
-char *file;
-int line;
-int lhs;
-char *what;
-int rhs;
-{
- panic0(file, line);
- printf("compare (%d) %s (%d) failed", lhs, what, rhs);
- panic("help");
-}
-#endif /* !NDEBUG */
-
-/*
- * $PchId: inet.c,v 1.23 2005/06/28 14:27:22 philip Exp $
- */
+++ /dev/null
-service inet
-{
- uid 0;
-};
-
+++ /dev/null
-/*
-inet/inet.h
-
-Created: Dec 30, 1991 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__INET_H
-#define INET__INET_H
-
-#define _SYSTEM 1 /* get OK and negative error codes */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-#include <sys/ioc_file.h>
-#include <sys/time.h>
-#include <minix/config.h>
-#include <minix/type.h>
-
-#define _NORETURN /* Should be non empty for GCC */
-
-typedef unsigned long ioreq_t;
-
-#include <minix/const.h>
-#include <minix/com.h>
-#include <minix/syslib.h>
-#include <minix/sysutil.h>
-#include <net/hton.h>
-#include <net/gen/ether.h>
-#include <net/gen/eth_hdr.h>
-#include <net/gen/eth_io.h>
-#include <net/gen/in.h>
-#include <net/gen/ip_hdr.h>
-#include <net/gen/ip_io.h>
-#include <net/gen/icmp.h>
-#include <net/gen/icmp_hdr.h>
-#include <net/gen/oneCsum.h>
-#include <net/gen/psip_hdr.h>
-#include <net/gen/psip_io.h>
-#include <net/gen/route.h>
-#include <net/gen/tcp.h>
-#include <net/gen/tcp.h>
-#include <net/gen/tcp_hdr.h>
-#include <net/gen/tcp_io.h>
-#include <net/gen/udp.h>
-#include <net/gen/udp_hdr.h>
-#include <net/gen/udp_io.h>
-
-#include <net/gen/arp_io.h>
-#include <sys/ioc_net.h>
-
-#include "const.h"
-#include "inet_config.h"
-
-#define PUBLIC
-#define EXTERN extern
-#define PRIVATE static
-#define FORWARD static
-
-#define THIS_FILE
-#define this_file __FILE__
-
-void panic0(char *file, int line);
-void inet_panic(void) _NORETURN;
-
-#if 0
-#define ip_panic(print_list) \
- (panic0(this_file, __LINE__), printf print_list, panic())
-#define panic() inet_panic()
-#else
-#define ip_panic(print_list) do { panic print_list; } while(0)
-#endif
-
-#if DEBUG
-#define ip_warning(print_list) \
- ( \
- printf("warning at %s, %d: ", this_file, __LINE__), \
- printf print_list, \
- printf("\ninet stacktrace: "), \
- util_stacktrace() \
- )
-#else
-#define ip_warning(print_list) ((void) 0)
-#endif
-
-#define DBLOCK(level, code) \
- do { if ((level) & DEBUG) { where(); code; } } while(0)
-#define DIFBLOCK(level, condition, code) \
- do { if (((level) & DEBUG) && (condition)) \
- { where(); code; } } while(0)
-
-extern endpoint_t this_proc;
-extern char version[];
-
-#ifndef HZ
-EXTERN u32_t system_hz;
-#define HZ system_hz
-#define HZ_DYNAMIC 1
-#endif
-
-#endif /* INET__INET_H */
-
-/*
- * $PchId: inet.h,v 1.16 2005/06/28 14:27:54 philip Exp $
- */
+++ /dev/null
-/*
-inet/inet_config.c
-
-Created: Nov 11, 1992 by Philip Homburg
-
-Modified: Apr 07, 2001 by Kees J. Bot
- Read the configuration file and fill in the xx_conf[] arrays.
-
-Copyright 1995 Philip Homburg
-*/
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/cdefs.h>
-#include <minix/type.h>
-#include <minix/sysutil.h>
-#include <minix/syslib.h>
-#include "inet_config.h"
-#include "inet.h"
-
-THIS_FILE
-
-struct eth_conf eth_conf[IP_PORT_MAX];
-struct psip_conf psip_conf[IP_PORT_MAX];
-struct ip_conf ip_conf[IP_PORT_MAX];
-struct tcp_conf tcp_conf[IP_PORT_MAX];
-struct udp_conf udp_conf[IP_PORT_MAX];
-dev_t ip_dev;
-
-int eth_conf_nr;
-int psip_conf_nr;
-int ip_conf_nr;
-int tcp_conf_nr;
-int udp_conf_nr;
-
-int ip_forward_directed_bcast= 0; /* Default is off */
-
-static u8_t iftype[IP_PORT_MAX]; /* Interface in use as? */
-static int ifdefault= -1; /* Default network interface. */
-
-__dead
-static void fatal(char *label)
-{
- printf("init: %s: %s\n", label, strerror(errno));
- exit(1);
-}
-
-static void check_rm(char *device)
-/* Check if a device is not among the living. */
-{
- if (unlink(device) < 0) {
- if (errno == ENOENT) return;
- fatal(device);
- }
- printf("rm %s\n", device);
-}
-
-static void check_mknod(char *device, mode_t mode, int minor)
-/* Check if a device exists with the proper device number. */
-{
- struct stat st;
- dev_t dev;
-
- dev= makedev(major(ip_dev), minor);
-
- if (stat(device, &st) < 0) {
- if (errno != ENOENT) fatal(device);
- } else {
- if (S_ISCHR(st.st_mode) && st.st_rdev == dev) return;
- if (unlink(device) < 0) fatal(device);
- }
-
- if (mknod(device, S_IFCHR | mode, dev) < 0) fatal(device);
- printf("mknod %s c %d %d\n", device, major(ip_dev), minor);
-}
-
-static void check_ln(char *old, char *new)
-/* Check if 'old' and 'new' are still properly linked. */
-{
- struct stat st_old, st_new;
-
- if (stat(old, &st_old) < 0) fatal(old);
- if (stat(new, &st_new) < 0) {
- if (errno != ENOENT) fatal(new);
- } else {
- if (st_new.st_dev == st_old.st_dev
- && st_new.st_ino == st_old.st_ino) {
- return;
- }
- if (unlink(new) < 0) fatal(new);
- }
-
- if (link(old, new) < 0) fatal(new);
- printf("ln %s %s\n", old, new);
-}
-
-static void check_dev(int type, int ifno)
-/* Check if the device group with interface number 'ifno' exists and has the
- * proper device numbers. If 'type' is -1 then the device group must be
- * removed.
- */
-{
- static struct devlist {
- char *defname;
- mode_t mode;
- u8_t minor_off;
- } devlist[5] = {
- { (char *) "/dev/eth", 0600, ETH_DEV_OFF },
- { (char *) "/dev/psip", 0600, PSIP_DEV_OFF },
- { (char *) "/dev/ip", 0600, IP_DEV_OFF },
- { (char *) "/dev/tcp", 0666, TCP_DEV_OFF },
- { (char *) "/dev/udp", 0666, UDP_DEV_OFF },
- };
- struct devlist *dvp;
- int i;
- char device[sizeof("/dev/psip99")];
- char *dp;
-
- for (i= 0; i < sizeof(devlist) / sizeof(devlist[0]); i++) {
- dvp= &devlist[i];
- strcpy(device, dvp->defname);
- dp= device + strlen(device);
- if (ifno >= 10) *dp++ = '0' + (ifno / 10);
- *dp++ = '0' + (ifno % 10);
- *dp = 0;
-
- if (type == 0
- || (i == 0 && type != NETTYPE_ETH)
- || (i == 1 && type != NETTYPE_PSIP)
- ) {
- check_rm(device);
- if (ifno == ifdefault) check_rm(dvp->defname);
- } else {
- check_mknod(device, dvp->mode,
- if2minor(ifno, dvp->minor_off));
- if (ifno == ifdefault) check_ln(device, dvp->defname);
- }
- }
- check_mknod(IPSTAT_DEV, IPSTAT_MODE, IPSTAT_MINOR);
-}
-
-static int cfg_fd;
-static char word[16];
-static unsigned char line[256], *lineptr;
-static unsigned linenr;
-
-__dead
-static void error(void)
-{
- printf("inet: error on line %u\n", linenr);
- exit(1);
-}
-
-static int nextline(void)
-{
- /* Read a line from the configuration file, to be used by subsequent
- * token() calls. Skip empty lines, and lines where the first character
- * after leading "whitespace" is '#'. The last line of the file need
- * not be terminated by a newline. Return 1 if a line was read in
- * successfully, and 0 on EOF or error.
- */
- unsigned char *lp, c;
- int r, skip;
-
- lineptr = lp = line;
- linenr++;
- skip = -1;
-
- while ((r = read(cfg_fd, &c, 1)) == 1) {
- if (c == '\n') {
- if (skip == 0)
- break;
-
- linenr++;
- skip = -1;
- continue;
- }
-
- if (skip == -1 && c > ' ')
- skip = (c == '#');
-
- if (skip == 0 && lp < (unsigned char *) line + sizeof(line)-1)
- *lp++ = c;
- }
-
- *lp = 0;
- return (r == 1 || lp != line);
-}
-
-static void token(int need)
-{
- /* Read a word from the configuration line. Return a null string on
- * EOL. Return a punctuation as a one character word. If 'need' is
- * true then an actual word is expected at this point, so err out if
- * not.
- */
- unsigned char *wp;
- static unsigned char c= '\n';
-
- wp= (unsigned char *) word;
- *wp = 0;
-
- while (c <= ' ') {
- if (*lineptr == 0) {
- if (need) error();
- return;
- }
- c = *lineptr++;
- }
-
- do {
- if (wp < (unsigned char *) word + sizeof(word)-1) *wp++ = c;
- c = (*lineptr != 0) ? *lineptr++ : ' ';
- if (word[0] == ';' || word[0] == '{' || word[0] == '}') {
- if (need) error();
- break;
- }
- } while (c > ' ' && c != ';' && c != '{' && c != '}');
- *wp = 0;
-}
-
-static unsigned number(char *str, unsigned max)
-{
- /* Interpret a string as an unsigned decimal number, no bigger than
- * 'max'. Return this number.
- */
- char *s;
- unsigned n, d;
-
- s= str;
- n= 0;
- while ((d= (*s - '0')) < 10 && n <= max) {
- n= n * 10 + d;
- s++;
- }
- if (*s != 0 || n > max) {
- printf("inet: '%s' is not a number <= %u\n", str, max);
- error();
- }
- return n;
-}
-
-void read_conf(void)
-{
- int i, j, ifno = -1, type = -1, port = -1, enable;
- struct eth_conf *ecp;
- struct psip_conf *pcp;
- struct ip_conf *icp;
- struct stat st;
- char buf[sizeof(word)];
-
- { static int first= 1;
- if (!first) ip_panic(( "read_conf: called a second time" ));
- first= 0;
-#if 0
- *(u8_t *)0 = 0xcc; /* INT 3 */
-#endif
- }
-
-
- /* Open the configuration file. */
- if ((cfg_fd= open(PATH_INET_CONF, O_RDONLY)) == -1)
- fatal(PATH_INET_CONF);
-
- ecp= eth_conf;
- pcp= psip_conf;
- icp= ip_conf;
-
- while (nextline()) {
- token(1);
- if (strncmp(word, "eth", 3) == 0) {
- ecp->ec_ifno= ifno= number(word+3, IP_PORT_MAX-1);
- type= NETTYPE_ETH;
- port= eth_conf_nr;
- token(1);
- if (strcmp(word, "vlan") == 0) {
- token(1);
- ecp->ec_vlan= number(word, (1<<12)-1);
- token(1);
- if (strncmp(word, "eth", 3) != 0) {
- printf(
- "inet: VLAN eth%d can't be built on %s\n",
- ifno, word);
- exit(1);
- }
- ecp->ec_port= number(word+3, IP_PORT_MAX-1);
- } else {
- /* The process label consists of the driver
- * name, an underscore, and the instance
- * number.
- */
- size_t len;
- strncpy(buf, word, sizeof(buf)-1);
- buf[sizeof(buf)-1]= 0;
- token(1);
- len = strlen(buf)+1+strlen(word)+1;
- ecp->ec_label= alloc(len);
- snprintf(ecp->ec_label, len, "%s_%s", buf, word);
- ecp->ec_port= 0;
- }
- ecp++;
- eth_conf_nr++;
- } else if (strncmp(word, "psip", 4) == 0) {
- pcp->pc_ifno= ifno= number(word+4, IP_PORT_MAX-1);
- type= NETTYPE_PSIP;
- port= psip_conf_nr;
- pcp++;
- psip_conf_nr++;
- } else {
- printf("inet: Unknown device '%s'\n", word);
- error();
- }
-
- if (type == -1 || ifno == -1 || port == -1) {
- printf("inet: faulty configuration\n");
- exit(1);
- }
-
- iftype[ifno]= type;
- icp->ic_ifno= ifno;
- icp->ic_devtype= type;
- icp->ic_port= port;
- tcp_conf[tcp_conf_nr].tc_port= ip_conf_nr;
- udp_conf[udp_conf_nr].uc_port= ip_conf_nr;
-
- enable= 7; /* 1 = IP, 2 = TCP, 4 = UDP */
-
- token(0);
- if (word[0] == '{') {
- token(0);
- while (word[0] != '}') {
- if (strcmp(word, "default") == 0) {
- if (ifdefault != -1) {
- printf(
- "inet: ip%d and ip%d can't both be default\n",
- ifdefault, ifno);
- error();
- }
- ifdefault= ifno;
- token(0);
- } else
- if (strcmp(word, "no") == 0) {
- token(1);
- if (strcmp(word, "ip") == 0) {
- enable= 0;
- } else
- if (strcmp(word, "tcp") == 0) {
- enable &= ~2;
- } else
- if (strcmp(word, "udp") == 0) {
- enable &= ~4;
- } else {
- printf(
- "inet: Can't do 'no %s'\n",
- word);
- exit(1);
- }
- token(0);
- } else {
- printf("inet: Unknown option '%s'\n",
- word);
- exit(1);
- }
- if (word[0] == ';') token(0);
- else
- if (word[0] != '}') error();
- }
- token(0);
- }
- if (word[0] != ';' && word[0] != 0) error();
-
- if (enable & 1) icp++, ip_conf_nr++;
- if (enable & 2) tcp_conf_nr++;
- if (enable & 4) udp_conf_nr++;
- }
-
- if (ifdefault == -1) {
- printf("inet: No networks or no default network defined\n");
- exit(1);
- }
-
- /* Translate VLAN network references to port numbers. */
- for (i= 0; i < eth_conf_nr; i++) {
- ecp= ð_conf[i];
- if (eth_is_vlan(ecp)) {
- for (j= 0; j < eth_conf_nr; j++) {
- if (eth_conf[j].ec_ifno == ecp->ec_port
- && !eth_is_vlan(ð_conf[j])
- ) {
- ecp->ec_port= j;
- break;
- }
- }
- if (j == eth_conf_nr) {
- printf(
- "inet: VLAN eth%d can't be built on eth%d\n",
- ecp->ec_ifno, ecp->ec_port);
- exit(1);
- }
- }
- }
-
- /* Set umask 0 so we can creat mode 666 devices. */
- (void) umask(0);
-
- /* See what the device number of /dev/ip is. That's what we
- * used last time for the network devices, so we keep doing so.
- */
- if (stat("/dev/ip", &st) < 0) fatal((char *) "/dev/ip");
- ip_dev= st.st_rdev;
-
- for (i= 0; i < IP_PORT_MAX; i++) {
- /* Create network devices. */
- check_dev(iftype[i], i);
- }
-}
-
-void *alloc(size_t size)
-{
- /* Allocate memory on the heap with sbrk(). */
-
- void *addr = malloc(size);
- memset(addr, 0, size);
- return addr;
-}
-
-/*
- * $PchId: inet_config.c,v 1.10 2003/08/21 09:26:02 philip Exp $
- */
+++ /dev/null
-/*
-inet/inet_config.h
-
-Created: Nov 11, 1992 by Philip Homburg
-
-Defines values for configurable parameters. The structure definitions for
-configuration information are also here.
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__INET_CONFIG_H
-#define INET__INET_CONFIG_H
-
-/* Inet configuration file. */
-#define PATH_INET_CONF (char *) "/etc/inet.conf"
-
-#define IP_PORT_MAX 32 /* Up to this many network devices */
-extern int eth_conf_nr; /* Number of ethernets */
-extern int psip_conf_nr; /* Number of Pseudo IP networks */
-extern int ip_conf_nr; /* Number of configured IP layers */
-extern int tcp_conf_nr; /* Number of configured TCP layers */
-extern int udp_conf_nr; /* Number of configured UDP layers */
-
-extern dev_t ip_dev; /* Device number of /dev/ip */
-
-struct eth_conf
-{
- char *ec_label; /* Process label name if nonnull */
- u8_t ec_port; /* Ethernet port for VLAN if label == NULL */
- u8_t ec_ifno; /* Interface number of /dev/eth* */
- u16_t ec_vlan; /* VLAN number of this net if label == NULL */
-};
-#define eth_is_vlan(ecp) ((ecp)->ec_label == NULL)
-
-struct psip_conf
-{
- u8_t pc_ifno; /* Interface number of /dev/psip* */
-};
-
-struct ip_conf
-{
- u8_t ic_devtype; /* Underlying device type: Ethernet / PSIP */
- u8_t ic_port; /* Port of underlying device */
- u8_t ic_ifno; /* Interface number of /dev/ip*, tcp*, udp* */
-};
-
-struct tcp_conf
-{
- u8_t tc_port; /* IP port number */
-};
-
-struct udp_conf
-{
- u8_t uc_port; /* IP port number */
-};
-
-/* Types of networks. */
-#define NETTYPE_ETH 1
-#define NETTYPE_PSIP 2
-
-/* To compute the minor device number for a device on an interface. */
-#define if2minor(ifno, dev) (1 + (ifno) * 8 + (dev))
-
-#define IPSTAT_DEV (char *) "/dev/ipstat"
-#define IPSTAT_MODE 0666 /* Is this right? What about just setuid apps */
-#define IPSTAT_MINOR 0 /* Minor number of /dev/ipstat */
-
-/* Offsets of the minor device numbers within a group per interface. */
-#define ETH_DEV_OFF 0
-#define PSIP_DEV_OFF 0
-#define IP_DEV_OFF 1
-#define TCP_DEV_OFF 2
-#define UDP_DEV_OFF 3
-
-extern struct eth_conf eth_conf[IP_PORT_MAX];
-extern struct psip_conf psip_conf[IP_PORT_MAX];
-extern struct ip_conf ip_conf[IP_PORT_MAX];
-extern struct tcp_conf tcp_conf[IP_PORT_MAX];
-extern struct udp_conf udp_conf[IP_PORT_MAX];
-void read_conf(void);
-extern void *sbrk(int);
-void *alloc(size_t size);
-
-/* Options */
-extern int ip_forward_directed_bcast;
-
-#undef HTONL
-#undef HTONS
-#define HTONL htonl
-#define HTONS htons
-
-#endif /* INET__INET_CONFIG_H */
-
-/*
- * $PchId: inet_config.h,v 1.10 2003/08/21 09:24:33 philip Exp $
- */
+++ /dev/null
-/*
-inet/mnx_eth.c
-
-Created: Jan 2, 1992 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include <minix/safecopies.h>
-#include "proto.h"
-#include "osdep_eth.h"
-#include "generic/type.h"
-
-#include "generic/assert.h"
-#include "generic/buf.h"
-#include "generic/clock.h"
-#include "generic/eth.h"
-#include "generic/eth_int.h"
-#include "generic/sr.h"
-
-THIS_FILE
-
-static void setup_read(eth_port_t *eth_port);
-static void read_int(eth_port_t *eth_port, int count);
-static void eth_issue_send(eth_port_t *eth_port);
-static void write_int(eth_port_t *eth_port);
-static void eth_restart(eth_port_t *eth_port, endpoint_t endpoint);
-static void send_getstat(eth_port_t *eth_port);
-
-void osdep_eth_init()
-{
- int i, j, rport;
- struct eth_conf *ecp;
- eth_port_t *eth_port, *rep;
- cp_grant_id_t gid;
-
- /* First initialize normal ethernet interfaces */
- for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
- i<eth_conf_nr; i++, ecp++, eth_port++)
- {
- /* Set all grants to invalid */
- for (j= 0; j<IOVEC_NR; j++)
- eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
- eth_port->etp_osdep.etp_wr_vec_grant= -1;
- for (j= 0; j<RD_IOVEC; j++)
- eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
- eth_port->etp_osdep.etp_rd_vec_grant= -1;
-
- eth_port->etp_osdep.etp_state= OEPS_INIT;
- eth_port->etp_osdep.etp_flags= OEPF_EMPTY;
- eth_port->etp_osdep.etp_stat_gid= -1;
- eth_port->etp_osdep.etp_stat_buf= NULL;
-
- if (eth_is_vlan(ecp))
- continue;
-
- /* Allocate grants */
- for (j= 0; j<IOVEC_NR; j++)
- {
- if (cpf_getgrants(&gid, 1) != 1)
- {
- ip_panic((
- "osdep_eth_init: cpf_getgrants failed: %d\n",
- errno));
- }
- eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= gid;
- }
- if (cpf_getgrants(&gid, 1) != 1)
- {
- ip_panic((
- "osdep_eth_init: cpf_getgrants failed: %d\n",
- errno));
- }
- eth_port->etp_osdep.etp_wr_vec_grant= gid;
- for (j= 0; j<RD_IOVEC; j++)
- {
- if (cpf_getgrants(&gid, 1) != 1)
- {
- ip_panic((
- "osdep_eth_init: cpf_getgrants failed: %d\n",
- errno));
- }
- eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= gid;
- }
- if (cpf_getgrants(&gid, 1) != 1)
- {
- ip_panic((
- "osdep_eth_init: cpf_getgrants failed: %d\n",
- errno));
- }
- eth_port->etp_osdep.etp_rd_vec_grant= gid;
-
- eth_port->etp_osdep.etp_task= NONE;
- eth_port->etp_osdep.etp_recvconf= 0;
- ev_init(ð_port->etp_osdep.etp_recvev);
-
- sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
- i, eth_open, eth_close, eth_read,
- eth_write, eth_ioctl, eth_cancel, eth_select);
-
- eth_port->etp_flags |= EPF_ENABLED;
- eth_port->etp_vlan= 0;
- eth_port->etp_vlan_port= NULL;
- eth_port->etp_wr_pack= 0;
- eth_port->etp_rd_pack= 0;
- }
-
- /* And now come the VLANs */
- for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
- i<eth_conf_nr; i++, ecp++, eth_port++)
- {
- if (!eth_is_vlan(ecp))
- continue;
-
- eth_port->etp_osdep.etp_task= NONE;
- ev_init(ð_port->etp_osdep.etp_recvev);
-
- rport= ecp->ec_port;
- assert(rport >= 0 && rport < eth_conf_nr);
- rep= ð_port_table[rport];
- if (!(rep->etp_flags & EPF_ENABLED))
- {
- printf(
- "eth%d: underlying ethernet device %d not enabled",
- i, rport);
- continue;
- }
- if (rep->etp_vlan != 0)
- {
- printf(
- "eth%d: underlying ethernet device %d is a VLAN",
- i, rport);
- continue;
- }
-
- if (rep->etp_flags & EPF_GOT_ADDR)
- {
- eth_port->etp_ethaddr= rep->etp_ethaddr;
- printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
- eth_port->etp_flags |= EPF_GOT_ADDR;
- }
-
- sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
- i, eth_open, eth_close, eth_read,
- eth_write, eth_ioctl, eth_cancel, eth_select);
-
- eth_port->etp_flags |= EPF_ENABLED;
- eth_port->etp_vlan= ecp->ec_vlan;
- eth_port->etp_vlan_port= rep;
- assert(eth_port->etp_vlan != 0);
- eth_port->etp_wr_pack= 0;
- eth_port->etp_rd_pack= 0;
- eth_reg_vlan(rep, eth_port);
- }
-}
-
-void eth_write_port(eth_port, pack)
-eth_port_t *eth_port;
-acc_t *pack;
-{
- assert(!no_ethWritePort);
- assert(!eth_port->etp_vlan);
-
- assert(eth_port->etp_wr_pack == NULL);
- eth_port->etp_wr_pack= pack;
-
- if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
- {
- eth_port->etp_osdep.etp_flags |= OEPF_NEED_SEND;
- return;
- }
-
-
- eth_issue_send(eth_port);
-}
-
-void eth_rec(message *m)
-{
- int i, r, flags;
- eth_port_t *loc_port, *vlan_port;
-
- for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
- {
- if (loc_port->etp_osdep.etp_task == m->m_source)
- break;
- }
- if (i >= eth_conf_nr)
- {
- printf("eth_rec: message 0x%x from unknown driver %d\n",
- m->m_type, m->m_source);
- return;
- }
-
- switch (m->m_type) {
- case DL_CONF_REPLY:
- if (loc_port->etp_osdep.etp_state != OEPS_CONF_SENT) {
- printf("eth_rec: got DL_CONF_REPLY from %d while in "
- "state %d (ignoring)\n", m->m_source,
- loc_port->etp_osdep.etp_state);
- return;
- }
-
- r= m->m_netdrv_net_dl_conf.stat;
- if (r < 0)
- {
- ip_warning(("eth_rec: DL_CONF returned error %d\n",
- r));
-
- /* Just leave it in limbo. Nothing more we can do. */
- return;
- }
-
- loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_CONF;
- loc_port->etp_osdep.etp_state= OEPS_IDLE;
- loc_port->etp_flags |= EPF_ENABLED;
-
- memcpy(loc_port->etp_ethaddr.ea_addr,
- m->m_netdrv_net_dl_conf.hw_addr,
- sizeof(loc_port->etp_ethaddr.ea_addr));
- if (!(loc_port->etp_flags & EPF_GOT_ADDR))
- {
- loc_port->etp_flags |= EPF_GOT_ADDR;
-#if 0
- printf("eth_rec: calling eth_restart_ioctl\n");
-#endif
- eth_restart_ioctl(loc_port);
-
- /* Also update any VLANs on this device */
- for (i=0, vlan_port= eth_port_table; i<eth_conf_nr;
- i++, vlan_port++)
- {
- if (!(vlan_port->etp_flags & EPF_ENABLED))
- continue;
- if (vlan_port->etp_vlan_port != loc_port)
- continue;
-
- vlan_port->etp_ethaddr= loc_port->etp_ethaddr;
- vlan_port->etp_flags |= EPF_GOT_ADDR;
- eth_restart_ioctl(vlan_port);
- }
- }
-
- if (!(loc_port->etp_flags & EPF_READ_IP))
- loc_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
-
- break;
-
- case DL_STAT_REPLY:
- if (loc_port->etp_osdep.etp_state != OEPS_GETSTAT_SENT) {
- printf("eth_rec: got DL_STAT_REPLY from %d while in "
- "state %d (ignoring)\n", m->m_source,
- loc_port->etp_osdep.etp_state);
- return;
- }
-
- loc_port->etp_osdep.etp_state= OEPS_IDLE;
- loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_STAT;
-
- assert(loc_port->etp_osdep.etp_stat_gid != -1);
- cpf_revoke(loc_port->etp_osdep.etp_stat_gid);
- loc_port->etp_osdep.etp_stat_gid= -1;
- loc_port->etp_osdep.etp_stat_buf= NULL;
-
- /* Finish ioctl */
- assert(loc_port->etp_flags & EPF_GOT_ADDR);
- eth_restart_ioctl(loc_port);
-
- break;
-
- case DL_TASK_REPLY:
- if (loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
- loc_port->etp_osdep.etp_state == OEPS_SEND_SENT)
- loc_port->etp_osdep.etp_state= OEPS_IDLE;
-
- flags= m->m_netdrv_net_dl_task.flags;
-
- if (flags & DL_PACK_SEND)
- write_int(loc_port);
- if (flags & DL_PACK_RECV)
- read_int(loc_port, m->m_netdrv_net_dl_task.count);
-
- break;
-
- default:
- panic("invalid ethernet reply %d", m->m_type);
- }
-
- if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
- loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
- {
- loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_SEND;
- if (loc_port->etp_wr_pack)
- eth_issue_send(loc_port);
- }
- if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
- (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV))
- {
- loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_RECV;
- if (!(loc_port->etp_flags & EPF_READ_IP))
- setup_read (loc_port);
- }
- if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
- (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
- {
- eth_set_rec_conf(loc_port,
- loc_port->etp_osdep.etp_recvconf);
- }
- if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
- (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
- {
- send_getstat(loc_port);
- }
-}
-
-void eth_check_driver(char *label, endpoint_t endpoint)
-{
- int i;
- eth_port_t *loc_port;
- struct eth_conf *ecp;
-
- /* Re-init ethernet interface */
- for (i= 0, ecp= eth_conf, loc_port= eth_port_table;
- i<eth_conf_nr; i++, ecp++, loc_port++)
- {
- if (eth_is_vlan(ecp))
- continue;
-
- if (strcmp(ecp->ec_label, label) != 0)
- {
- /* Wrong driver */
- continue;
- }
- eth_restart(loc_port, endpoint);
- }
-}
-
-int eth_get_stat(eth_port, eth_stat)
-eth_port_t *eth_port;
-eth_stat_t *eth_stat;
-{
- cp_grant_id_t gid;
-
- assert(!eth_port->etp_vlan);
-
- if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
- ip_panic(( "eth_get_stat: getstat already in progress" ));
-
- gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
- (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
- if (gid == -1)
- {
- ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
- errno));
- }
- assert(eth_port->etp_osdep.etp_stat_gid == -1);
- eth_port->etp_osdep.etp_stat_gid= gid;
- eth_port->etp_osdep.etp_stat_buf= eth_stat;
-
- if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
- {
- eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
- return SUSPEND;
- }
-
- send_getstat(eth_port);
-
- return SUSPEND;
-}
-
-void eth_set_rec_conf (eth_port, flags)
-eth_port_t *eth_port;
-u32_t flags;
-{
- int r;
- unsigned dl_flags, mask;
- message mess;
-
- assert(!eth_port->etp_vlan);
-
- if (!(eth_port->etp_flags & EPF_GOT_ADDR))
- {
- /* We have never seen the device. */
-#if 0
- printf("eth_set_rec_conf: waiting for device to appear\n");
-#endif
- return;
- }
-
- if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
- {
-#if 0
- printf(
- "eth_set_rec_conf: setting OEPF_NEED_CONF, state = %d\n",
- eth_port->etp_osdep.etp_state);
-#endif
- eth_port->etp_osdep.etp_flags |= OEPF_NEED_CONF;
- return;
- }
-
- mask = NWEO_EN_BROAD | NWEO_EN_MULTI | NWEO_EN_PROMISC;
- if ((eth_port->etp_osdep.etp_recvconf & mask) == (flags & mask))
- {
- /* No change for the driver, so don't send an update */
- return;
- }
-
- eth_port->etp_osdep.etp_recvconf= flags;
- dl_flags= DL_NOMODE;
- if (flags & NWEO_EN_BROAD)
- dl_flags |= DL_BROAD_REQ;
- if (flags & NWEO_EN_MULTI)
- dl_flags |= DL_MULTI_REQ;
- if (flags & NWEO_EN_PROMISC)
- dl_flags |= DL_PROMISC_REQ;
-
- mess.m_type= DL_CONF;
- mess.m_net_netdrv_dl_conf.mode = dl_flags;
-
- assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
- r= asynsend(eth_port->etp_osdep.etp_task, &mess);
- eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
-
- if (r < 0)
- {
- printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
- eth_port->etp_osdep.etp_task, r);
- return;
- }
-}
-
-static void eth_issue_send(eth_port)
-eth_port_t *eth_port;
-{
- int i, r, pack_size;
- acc_t *pack, *pack_ptr;
- iovec_s_t *iovec;
- message m;
-
- iovec= eth_port->etp_osdep.etp_wr_iovec;
- pack= eth_port->etp_wr_pack;
- pack_size= 0;
- for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
- pack_ptr= pack_ptr->acc_next)
- {
- r= cpf_setgrant_direct(iovec[i].iov_grant,
- eth_port->etp_osdep.etp_task,
- (vir_bytes)ptr2acc_data(pack_ptr),
- (vir_bytes)pack_ptr->acc_length,
- CPF_READ);
- if (r != 0)
- {
- ip_panic((
- "eth_write_port: cpf_setgrant_direct failed: %d\n",
- errno));
- }
- pack_size += iovec[i].iov_size= pack_ptr->acc_length;
- }
- if (i>= IOVEC_NR)
- {
- pack= bf_pack(pack); /* packet is too fragmented */
- eth_port->etp_wr_pack= pack;
- pack_size= 0;
- for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
- i++, pack_ptr= pack_ptr->acc_next)
- {
- r= cpf_setgrant_direct(iovec[i].iov_grant,
- eth_port->etp_osdep.etp_task,
- (vir_bytes)ptr2acc_data(pack_ptr),
- (vir_bytes)pack_ptr->acc_length,
- CPF_READ);
- if (r != 0)
- {
- ip_panic((
- "eth_write_port: cpf_setgrant_direct failed: %d\n",
- errno));
- }
- pack_size += iovec[i].iov_size= pack_ptr->acc_length;
- }
- }
- assert (i< IOVEC_NR);
- assert (pack_size >= ETH_MIN_PACK_SIZE);
-
- r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
- eth_port->etp_osdep.etp_task,
- (vir_bytes)iovec,
- (vir_bytes)(i * sizeof(iovec[0])),
- CPF_READ);
- if (r != 0)
- {
- ip_panic((
- "eth_write_port: cpf_setgrant_direct failed: %d\n",
- errno));
- }
- m.m_type= DL_WRITEV_S;
- m.m_net_netdrv_dl_writev_s.count= i;
- m.m_net_netdrv_dl_writev_s.grant= eth_port->etp_osdep.etp_wr_vec_grant;
-
- assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
- r= asynsend(eth_port->etp_osdep.etp_task, &m);
-
- if (r < 0)
- {
- printf("eth_issue_send: send to %d failed: %d\n",
- eth_port->etp_osdep.etp_task, r);
- return;
- }
- eth_port->etp_osdep.etp_state= OEPS_SEND_SENT;
-}
-
-static void write_int(eth_port_t *eth_port)
-{
- acc_t *pack;
- int multicast;
- u8_t *eth_dst_ptr;
-
- pack= eth_port->etp_wr_pack;
- if (pack == NULL)
- {
- printf("write_int: strange no packet on eth port %d\n",
- (int)(eth_port-eth_port_table));
- eth_restart_write(eth_port);
- return;
- }
-
- eth_port->etp_wr_pack= NULL;
-
- eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
- multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
- if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
- {
- assert(!no_ethWritePort);
- no_ethWritePort= 1;
- eth_arrive(eth_port, pack, bf_bufsize(pack));
- assert(no_ethWritePort);
- no_ethWritePort= 0;
- }
- else
- bf_afree(pack);
-
- eth_restart_write(eth_port);
-}
-
-static void read_int(eth_port, count)
-eth_port_t *eth_port;
-int count;
-{
- acc_t *pack, *pack_ptr, *cut_pack;
- iovec_s_t *iovec;
- int i, r;
-
- /* A buggy driver might try to feed us a reply for a request we never
- * sent. Don't let this cause a crash further up.
- */
- if (!(eth_port->etp_flags & EPF_READ_IP))
- {
- printf("mnx_eth`read_int: read reply with no read going on\n");
- return;
- }
-
- pack= eth_port->etp_rd_pack;
- eth_port->etp_rd_pack= NULL;
-
- /* Invalidate the grants first, so that the ethernet driver can no
- * longer modify the contents of the packet.
- */
- iovec= eth_port->etp_osdep.etp_rd_iovec;
- for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
- i++, pack_ptr= pack_ptr->acc_next)
- {
- r= cpf_setgrant_disable(iovec[i].iov_grant);
- if (r != 0)
- {
- ip_panic((
- "mnx_eth`read_int: cpf_setgrant_disable failed: %d\n",
- errno));
- }
- }
-
- if (count < ETH_MIN_PACK_SIZE)
- {
- printf("mnx_eth`read_int: packet size too small (%d)\n",
- count);
- bf_afree(pack);
- }
- else if (count > ETH_MAX_PACK_SIZE_TAGGED)
- {
- printf("mnx_eth`read_int: packet size too big (%d)\n",
- count);
- bf_afree(pack);
- }
- else
- {
- cut_pack= bf_cut(pack, 0, count);
- bf_afree(pack);
-
- assert(!no_ethWritePort);
- no_ethWritePort= 1;
- eth_arrive(eth_port, cut_pack, count);
- assert(no_ethWritePort);
- no_ethWritePort= 0;
- }
-
- eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
- setup_read(eth_port);
-}
-
-static void setup_read(eth_port)
-eth_port_t *eth_port;
-{
- acc_t *pack, *pack_ptr;
- message mess;
- iovec_s_t *iovec;
- int i, r;
-
- assert(!eth_port->etp_vlan);
- assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
-
- if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
- {
- eth_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
-
- return;
- }
-
- assert (!eth_port->etp_rd_pack);
-
- iovec= eth_port->etp_osdep.etp_rd_iovec;
- pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
-
- for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
- i++, pack_ptr= pack_ptr->acc_next)
- {
- r= cpf_setgrant_direct(iovec[i].iov_grant,
- eth_port->etp_osdep.etp_task,
- (vir_bytes)ptr2acc_data(pack_ptr),
- (vir_bytes)pack_ptr->acc_length,
- CPF_WRITE);
- if (r != 0)
- {
- ip_panic((
- "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
- errno));
- }
- iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
- }
- assert (!pack_ptr);
-
- r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
- eth_port->etp_osdep.etp_task,
- (vir_bytes)iovec,
- (vir_bytes)(i * sizeof(iovec[0])),
- CPF_READ);
- if (r != 0)
- {
- ip_panic((
- "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
- errno));
- }
-
- mess.m_type= DL_READV_S;
- mess.m_net_netdrv_dl_readv_s.count= i;
- mess.m_net_netdrv_dl_readv_s.grant= eth_port->etp_osdep.etp_rd_vec_grant;
-
- assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
-
- r= asynsend(eth_port->etp_osdep.etp_task, &mess);
- eth_port->etp_osdep.etp_state= OEPS_RECV_SENT;
-
- if (r < 0)
- {
- printf(
- "mnx_eth`setup_read: asynsend to %d failed: %d\n",
- eth_port->etp_osdep.etp_task, r);
- }
- eth_port->etp_rd_pack= pack;
- eth_port->etp_flags |= EPF_READ_IP;
- eth_port->etp_flags |= EPF_READ_SP;
-}
-
-static void eth_restart(eth_port_t *eth_port, endpoint_t endpoint)
-{
- int r;
- unsigned flags, dl_flags;
- cp_grant_id_t gid;
- message mess;
-
- eth_port->etp_osdep.etp_task= endpoint;
-
- switch(eth_port->etp_osdep.etp_state)
- {
- case OEPS_INIT:
- case OEPS_CONF_SENT:
- case OEPS_RECV_SENT:
- case OEPS_SEND_SENT:
- /* We can safely ignore the pending CONF, RECV, and SEND
- * requests. If this is the first time that we see this
- * driver at all, that's fine too.
- */
- eth_port->etp_osdep.etp_state= OEPS_IDLE;
- break;
- case OEPS_GETSTAT_SENT:
- /* Set the OEPF_NEED_STAT to trigger a new request */
- eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
- eth_port->etp_osdep.etp_state= OEPS_IDLE;
- break;
- }
-
- /* If there is a pending GETSTAT request then we have to create a
- * new grant.
- */
- if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
- {
- assert(eth_port->etp_osdep.etp_stat_gid != -1);
- cpf_revoke(eth_port->etp_osdep.etp_stat_gid);
-
- gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
- (vir_bytes)eth_port->etp_osdep.etp_stat_buf,
- sizeof(*eth_port->etp_osdep.etp_stat_buf), CPF_WRITE);
- if (gid == -1)
- {
- ip_panic((
- "eth_restart: cpf_grant_direct failed: %d\n",
- errno));
- }
- eth_port->etp_osdep.etp_stat_gid= gid;
- }
-
- flags= eth_port->etp_osdep.etp_recvconf;
- dl_flags= DL_NOMODE;
- if (flags & NWEO_EN_BROAD)
- dl_flags |= DL_BROAD_REQ;
- if (flags & NWEO_EN_MULTI)
- dl_flags |= DL_MULTI_REQ;
- if (flags & NWEO_EN_PROMISC)
- dl_flags |= DL_PROMISC_REQ;
- mess.m_type= DL_CONF;
- mess.m_net_netdrv_dl_conf.mode= dl_flags;
-
- compare(eth_port->etp_osdep.etp_state, ==, OEPS_IDLE);
- r= asynsend(eth_port->etp_osdep.etp_task, &mess);
- if (r<0)
- {
- printf(
- "eth_restart: send to ethernet task %d failed: %d\n",
- eth_port->etp_osdep.etp_task, r);
- return;
- }
- eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
-
- if (eth_port->etp_wr_pack)
- {
- bf_afree(eth_port->etp_wr_pack);
- eth_port->etp_wr_pack= NULL;
- eth_restart_write(eth_port);
- }
- if (eth_port->etp_rd_pack)
- {
- bf_afree(eth_port->etp_rd_pack);
- eth_port->etp_rd_pack= NULL;
- eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
- }
-
-}
-
-static void send_getstat(eth_port)
-eth_port_t *eth_port;
-{
- int r;
- message mess;
-
- mess.m_type= DL_GETSTAT_S;
- mess.m_net_netdrv_dl_getstat_s.grant= eth_port->etp_osdep.etp_stat_gid;
-
- assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
-
- r= asynsend(eth_port->etp_osdep.etp_task, &mess);
- eth_port->etp_osdep.etp_state= OEPS_GETSTAT_SENT;
-
- if (r != OK)
- ip_panic(( "eth_get_stat: asynsend failed: %d", r));
-}
-
-/*
- * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $
- */
+++ /dev/null
-/*
-inet/mq.c
-
-Created: Jan 3, 1992 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#include "inet.h"
-#include "mq.h"
-#include "generic/assert.h"
-
-THIS_FILE
-
-#define MQ_SIZE 128
-
-static mq_t mq_list[MQ_SIZE];
-static mq_t *mq_freelist;
-
-void mq_init()
-{
- int i;
-
- mq_freelist= NULL;
- for (i= 0; i<MQ_SIZE; i++)
- {
- mq_list[i].mq_next= mq_freelist;
- mq_freelist= &mq_list[i];
- mq_list[i].mq_allocated= 0;
- }
-}
-
-mq_t *mq_get()
-{
- mq_t *mq;
-
- mq= mq_freelist;
- assert(mq != NULL);
-
- mq_freelist= mq->mq_next;
- mq->mq_next= NULL;
- assert(mq->mq_allocated == 0);
- mq->mq_allocated= 1;
- return mq;
-}
-
-void mq_free(mq)
-mq_t *mq;
-{
- mq->mq_next= mq_freelist;
- mq_freelist= mq;
- assert(mq->mq_allocated == 1);
- mq->mq_allocated= 0;
-}
-
-/*
- * $PchId: mq.c,v 1.7 1998/10/23 20:10:47 philip Exp $
- */
+++ /dev/null
-/*
-inet/mq.h
-
-Created: Jan 3, 1992 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__MQ_H
-#define INET__MQ_H
-
-#include <minix/chardriver.h>
-
-typedef struct sr_req {
- enum {
- SRR_READ,
- SRR_WRITE,
- SRR_IOCTL
- } srr_type;
- devminor_t srr_minor;
- endpoint_t srr_endpt;
- cp_grant_id_t srr_grant;
- union {
- size_t srr_size; /* for SRR_READ, SRR_WRITE */
- unsigned long srr_req; /* for SRR_IOCTL */
- };
- int srr_flags;
- cdev_id_t srr_id;
-} sr_req_t;
-
-typedef struct mq
-{
- sr_req_t mq_req;
- struct mq *mq_next;
- int mq_allocated;
-} mq_t;
-
-mq_t *mq_get(void);
-void mq_free(mq_t *mq);
-void mq_init(void);
-
-#endif /* INET__MQ_H */
-
-/*
- * $PchId: mq.h,v 1.4 1995/11/21 06:40:30 philip Exp $
- */
+++ /dev/null
-/*
-inet/osdep_eth.h
-
-Created: Dec 30, 1991 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__OSDEP_ETH_H
-#define INET__OSDEP_ETH_H
-
-#include "generic/event.h"
-
-#define IOVEC_NR 16
-#define RD_IOVEC ((ETH_MAX_PACK_SIZE + BUF_S -1)/BUF_S)
-
-typedef struct osdep_eth_port
-{
- int etp_state;
- int etp_flags;
- endpoint_t etp_task;
- int etp_recvconf;
- iovec_s_t etp_wr_iovec[IOVEC_NR];
- cp_grant_id_t etp_wr_vec_grant;
- iovec_s_t etp_rd_iovec[RD_IOVEC];
- cp_grant_id_t etp_rd_vec_grant;
- event_t etp_recvev;
- cp_grant_id_t etp_stat_gid;
- eth_stat_t *etp_stat_buf;
-} osdep_eth_port_t;
-
-#define OEPS_INIT 0 /* Not initialized */
-#define OEPS_CONF_SENT 1 /* Conf. request has been sent */
-#define OEPS_IDLE 2 /* Device is ready to accept requests */
-#define OEPS_RECV_SENT 3 /* Recv. request has been sent */
-#define OEPS_SEND_SENT 4 /* Send request has been sent */
-#define OEPS_GETSTAT_SENT 5 /* GETSTAT request has been sent */
-
-#define OEPF_EMPTY 0
-#define OEPF_NEED_RECV 1 /* Issue recv. request when the state becomes
- * idle
- */
-#define OEPF_NEED_SEND 2 /* Issue send request when the state becomes
- * idle
- */
-#define OEPF_NEED_CONF 4 /* Issue conf request when the state becomes
- * idle
- */
-#define OEPF_NEED_STAT 8 /* Issue getstat request when the state becomes
- * idle
- */
-
-#endif /* INET__OSDEP_ETH_H */
-
-/*
- * $PchId: osdep_eth.h,v 1.6 2001/04/20 06:39:54 philip Exp $
- */
+++ /dev/null
-/*
-inet/proto.h
-
-Created: Jan 2, 1992 by Philip Homburg
-
-Copyright 1995 Philip Homburg
-*/
-
-/* clock.c */
-
-void clck_tick(message *mess);
-
-/* mnx_eth.c */
-
-void eth_rec(message *m);
-void eth_check_driver(char *label, endpoint_t endpoint);
-
-/* rtinfo.c */
-
-void rtinfo_init(void);
-
-/* sr.c */
-
-void sr_rec(message *m, int ipc_status);
-
-/*
- * $PchId: proto.h,v 1.4 1995/11/21 06:36:37 philip Exp $
- */
+++ /dev/null
-/*
-inet/qp.c
-
-Query parameters
-
-Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
-*/
-
-#include "inet.h"
-#include "generic/assert.h"
-
-#include "queryparam.h"
-
-#include "generic/buf.h"
-#include "generic/clock.h"
-#include "generic/event.h"
-#include "generic/type.h"
-#include "generic/sr.h"
-
-#include "generic/tcp_int.h"
-#include "generic/udp_int.h"
-#include "mq.h"
-#include "qp.h"
-#include "sr_int.h"
-
-THIS_FILE
-
-#define MAX_REQ 1024 /* Maximum size of a request */
-
-#define QP_FD_NR 4
-
-typedef struct qp_fd
-{
- int qf_flags;
- int qf_srfd;
- get_userdata_t qf_get_userdata;
- put_userdata_t qf_put_userdata;
- acc_t *qf_req_pkt;
-} qp_fd_t;
-
-#define QFF_EMPTY 0
-#define QFF_INUSE 1
-
-static qp_fd_t qp_fd_table[QP_FD_NR];
-
-static struct export_param_list inet_ex_list[]=
-{
- QP_VARIABLE(sr_fd_table),
- QP_VARIABLE(ip_dev),
- QP_VARIABLE(tcp_fd_table),
- QP_VARIABLE(tcp_conn_table),
- QP_VARIABLE(tcp_cancel_f),
- QP_VECTOR(udp_port_table, udp_port_table, ip_conf_nr),
- QP_VARIABLE(udp_fd_table),
- QP_END()
-};
-
-static struct export_params inet_ex_params= { inet_ex_list, NULL };
-
-static struct queryvars {
- /* Input */
- acc_t *param;
-
- /* Output */
- qp_fd_t *qp_fd;
- off_t fd_offset;
- size_t rd_bytes_left;
- off_t outbuf_off;
- char outbuf[256];
-
- int r; /* result */
-} *qvars;
-
-
-static int qp_open ARGS(( int port, int srfd,
- get_userdata_t get_userdata, put_userdata_t put_userdata,
- put_pkt_t put_pkt, select_res_t select_res ));
-static void qp_close ARGS(( int fd ));
-static int qp_read ARGS(( int fd, size_t count ));
-static int qp_write ARGS(( int fd, size_t count ));
-static int qp_ioctl ARGS(( int fd, ioreq_t req ));
-static int qp_cancel ARGS(( int fd, int which_operation ));
-static int qp_select ARGS(( int fd, unsigned operations ));
-static qp_fd_t *get_qp_fd ARGS(( int fd ));
-static int do_query ARGS(( qp_fd_t *qp_fd, acc_t *pkt, int count ));
-static int qp_getc ARGS(( void ));
-static void qp_putc ARGS(( struct queryvars *qv, int c ));
-static void qp_buffree ARGS(( int priority ));
-#ifdef BUF_CONSISTENCY_CHECK
-static void qp_bufcheck ARGS(( void ));
-#endif
-
-void qp_init()
-{
- int i;
-
- qp_export(&inet_ex_params);
-
- for (i= 0; i<QP_FD_NR; i++)
- qp_fd_table[i].qf_flags= QFF_EMPTY;
-
-#ifndef BUF_CONSISTENCY_CHECK
- bf_logon(qp_buffree);
-#else
- bf_logon(qp_buffree, qp_bufcheck);
-#endif
-
- sr_add_minor(IPSTAT_MINOR, 0, qp_open, qp_close, qp_read, qp_write,
- qp_ioctl, qp_cancel, qp_select);
-}
-
-static int qp_open(port, srfd, get_userdata, put_userdata, put_pkt,
- select_res)
-int port;
-int srfd;
-get_userdata_t get_userdata;
-put_userdata_t put_userdata;
-put_pkt_t put_pkt;
-select_res_t select_res;
-{
- int i;
- qp_fd_t *qp_fd;
-
- for (i= 0; i< QP_FD_NR; i++)
- {
- if (!(qp_fd_table[i].qf_flags & QFF_INUSE))
- break;
- }
- if (i >= QP_FD_NR)
- return EAGAIN;
- qp_fd= &qp_fd_table[i];
- qp_fd->qf_flags= QFF_INUSE;
- qp_fd->qf_srfd= srfd;
- qp_fd->qf_get_userdata= get_userdata;
- qp_fd->qf_put_userdata= put_userdata;
- qp_fd->qf_req_pkt= NULL;
-
- return i;
-}
-
-static void qp_close(fd)
-int fd;
-{
- qp_fd_t *qp_fd;
-
- qp_fd= get_qp_fd(fd);
- qp_fd->qf_flags= QFF_EMPTY;
- if (qp_fd->qf_req_pkt)
- {
- bf_afree(qp_fd->qf_req_pkt);
- qp_fd->qf_req_pkt= NULL;
- }
-}
-
-static int qp_read(fd, count)
-int fd;
-size_t count;
-{
- int r;
- acc_t *pkt;
- qp_fd_t *qp_fd;
-
- qp_fd= get_qp_fd(fd);
- pkt= qp_fd->qf_req_pkt;
- qp_fd->qf_req_pkt= NULL;
- if (!pkt)
- {
- /* Nothing to do */
- qp_fd->qf_put_userdata(qp_fd->qf_srfd, EIO, 0,
- FALSE /* !for_ioctl*/);
- return OK;
- }
- r= do_query(qp_fd, pkt, count);
- qp_fd->qf_put_userdata(qp_fd->qf_srfd, r, 0,
- FALSE /* !for_ioctl*/);
- return OK;
-}
-
-static int qp_write(fd, count)
-int fd;
-size_t count;
-{
- acc_t *pkt;
- qp_fd_t *qp_fd;
-
- qp_fd= get_qp_fd(fd);
- if (count > MAX_REQ)
- {
- qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOMEM, 0,
- FALSE /* !for_ioctl*/);
- return OK;
- }
- pkt= qp_fd->qf_get_userdata(qp_fd->qf_srfd, 0, count,
- FALSE /* !for_ioctl*/);
- if (!pkt)
- {
- qp_fd->qf_get_userdata(qp_fd->qf_srfd, EFAULT, 0,
- FALSE /* !for_ioctl*/);
- return OK;
- }
- if (qp_fd->qf_req_pkt)
- {
- bf_afree(qp_fd->qf_req_pkt);
- qp_fd->qf_req_pkt= NULL;
- }
- qp_fd->qf_req_pkt= pkt;
- qp_fd->qf_get_userdata(qp_fd->qf_srfd, count, 0,
- FALSE /* !for_ioctl*/);
- return OK;
-}
-
-static int qp_ioctl(fd, req)
-int fd;
-ioreq_t req;
-{
- qp_fd_t *qp_fd;
-
- qp_fd= get_qp_fd(fd);
- qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOTTY, 0,
- TRUE /* for_ioctl*/);
- return OK;
-}
-
-static int qp_cancel(fd, which_operation)
-int fd;
-int which_operation;
-{
- ip_panic(( "qp_cancel: should not be here, no blocking calls" ));
- return OK;
-}
-
-static int qp_select(fd, operations)
-int fd;
-unsigned operations;
-{
- unsigned resops;
-
- resops= 0;
- if (operations & SR_SELECT_READ)
- resops |= SR_SELECT_READ;
- if (operations & SR_SELECT_WRITE)
- resops |= SR_SELECT_WRITE;
- return resops;
-}
-
-static qp_fd_t *get_qp_fd(fd)
-int fd;
-{
- qp_fd_t *qp_fd;
-
- assert(fd >= 0 && fd < QP_FD_NR);
- qp_fd= &qp_fd_table[fd];
- assert(qp_fd->qf_flags & QFF_INUSE);
- return qp_fd;
-}
-
-static int do_query(qp_fd, pkt, count)
-qp_fd_t *qp_fd;
-acc_t *pkt;
-int count;
-{
- struct queryvars qv;
- void *addr;
- size_t n, size;
- int byte;
- int more;
- static char hex[]= "0123456789ABCDEF";
-
- qvars= &qv;
- qv.param= pkt; pkt= NULL;
- qv.qp_fd= qp_fd;
- qv.fd_offset= 0;
- qv.outbuf_off= 0;
- qv.rd_bytes_left= count;
- qv.r= 0;
-
- do {
- more= queryparam(qp_getc, &addr, &size);
- for (n= 0; n < size; n++) {
- byte= ((u8_t *) addr)[n];
- qp_putc(&qv, hex[byte >> 4]);
- qp_putc(&qv, hex[byte & 0x0F]);
- }
- qp_putc(&qv, more ? ',' : 0);
- if (qv.r)
- break;
- } while (more);
- if (qv.param)
- {
- assert(0);
- bf_afree(qv.param);
- qv.param= NULL;
- }
- if (qv.r)
- return qv.r;
- return qv.fd_offset;
-}
-
-static int qp_getc()
-{
- /* Return one character of the names to search for. */
- acc_t *pkt;
- struct queryvars *qv= qvars;
- u8_t c;
-
- pkt= qv->param;
- qv->param= NULL;
- if (pkt == NULL)
- return 0;
-
- assert(bf_bufsize(pkt) > 0);
- c= ptr2acc_data(pkt)[0];
- if (bf_bufsize(pkt) > 1)
- qv->param= bf_delhead(pkt, 1);
- else
- {
- bf_afree(pkt);
- qv->param= NULL;
- }
-
- return c;
-}
-
-static void qp_putc(qv, c)
-struct queryvars *qv;
-int c;
-{
- /* Send one character back to the user. */
- acc_t *pkt;
- qp_fd_t *qp_fd;
- size_t bytes_left;
- off_t off;
-
- bytes_left= qv->rd_bytes_left;
- if (qv->r || bytes_left == 0)
- return;
-
- off= qv->outbuf_off;
- assert(off < sizeof(qv->outbuf));
- qv->outbuf[off]= c;
- off++;
- bytes_left--;
- qv->rd_bytes_left= bytes_left;
- if (c != '\0' && off < sizeof(qv->outbuf) && bytes_left != 0)
- {
- qv->outbuf_off= off;
- return;
- }
-
- pkt= bf_memreq(off);
- assert(pkt->acc_next == NULL);
- memcpy(ptr2acc_data(pkt), qv->outbuf, off);
- qp_fd= qv->qp_fd;
- qv->r= qp_fd->qf_put_userdata(qp_fd->qf_srfd, qv->fd_offset,
- pkt, FALSE /* !for_ioctl*/ );
- qv->fd_offset += off;
- qv->outbuf_off= 0;
-}
-
-static void qp_buffree (priority)
-int priority;
-{
- /* For the moment, we are not going to free anything */
-}
-
-#ifdef BUF_CONSISTENCY_CHECK
-static void qp_bufcheck()
-{
- int i;
- qp_fd_t *qp_fd;
-
- for (i= 0, qp_fd= qp_fd_table; i<QP_FD_NR; i++, qp_fd++)
- {
- if (!(qp_fd->qf_flags & QFF_INUSE))
- continue;
- if (qp_fd->qf_req_pkt)
- bf_check_acc(qp_fd->qf_req_pkt);
- }
-}
-#endif
-
-/*
- * $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $
- */
+++ /dev/null
-/*
-inet/qp.h
-
-Handle queryparams requests
-
-Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Copyright 1995 Philip Homburg
-*/
-
-#ifndef INET__QP_H
-#define INET__QP_H
-
-void qp_init ARGS(( void ));
-
-#endif /* INET__QP_H */
-
-/*
- * $PchId: qp.h,v 1.4 2005/01/29 18:08:06 philip Exp $
- */
+++ /dev/null
-/* queryparam() - allow program parameters to be queried
- * Author: Kees J. Bot
- * 21 Apr 1994
- */
-#define nil 0
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include "queryparam.h"
-
-#if EXAMPLE
-struct stat st[2];
-
-struct export_param_list ex_st_list[]= {
- QP_VARIABLE(st),
- QP_ARRAY(st),
- QP_FIELD(st_dev, struct stat),
- QP_FIELD(st_ino, struct stat),
- ...
- QP_END()
-};
-
-struct buf { block_t b_blocknr; ... } *buf;
-size_t nr_bufs;
-
-struct export_param_list ex_buf_list[]=
- QP_VECTOR(buf, buf, nr_bufs),
- QP_FIELD(b_blocknr),
- ...
- QP_END()
-};
-
-struct export_params ex_st= { ex_st_list, 0 };
-struct export_params ex_buf= { ex_buf_list, 0 };
-#endif
-
-#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
-
-static int isvar(int c)
-{
- return between('a', c, 'z') || between('A', c, 'Z')
- || between('0', c, '9') || c == '_';
-}
-
-static struct export_params *params;
-
-void qp_export(struct export_params *ex_params)
-{
- /* Add a set of exported parameters. */
-
- if (ex_params->next == nil) {
- ex_params->next= params;
- params= ex_params;
- }
-}
-
-int queryparam(int qgetc(void), void **poffset, size_t *psize)
-{
- char *prefix;
- struct export_params *ep;
- struct export_param_list *epl;
- size_t offset= 0;
- size_t size= -1;
- size_t n;
- static size_t retval;
- int c, firstc;
-
- firstc= c= (*qgetc)();
- if (c == '&' || c == '$') c= (*qgetc)();
- if (!isvar(c)) goto fail;
-
- if ((ep= params) == nil) goto fail;
- epl= ep->list;
-
- while (c != 0 && c != ',') {
- prefix= (char *) "x";
- n= 0;
-
- for (;;) {
- while (epl->name == nil) {
- if ((ep= ep->next) == nil) goto fail;
- epl= ep->list;
- }
- if (strncmp(prefix, epl->name, n) == 0) {
- prefix= epl->name;
- while (prefix[n] != 0 && c == prefix[n]) {
- n++;
- c= (*qgetc)();
- }
- }
- if (prefix[n] == 0 && (!isvar(c) || prefix[0] == '[')) {
- /* Got a match. */
- break;
- }
- epl++;
- }
-
- if (prefix[0] == '[') {
- /* Array reference. */
- size_t idx= 0, cnt= 1, max= size / epl->size;
-
- while (between('0', c, '9')) {
- idx= idx * 10 + (c - '0');
- if (idx > max) goto fail;
- c= (*qgetc)();
- }
- if (c == ':') {
- cnt= 0;
- while (between('0', (c= (*qgetc)()), '9')) {
- cnt= cnt * 10 + (c - '0');
- }
- }
- if (c != ']') goto fail;
- if (idx + cnt > max) cnt= max - idx;
- offset+= idx * epl->size;
- size= cnt * epl->size;
- c= (*qgetc)();
- } else
- if (epl->size == -1) {
- /* Vector. */
- offset= (size_t) * (void **) epl->offset;
- size= (* (size_t *) epl[1].offset) * epl[1].size;
- } else {
- /* Variable or struct field. */
- offset+= (size_t) epl->offset;
- if ((size_t) epl->offset > size) goto fail;
- size-= (size_t) epl->offset;
- if (size < epl->size) goto fail;
- size= epl->size;
- }
- }
- if (firstc == '&' || firstc == '$') {
- retval= firstc == '&' ? offset : size;
- offset= (size_t) &retval;
- size= sizeof(retval);
- }
- if (c != 0 && c != ',') goto fail;
- *poffset= (void *) offset;
- *psize= size;
- return c != 0;
-fail:
- while (c != 0 && c != ',') c= (*qgetc)();
- *poffset= nil;
- *psize= 0;
- return c != 0;
-}
-
-/*
- * $PchId: queryparam.c,v 1.1 2005/06/28 14:30:56 philip Exp $
- */
+++ /dev/null
-/* queryparam.h - query program parameters Author: Kees J. Bot
- * 22 Apr 1994
- */
-#ifndef _MINIX__QUERYPARAM_H
-#define _MINIX__QUERYPARAM_H
-
-
-typedef size_t _mnx_size_t;
-
-struct export_param_list {
- char *name; /* "variable", "[", ".field", or NULL. */
- void *offset; /* Address of a variable or field offset. */
- size_t size; /* Size of the resulting object. */
-};
-
-struct export_params {
- struct export_param_list *list; /* List of exported parameters. */
- struct export_params *next; /* Link several sets of parameters. */
-};
-
-#ifdef __STDC__
-#define qp_stringize(var) (char *) #var
-#define qp_dotstringize(var) "." (char *) #var
-#else
-#define qp_stringize(var) "var"
-#define qp_dotstringize(var) ".var"
-#endif
-#define QP_VARIABLE(var) { qp_stringize(var), &(var), sizeof(var) }
-#define QP_ARRAY(var) { (char *) "[", 0, sizeof((var)[0]) }
-#define QP_VECTOR(var,ptr,len) { qp_stringize(var), &(ptr), -1 },\
- { (char *) "[", &(len), sizeof(*(ptr)) }
-#define QP_FIELD(field, type) { qp_dotstringize(field), \
- (void *)offsetof(type, field), \
- sizeof(((type *)0)->field) }
-#define QP_END() { 0, 0, 0 }
-
-void qp_export(struct export_params *_ex_params);
-int queryparam(int (*_qgetc) (void), void **_paddress, _mnx_size_t
- *_psize);
-_mnx_size_t paramvalue(char **_value, void *_address, _mnx_size_t
- _size);
-#endif /* _MINIX__QUERYPARAM_H */
-
-/* $PchId: queryparam.h,v 1.1 2005/06/28 14:31:26 philip Exp $ */
+++ /dev/null
-/*
- * Mock net.route sysctl(2) subtree implementation using RMIB. This code
- * serves as a temporary bridge to allow libc to switch from the original,
- * native MINIX3 getifaddrs(3) to the NetBSD getifaddrs(3). As such, it
- * implements only a small subset of NetBSD's full net.route functionality,
- * although also more than needed only to imitate the MINIX3 getifaddrs(3).
- */
-
-#include "inet.h"
-#include "generic/type.h"
-#include "generic/buf.h"
-#include "generic/event.h"
-#include "generic/ip_int.h"
-#include "osdep_eth.h"
-#include "generic/eth_int.h"
-#include <netinet/in.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <net/route.h>
-#include <sys/sysctl.h>
-#include <minix/rmib.h>
-#include <assert.h>
-
-/* Max. number of bytes for a full sockaddr_dl structure, including data. */
-#define SDL_BUFSIZE (sizeof(struct sockaddr_dl) + 32)
-
-static const char padbuf[RT_ROUNDUP(0)] = { 0 };
-
-/*
- * Compute the length for, and possibly copy out, an interface information or
- * interface address record with an associated set of zero or more routing
- * table addresses. The addresses are padded as necessary. Store the full
- * record length and the address bitmap before copying out the entire record.
- */
-static ssize_t
-copyout_rta(void * hdr, size_t size, u_short * msglen, int * addrs,
- void * rta_map[RTAX_MAX], size_t rta_len[RTAX_MAX],
- struct rmib_oldp * oldp, ssize_t off)
-{
- iovec_t iov[1 + RTAX_MAX * 2];
- size_t len, total, padlen;
- unsigned int i, iovcnt;
- int mask;
-
- iovcnt = 0;
- iov[iovcnt].iov_addr = (vir_bytes)hdr;
- iov[iovcnt++].iov_size = size;
-
- total = size;
- mask = 0;
-
- /*
- * Any addresses in the given map should be stored in the numbering
- * order of the map.
- */
- for (i = 0; i < RTAX_MAX; i++) {
- if (rta_map[i] == NULL)
- continue;
-
- assert(iovcnt < __arraycount(iov));
- iov[iovcnt].iov_addr = (vir_bytes)rta_map[i];
- iov[iovcnt++].iov_size = len = rta_len[i];
-
- padlen = RT_ROUNDUP(len) - len;
- if (padlen > 0) {
- assert(iovcnt < __arraycount(iov));
- iov[iovcnt].iov_addr = (vir_bytes)padbuf;
- iov[iovcnt++].iov_size = padlen;
- }
-
- total += len + padlen;
- mask |= (1 << i);
- }
-
- /* If only the length was requested, return it now. */
- if (oldp == NULL)
- return total;
-
- /*
- * Casting 'hdr' would violate C99 strict aliasing rules, so store the
- * computed header values through direct pointers. Bah.
- */
- *msglen = total;
- *addrs = mask;
-
- return rmib_vcopyout(oldp, off, iov, iovcnt);
-}
-
-/*
- * Given an INET ip-layer datalink type, return a matching BSD interface type.
- */
-static unsigned char
-ipdl_to_ift(int ip_dl_type)
-{
-
- switch (ip_dl_type) {
- case IPDL_ETH:
- return IFT_ETHER;
- case IPDL_PSIP:
- return IFT_LOOP;
- default:
- return IFT_OTHER;
- }
-}
-
-/*
- * Compute the length for, and possibly generate, a sockaddr_dl structure for
- * the given interface. The complication here is that the structure contains
- * various field packed together dynamically, making it variable sized.
- */
-static size_t
-make_sdl(const ip_port_t * ip_port, int ndx, char * buf, size_t max)
-{
- const eth_port_t *eth_port;
- struct sockaddr_dl sdl;
- static char namebuf[8];
- const void *addrptr;
- size_t hdrlen, namelen, addrlen, padlen, len;
-
- /* Normally the interface name would be pregenerated somewhere. */
- snprintf(namebuf, sizeof(namebuf), "ip%u", ip_port->ip_port);
- namelen = strlen(namebuf);
-
- addrlen = 0;
- if (ip_port->ip_dl_type == IPDL_ETH) {
- eth_port = ð_port_table[ip_port->ip_dl.dl_eth.de_port];
- if (eth_port->etp_flags & EPF_GOT_ADDR) {
- addrptr = ð_port->etp_ethaddr;
- addrlen = sizeof(eth_port->etp_ethaddr);
- }
- }
-
- /*
- * Compute the unpadded and padded length of the structure. We pad the
- * structure ourselves here, even though the caller will otherwise pad
- * it later, because it is easy to do so and saves on a vector element.
- */
- hdrlen = offsetof(struct sockaddr_dl, sdl_data);
- len = hdrlen + namelen + addrlen;
- padlen = RT_ROUNDUP(len) - len;
- assert(len + padlen <= max);
-
- /* If we are asked not to generate the actual data, stop here. */
- if (buf == NULL)
- return len + padlen;
-
- /*
- * Fill the sockaddr_dl structure header. The C99 strict aliasing
- * rules prevent us from filling 'buf' through a pointer structure
- * directly.
- */
- memset(&sdl, 0, hdrlen);
- sdl.sdl_len = len;
- sdl.sdl_family = AF_LINK;
- sdl.sdl_index = ndx;
- sdl.sdl_type = ipdl_to_ift(ip_port->ip_dl_type);
- sdl.sdl_nlen = namelen;
- sdl.sdl_alen = addrlen;
- sdl.sdl_slen = 0;
-
- /*
- * Generate the full sockaddr_dl structure in the given buffer. These
- * memory sizes are typically small, so the extra memory copies are not
- * too expensive. The advantage of generating a single sockaddr_dl
- * structure buffer is that we can use copyout_rta() on it.
- */
- memcpy(buf, &sdl, hdrlen);
- if (namelen > 0)
- memcpy(&buf[hdrlen], namebuf, namelen);
- if (addrlen > 0)
- memcpy(&buf[hdrlen + namelen], addrptr, addrlen);
- if (padlen > 0)
- memset(&buf[len], 0, padlen);
-
- return len + padlen;
-}
-
-/*
- * Compute the length for, and possibly generate, an interface information
- * record for the given interface.
- */
-static ssize_t
-gen_ifm(const ip_port_t * ip_port, int ndx, int is_up, struct rmib_oldp * oldp,
- ssize_t off)
-{
- struct if_msghdr ifm;
- char buf[SDL_BUFSIZE];
- void *rta_map[RTAX_MAX];
- size_t rta_len[RTAX_MAX], size;
-
- if (oldp != NULL) {
- memset(&ifm, 0, sizeof(ifm));
- ifm.ifm_version = RTM_VERSION;
- ifm.ifm_type = RTM_IFINFO;
- ifm.ifm_flags = (is_up) ? (IFF_UP | IFF_RUNNING) : 0;
- ifm.ifm_index = ndx;
- ifm.ifm_data.ifi_type = ipdl_to_ift(ip_port->ip_dl_type);
- if (ifm.ifm_data.ifi_type == IFT_LOOP)
- ifm.ifm_flags |= IFF_LOOPBACK;
- /* TODO: other ifm_flags, other ifm_data fields, etc. */
- }
-
- /*
- * Note that we add padding even in this case, to ensure that the
- * following structures are properly aligned as well.
- */
- size = make_sdl(ip_port, ndx, (oldp != NULL) ? buf : NULL,
- sizeof(buf));
-
- memset(rta_map, 0, sizeof(rta_map));
- rta_map[RTAX_IFP] = buf;
- rta_len[RTAX_IFP] = size;
-
- return copyout_rta(&ifm, sizeof(ifm), &ifm.ifm_msglen, &ifm.ifm_addrs,
- rta_map, rta_len, oldp, off);
-}
-
-/*
- * Compute the length for, and possibly generate, an AF_LINK-family interface
- * address record.
- */
-static ssize_t
-gen_ifam_dl(const ip_port_t * ip_port, int ndx, int is_up,
- struct rmib_oldp * oldp, ssize_t off)
-{
- struct ifa_msghdr ifam;
- char buf[SDL_BUFSIZE];
- void *rta_map[RTAX_MAX];
- size_t rta_len[RTAX_MAX], size;
-
- if (oldp != NULL) {
- memset(&ifam, 0, sizeof(ifam));
- ifam.ifam_version = RTM_VERSION;
- ifam.ifam_type = RTM_NEWADDR;
- ifam.ifam_index = ndx;
- ifam.ifam_metric = 0; /* unknown and irrelevant */
- }
-
- size = make_sdl(ip_port, ndx, (oldp != NULL) ? buf : NULL,
- sizeof(buf));
-
- /*
- * We do not generate a netmask. NetBSD seems to generate a netmask
- * with all-one bits for the number of bytes equal to the name length,
- * for reasons unknown to me. If we did the same, we would end up with
- * a conflict on the static 'namebuf' buffer.
- */
- memset(rta_map, 0, sizeof(rta_map));
- rta_map[RTAX_IFA] = buf;
- rta_len[RTAX_IFA] = size;
-
- return copyout_rta(&ifam, sizeof(ifam), &ifam.ifam_msglen,
- &ifam.ifam_addrs, rta_map, rta_len, oldp, off);
-}
-
-/*
- * Compute the length for, and possibly generate, an AF_INET-family interface
- * address record.
- */
-static ssize_t
-gen_ifam_inet(const ip_port_t * ip_port, int ndx, int is_up,
- struct rmib_oldp * oldp, ssize_t off)
-{
- struct ifa_msghdr ifam;
- struct sockaddr_in ipaddr, netmask;
- void *rta_map[RTAX_MAX];
- size_t rta_len[RTAX_MAX];
-
- if (oldp != NULL) {
- memset(&ifam, 0, sizeof(ifam));
- ifam.ifam_msglen = sizeof(ifam);
- ifam.ifam_version = RTM_VERSION;
- ifam.ifam_type = RTM_NEWADDR;
- ifam.ifam_addrs = 0;
- ifam.ifam_index = ndx;
- ifam.ifam_metric = 0; /* unknown and irrelevant */
- }
-
- memset(rta_map, 0, sizeof(rta_map));
-
- if (ip_port->ip_flags & IPF_IPADDRSET) {
- if (oldp != NULL) {
- memset(&ipaddr, 0, sizeof(ipaddr));
- ipaddr.sin_family = AF_INET;
- ipaddr.sin_len = sizeof(ipaddr);
- ipaddr.sin_addr.s_addr = ip_port->ip_ipaddr;
- }
-
- rta_map[RTAX_IFA] = &ipaddr;
- rta_len[RTAX_IFA] = sizeof(ipaddr);
- }
-
- if (ip_port->ip_flags & IPF_NETMASKSET) {
- /*
- * TODO: BSD goes through the trouble of compressing the
- * netmask for some reason. We need to figure out if
- * compression is actually required by any part of userland.
- */
- if (oldp != NULL) {
- memset(&netmask, 0, sizeof(netmask));
- netmask.sin_family = AF_INET;
- netmask.sin_len = sizeof(netmask);
- netmask.sin_addr.s_addr = ip_port->ip_subnetmask;
- }
-
- rta_map[RTAX_NETMASK] = &netmask;
- rta_len[RTAX_NETMASK] = sizeof(netmask);
- }
-
- return copyout_rta(&ifam, sizeof(ifam), &ifam.ifam_msglen,
- &ifam.ifam_addrs, rta_map, rta_len, oldp, off);
-}
-
-/*
- * Compute the size needed for, and optionally copy out, the interface and
- * address information for the given interface.
- */
-static ssize_t
-do_one_if(const ip_port_t * ip_port, int ndx, struct rmib_oldp * oldp,
- ssize_t off, int filter)
-{
- ssize_t r, len;
- int is_up;
-
- /*
- * If the interface is not configured, we mark it as down and do not
- * provide IP address information.
- */
- is_up = (ip_port->ip_flags & IPF_IPADDRSET);
-
- len = 0;
-
- /* There is always a full interface information record. */
- if ((r = gen_ifm(ip_port, ndx, is_up, oldp, off)) < 0)
- return r;
- len += r;
-
- /* If not filtered, there is a datalink address record. */
- if (filter == 0 || filter == AF_LINK) {
- if ((r = gen_ifam_dl(ip_port, ndx, is_up, oldp,
- off + len)) < 0)
- return r;
- len += r;
- }
-
- /* If configured and not filtered, there is an IPv4 address record. */
- if (is_up && (filter == 0 || filter == AF_INET)) {
- if ((r = gen_ifam_inet(ip_port, ndx, is_up, oldp,
- off + len)) < 0)
- return r;
- len += r;
- }
-
- /*
- * Whether or not anything was copied out, upon success we return the
- * full length of the data.
- */
- return len;
-}
-
-/*
- * Remote MIB implementation of CTL_NET PF_ROUTE 0. This function handles all
- * queries on the "net.route.rtable" sysctl(2) node.
- */
-static ssize_t
-net_route_rtable(struct rmib_call * call, struct rmib_node * node __unused,
- struct rmib_oldp * oldp, struct rmib_newp * newp __unused)
-{
- const ip_port_t *ip_port;
- ssize_t r, off;
- int i, filter, ndx;
-
- if (call->call_namelen != 3)
- return EINVAL;
-
- /* We only support listing interfaces for now. */
- if (call->call_name[1] != NET_RT_IFLIST)
- return EOPNOTSUPP;
-
- filter = call->call_name[0];
- ndx = call->call_name[2];
-
- off = 0;
-
- for (i = 0, ip_port = ip_port_table; i < ip_conf_nr; i++, ip_port++) {
- if (!(ip_port->ip_flags & IPF_CONFIGURED))
- continue;
-
- /*
- * If information about a specific interface index is requested
- * then skip all other entries. Interface indices must be
- * nonzero, so we shift the numbers by one. We can avoid going
- * through the loop altogether here, but getifaddrs(3) does not
- * query specific interfaces anyway.
- */
- if (ndx != 0 && ndx != ip_port->ip_port + 1)
- continue;
-
- /* Avoid generating results that are never copied out. */
- if (oldp != NULL && !rmib_inrange(oldp, off))
- oldp = NULL;
-
- if ((r = do_one_if(ip_port, ip_port->ip_port + 1, oldp, off,
- filter)) < 0)
- return r;
-
- off += r;
- }
-
- return off;
-}
-
-/* The CTL_NET PF_ROUTE subtree. */
-static struct rmib_node net_route_table[] = {
- [0] = RMIB_FUNC(RMIB_RO | CTLTYPE_NODE, 0, net_route_rtable,
- "rtable", "Routing table information")
-};
-
-/* The CTL_NET PF_ROUTE node. */
-static struct rmib_node net_route_node =
- RMIB_NODE(RMIB_RO, net_route_table, "route", "PF_ROUTE information");
-
-/*
- * Register the net.route RMIB subtree with the MIB service. Since inet does
- * not support clean shutdowns, there is no matching cleanup function.
- */
-void
-rtinfo_init(void)
-{
- const int mib[] = { CTL_NET, PF_ROUTE };
- int r;
-
- if ((r = rmib_register(mib, __arraycount(mib), &net_route_node)) != OK)
- panic("unable to register remote MIB tree: %d", r);
-}
+++ /dev/null
-/* this file contains the interface of the network software with the file
- * system.
- *
- * Copyright 1995 Philip Homburg
- */
-
-#include "inet.h"
-
-#include "mq.h"
-#include "qp.h"
-#include "proto.h"
-#include "generic/type.h"
-
-#include "generic/assert.h"
-#include "generic/buf.h"
-#include "generic/event.h"
-#include "generic/sr.h"
-#include "sr_int.h"
-
-THIS_FILE
-
-sr_fd_t sr_fd_table[FD_NR];
-
-static struct vscp_vec s_cp_req[SCPVEC_NR];
-
-static int sr_open(devminor_t minor, int access, endpoint_t user_endpt);
-static int sr_close(devminor_t minor);
-static ssize_t sr_read(devminor_t minor, u64_t position, endpoint_t endpt,
- cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
-static ssize_t sr_write(devminor_t minor, u64_t position, endpoint_t endpt,
- cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
-static int sr_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
- cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
-static int sr_rwio(sr_req_t *req);
-static int sr_restart_read(sr_fd_t *fdp);
-static int sr_restart_write(sr_fd_t *fdp);
-static int sr_restart_ioctl(sr_fd_t *fdp);
-static int sr_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
-static int sr_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
-static sr_fd_t *sr_getchannel(int minor);
-static acc_t *sr_get_userdata(int fd, size_t offset, size_t count, int
- for_ioctl);
-static int sr_put_userdata(int fd, size_t offset, acc_t *data, int
- for_ioctl);
-static void sr_select_res(int fd, unsigned ops);
-static int walk_queue(sr_fd_t *sr_fd, mq_t **q_head_ptr, mq_t **q_tail_ptr,
- int type, endpoint_t endpt, cdev_id_t id, int first_flag);
-static void sr_event(event_t *evp, ev_arg_t arg);
-static int cp_u2b(endpoint_t proc, cp_grant_id_t gid, vir_bytes offset,
- acc_t **var_acc_ptr, int size);
-static int cp_b2u(acc_t *acc_ptr, endpoint_t proc, cp_grant_id_t gid,
- vir_bytes offset);
-
-static struct chardriver inet_tab = {
- .cdr_open = sr_open,
- .cdr_close = sr_close,
- .cdr_read = sr_read,
- .cdr_write = sr_write,
- .cdr_ioctl = sr_ioctl,
- .cdr_cancel = sr_cancel,
- .cdr_select = sr_select
-};
-
-void sr_init()
-{
- int i;
-
- for (i=0; i<FD_NR; i++)
- {
- sr_fd_table[i].srf_flags= SFF_FREE;
- ev_init(&sr_fd_table[i].srf_ioctl_ev);
- ev_init(&sr_fd_table[i].srf_read_ev);
- ev_init(&sr_fd_table[i].srf_write_ev);
- }
-}
-
-void sr_rec(message *m, int ipc_status)
-{
- chardriver_process(&inet_tab, m, ipc_status);
-}
-
-void sr_add_minor(minor, port, openf, closef, readf, writef,
- ioctlf, cancelf, selectf)
-int minor;
-int port;
-sr_open_t openf;
-sr_close_t closef;
-sr_read_t readf;
-sr_write_t writef;
-sr_ioctl_t ioctlf;
-sr_cancel_t cancelf;
-sr_select_t selectf;
-{
- sr_fd_t *sr_fd;
-
- assert (minor>=0 && minor<FD_NR);
-
- sr_fd= &sr_fd_table[minor];
-
- assert(!(sr_fd->srf_flags & SFF_INUSE));
-
- sr_fd->srf_flags= SFF_INUSE | SFF_MINOR;
- sr_fd->srf_port= port;
- sr_fd->srf_open= openf;
- sr_fd->srf_close= closef;
- sr_fd->srf_write= writef;
- sr_fd->srf_read= readf;
- sr_fd->srf_ioctl= ioctlf;
- sr_fd->srf_cancel= cancelf;
- sr_fd->srf_select= selectf;
-}
-
-static int sr_open(devminor_t minor, int UNUSED(access),
- endpoint_t UNUSED(user_endpt))
-{
- sr_fd_t *sr_fd;
- int i, fd;
-
- if (minor<0 || minor>FD_NR)
- {
- DBLOCK(1, printf("replying EINVAL\n"));
- return EINVAL;
- }
- if (!(sr_fd_table[minor].srf_flags & SFF_MINOR))
- {
- DBLOCK(1, printf("replying ENXIO\n"));
- return ENXIO;
- }
- for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++);
-
- if (i>=FD_NR)
- {
- DBLOCK(1, printf("replying ENFILE\n"));
- return ENFILE;
- }
-
- sr_fd= &sr_fd_table[i];
- *sr_fd= sr_fd_table[minor];
- sr_fd->srf_flags= SFF_INUSE;
- fd= (*sr_fd->srf_open)(sr_fd->srf_port, i, sr_get_userdata,
- sr_put_userdata, 0 /* no put_pkt */, sr_select_res);
- if (fd<0)
- {
- sr_fd->srf_flags= SFF_FREE;
- DBLOCK(1, printf("replying %d\n", fd));
- return fd;
- }
- sr_fd->srf_fd= fd;
- return CDEV_CLONED | i;
-}
-
-static int sr_close(devminor_t minor)
-{
- sr_fd_t *sr_fd;
-
- sr_fd= sr_getchannel(minor);
- assert (sr_fd);
-
- if (sr_fd->srf_flags & SFF_BUSY)
- ip_panic(("close on busy channel"));
-
- assert (!(sr_fd->srf_flags & SFF_MINOR));
- (*sr_fd->srf_close)(sr_fd->srf_fd);
- sr_fd->srf_flags= SFF_FREE;
-
- return OK;
-}
-
-static int sr_rwio(sr_req_t *req)
-{
- sr_fd_t *sr_fd;
- mq_t *m, **q_head_ptr = NULL, **q_tail_ptr = NULL;
- int ip_flag = 0, susp_flag = 0, first_flag = 0;
- int r = OK;
- ioreq_t request;
- size_t size;
-
- if (!(m = mq_get()))
- ip_panic(("out of messages"));
- m->mq_req = *req;
-
- sr_fd= sr_getchannel(m->mq_req.srr_minor);
- assert (sr_fd);
-
- switch(m->mq_req.srr_type)
- {
- case SRR_READ:
- q_head_ptr= &sr_fd->srf_read_q;
- q_tail_ptr= &sr_fd->srf_read_q_tail;
- ip_flag= SFF_READ_IP;
- susp_flag= SFF_READ_SUSP;
- first_flag= SFF_READ_FIRST;
- break;
- case SRR_WRITE:
- q_head_ptr= &sr_fd->srf_write_q;
- q_tail_ptr= &sr_fd->srf_write_q_tail;
- ip_flag= SFF_WRITE_IP;
- susp_flag= SFF_WRITE_SUSP;
- first_flag= SFF_WRITE_FIRST;
- break;
- case SRR_IOCTL:
- q_head_ptr= &sr_fd->srf_ioctl_q;
- q_tail_ptr= &sr_fd->srf_ioctl_q_tail;
- ip_flag= SFF_IOCTL_IP;
- susp_flag= SFF_IOCTL_SUSP;
- first_flag= SFF_IOCTL_FIRST;
- break;
- default:
- ip_panic(("illegal request type"));
- }
-
- if (sr_fd->srf_flags & ip_flag)
- {
- assert(sr_fd->srf_flags & susp_flag);
- assert(*q_head_ptr);
-
- if (m->mq_req.srr_flags & CDEV_NONBLOCK) {
- mq_free(m);
- return EAGAIN;
- }
-
- (*q_tail_ptr)->mq_next= m;
- *q_tail_ptr= m;
- return EDONTREPLY;
- }
- assert(!*q_head_ptr);
-
- *q_tail_ptr= *q_head_ptr= m;
- sr_fd->srf_flags |= ip_flag;
- assert(!(sr_fd->srf_flags & first_flag));
- sr_fd->srf_flags |= first_flag;
-
- switch(m->mq_req.srr_type)
- {
- case SRR_READ:
- r= (*sr_fd->srf_read)(sr_fd->srf_fd, m->mq_req.srr_size);
- break;
- case SRR_WRITE:
- r= (*sr_fd->srf_write)(sr_fd->srf_fd, m->mq_req.srr_size);
- break;
- case SRR_IOCTL:
- request= m->mq_req.srr_req;
- size= _MINIX_IOCTL_SIZE(request);
- if (size>MAX_IOCTL_S)
- {
- DBLOCK(1, printf("replying EINVAL\n"));
- r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL,
- NULL, 1);
- assert(r == OK);
- assert(sr_fd->srf_flags & first_flag);
- sr_fd->srf_flags &= ~first_flag;
- return EDONTREPLY;
- }
- r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
- break;
- default:
- ip_panic(("illegal case entry"));
- }
-
- assert(sr_fd->srf_flags & first_flag);
- sr_fd->srf_flags &= ~first_flag;
-
- assert(r == OK || r == SUSPEND ||
- (printf("r= %d\n", r), 0));
- if (r == SUSPEND) {
- sr_fd->srf_flags |= susp_flag;
- if (m->mq_req.srr_flags & CDEV_NONBLOCK) {
- r= sr_cancel(m->mq_req.srr_minor, m->mq_req.srr_endpt,
- m->mq_req.srr_id);
- assert(r == EDONTREPLY); /* head of the queue */
- }
- } else
- mq_free(m);
- return EDONTREPLY; /* request already completed */
-}
-
-static ssize_t sr_read(devminor_t minor, u64_t UNUSED(position),
- endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
- cdev_id_t id)
-{
- sr_req_t req;
-
- req.srr_type = SRR_READ;
- req.srr_minor = minor;
- req.srr_endpt = endpt;
- req.srr_grant = grant;
- req.srr_size = size;
- req.srr_flags = flags;
- req.srr_id = id;
-
- return sr_rwio(&req);
-}
-
-static ssize_t sr_write(devminor_t minor, u64_t UNUSED(position),
- endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
- cdev_id_t id)
-{
- sr_req_t req;
-
- req.srr_type = SRR_WRITE;
- req.srr_minor = minor;
- req.srr_endpt = endpt;
- req.srr_grant = grant;
- req.srr_size = size;
- req.srr_flags = flags;
- req.srr_id = id;
-
- return sr_rwio(&req);
-}
-
-static int sr_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
- cp_grant_id_t grant, int flags, endpoint_t UNUSED(user_endpt),
- cdev_id_t id)
-{
- sr_req_t req;
-
- req.srr_type = SRR_IOCTL;
- req.srr_minor = minor;
- req.srr_req = request;
- req.srr_endpt = endpt;
- req.srr_grant = grant;
- req.srr_flags = flags;
- req.srr_id = id;
-
- return sr_rwio(&req);
-}
-
-static int sr_restart_read(sr_fd)
-sr_fd_t *sr_fd;
-{
- mq_t *mp;
- int r;
-
- mp= sr_fd->srf_read_q;
- assert(mp);
-
- if (sr_fd->srf_flags & SFF_READ_IP)
- {
- assert(sr_fd->srf_flags & SFF_READ_SUSP);
- return SUSPEND;
- }
- sr_fd->srf_flags |= SFF_READ_IP;
-
- r= (*sr_fd->srf_read)(sr_fd->srf_fd, mp->mq_req.srr_size);
-
- assert(r == OK || r == SUSPEND ||
- (printf("r= %d\n", r), 0));
- if (r == SUSPEND)
- sr_fd->srf_flags |= SFF_READ_SUSP;
- return r;
-}
-
-static int sr_restart_write(sr_fd)
-sr_fd_t *sr_fd;
-{
- mq_t *mp;
- int r;
-
- mp= sr_fd->srf_write_q;
- assert(mp);
-
- if (sr_fd->srf_flags & SFF_WRITE_IP)
- {
- assert(sr_fd->srf_flags & SFF_WRITE_SUSP);
- return SUSPEND;
- }
- sr_fd->srf_flags |= SFF_WRITE_IP;
-
- r= (*sr_fd->srf_write)(sr_fd->srf_fd, mp->mq_req.srr_size);
-
- assert(r == OK || r == SUSPEND ||
- (printf("r= %d\n", r), 0));
- if (r == SUSPEND)
- sr_fd->srf_flags |= SFF_WRITE_SUSP;
- return r;
-}
-
-static int sr_restart_ioctl(sr_fd)
-sr_fd_t *sr_fd;
-{
- mq_t *mp;
- int r;
-
- mp= sr_fd->srf_ioctl_q;
- assert(mp);
-
- if (sr_fd->srf_flags & SFF_IOCTL_IP)
- {
- assert(sr_fd->srf_flags & SFF_IOCTL_SUSP);
- return SUSPEND;
- }
- sr_fd->srf_flags |= SFF_IOCTL_IP;
-
- r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, mp->mq_req.srr_req);
-
- assert(r == OK || r == SUSPEND ||
- (printf("r= %d\n", r), 0));
- if (r == SUSPEND)
- sr_fd->srf_flags |= SFF_IOCTL_SUSP;
- return r;
-}
-
-static int sr_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
-{
- sr_fd_t *sr_fd;
- int result;
-
- sr_fd= sr_getchannel(minor);
- assert (sr_fd);
-
- result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q,
- &sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL,
- endpt, id, SFF_IOCTL_FIRST);
- if (result != EAGAIN)
- return (result == OK) ? EDONTREPLY : EINTR;
-
- result= walk_queue(sr_fd, &sr_fd->srf_read_q,
- &sr_fd->srf_read_q_tail, SR_CANCEL_READ,
- endpt, id, SFF_READ_FIRST);
- if (result != EAGAIN)
- return (result == OK) ? EDONTREPLY : EINTR;
-
- result= walk_queue(sr_fd, &sr_fd->srf_write_q,
- &sr_fd->srf_write_q_tail, SR_CANCEL_WRITE,
- endpt, id, SFF_WRITE_FIRST);
- if (result != EAGAIN)
- return (result == OK) ? EDONTREPLY : EINTR;
-
- /* We already replied to the request, so don't reply to the CANCEL. */
- return EDONTREPLY;
-}
-
-static int sr_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
-{
- sr_fd_t *sr_fd;
- int r, m_ops;
- unsigned int i_ops;
-
- sr_fd= sr_getchannel(minor);
- assert (sr_fd);
-
- sr_fd->srf_select_proc= endpt;
-
- i_ops= 0;
- if (ops & CDEV_OP_RD) i_ops |= SR_SELECT_READ;
- if (ops & CDEV_OP_WR) i_ops |= SR_SELECT_WRITE;
- if (ops & CDEV_OP_ERR) i_ops |= SR_SELECT_EXCEPTION;
- if (!(ops & CDEV_NOTIFY)) i_ops |= SR_SELECT_POLL;
-
- r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
- if (r < 0) {
- m_ops= r;
- } else {
- m_ops= 0;
- if (r & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
- if (r & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
- if (r & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
- }
-
- return m_ops;
-}
-
-static int walk_queue(sr_fd, q_head_ptr, q_tail_ptr, type, endpt, id,
- first_flag)
-sr_fd_t *sr_fd;
-mq_t **q_head_ptr;
-mq_t **q_tail_ptr;
-int type;
-endpoint_t endpt;
-cdev_id_t id;
-int first_flag;
-{
- mq_t *q_ptr_prv, *q_ptr;
- int result;
-
- for(q_ptr_prv= NULL, q_ptr= *q_head_ptr; q_ptr;
- q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
- {
- if (q_ptr->mq_req.srr_endpt != endpt)
- continue;
- if (q_ptr->mq_req.srr_id != id)
- continue;
- if (!q_ptr_prv)
- {
- assert(!(sr_fd->srf_flags & first_flag));
- sr_fd->srf_flags |= first_flag;
-
- /* This will also send a reply. */
- result= (*sr_fd->srf_cancel)(sr_fd->srf_fd, type);
- assert(result == OK);
-
- *q_head_ptr= q_ptr->mq_next;
- mq_free(q_ptr);
-
- assert(sr_fd->srf_flags & first_flag);
- sr_fd->srf_flags &= ~first_flag;
-
- return OK;
- }
- q_ptr_prv->mq_next= q_ptr->mq_next;
- mq_free(q_ptr);
- if (!q_ptr_prv->mq_next)
- *q_tail_ptr= q_ptr_prv;
- return EINTR;
- }
- return EAGAIN;
-}
-
-static sr_fd_t *sr_getchannel(minor)
-int minor;
-{
- sr_fd_t *loc_fd;
-
- compare(minor, >=, 0);
- compare(minor, <, FD_NR);
-
- loc_fd= &sr_fd_table[minor];
-
- assert (!(loc_fd->srf_flags & SFF_MINOR) &&
- (loc_fd->srf_flags & SFF_INUSE));
-
- return loc_fd;
-}
-
-static acc_t *sr_get_userdata (fd, offset, count, for_ioctl)
-int fd;
-size_t offset;
-size_t count;
-int for_ioctl;
-{
- sr_fd_t *loc_fd;
- mq_t **head_ptr, *m, *mq;
- int ip_flag, susp_flag, first_flag;
- int result, suspended, is_revive;
- acc_t *acc;
- event_t *evp;
- ev_arg_t arg;
-
- loc_fd= &sr_fd_table[fd];
-
- if (for_ioctl)
- {
- head_ptr= &loc_fd->srf_ioctl_q;
- evp= &loc_fd->srf_ioctl_ev;
- ip_flag= SFF_IOCTL_IP;
- susp_flag= SFF_IOCTL_SUSP;
- first_flag= SFF_IOCTL_FIRST;
- }
- else
- {
- head_ptr= &loc_fd->srf_write_q;
- evp= &loc_fd->srf_write_ev;
- ip_flag= SFF_WRITE_IP;
- susp_flag= SFF_WRITE_SUSP;
- first_flag= SFF_WRITE_FIRST;
- }
-
- assert (loc_fd->srf_flags & ip_flag);
-
- if (!count)
- {
- m= *head_ptr;
- mq= m->mq_next;
- *head_ptr= mq;
- result= (int)offset;
- is_revive= !(loc_fd->srf_flags & first_flag);
- chardriver_reply_task(m->mq_req.srr_endpt, m->mq_req.srr_id,
- result);
- if (is_revive)
- mq_free(m);
- suspended= (loc_fd->srf_flags & susp_flag);
- loc_fd->srf_flags &= ~(ip_flag|susp_flag);
- if (suspended)
- {
- if (mq)
- {
- arg.ev_ptr= loc_fd;
- ev_enqueue(evp, sr_event, arg);
- }
- }
- return NULL;
- }
-
- result= cp_u2b ((*head_ptr)->mq_req.srr_endpt,
- (*head_ptr)->mq_req.srr_grant, offset, &acc, count);
-
- return result<0 ? NULL : acc;
-}
-
-static int sr_put_userdata (fd, offset, data, for_ioctl)
-int fd;
-size_t offset;
-acc_t *data;
-int for_ioctl;
-{
- sr_fd_t *loc_fd;
- mq_t **head_ptr, *m, *mq;
- int ip_flag, susp_flag, first_flag;
- int result, suspended, is_revive;
- event_t *evp;
- ev_arg_t arg;
-
- loc_fd= &sr_fd_table[fd];
-
- if (for_ioctl)
- {
- head_ptr= &loc_fd->srf_ioctl_q;
- evp= &loc_fd->srf_ioctl_ev;
- ip_flag= SFF_IOCTL_IP;
- susp_flag= SFF_IOCTL_SUSP;
- first_flag= SFF_IOCTL_FIRST;
- }
- else
- {
- head_ptr= &loc_fd->srf_read_q;
- evp= &loc_fd->srf_read_ev;
- ip_flag= SFF_READ_IP;
- susp_flag= SFF_READ_SUSP;
- first_flag= SFF_READ_FIRST;
- }
-
- assert (loc_fd->srf_flags & ip_flag);
-
- if (!data)
- {
- m= *head_ptr;
- mq= m->mq_next;
- *head_ptr= mq;
- result= (int)offset;
- is_revive= !(loc_fd->srf_flags & first_flag);
- chardriver_reply_task(m->mq_req.srr_endpt, m->mq_req.srr_id,
- result);
- if (is_revive)
- mq_free(m);
- suspended= (loc_fd->srf_flags & susp_flag);
- loc_fd->srf_flags &= ~(ip_flag|susp_flag);
- if (suspended)
- {
- if (mq)
- {
- arg.ev_ptr= loc_fd;
- ev_enqueue(evp, sr_event, arg);
- }
- }
- return OK;
- }
-
- return cp_b2u (data, (*head_ptr)->mq_req.srr_endpt,
- (*head_ptr)->mq_req.srr_grant, offset);
-}
-
-static void sr_select_res(int fd, unsigned ops)
-{
- sr_fd_t *sr_fd;
- unsigned int m_ops;
-
- sr_fd= &sr_fd_table[fd];
-
- m_ops= 0;
- if (ops & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
- if (ops & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
- if (ops & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
-
- chardriver_reply_select(sr_fd->srf_select_proc, fd, m_ops);
-}
-
-static void sr_event(evp, arg)
-event_t *evp;
-ev_arg_t arg;
-{
- sr_fd_t *sr_fd;
- int r;
-
- sr_fd= arg.ev_ptr;
- if (evp == &sr_fd->srf_write_ev)
- {
- while(sr_fd->srf_write_q)
- {
- r= sr_restart_write(sr_fd);
- if (r == SUSPEND)
- return;
- }
- return;
- }
- if (evp == &sr_fd->srf_read_ev)
- {
- while(sr_fd->srf_read_q)
- {
- r= sr_restart_read(sr_fd);
- if (r == SUSPEND)
- return;
- }
- return;
- }
- if (evp == &sr_fd->srf_ioctl_ev)
- {
- while(sr_fd->srf_ioctl_q)
- {
- r= sr_restart_ioctl(sr_fd);
- if (r == SUSPEND)
- return;
- }
- return;
- }
- ip_panic(("sr_event: unknown event\n"));
-}
-
-static int cp_u2b(proc, gid, offset, var_acc_ptr, size)
-endpoint_t proc;
-cp_grant_id_t gid;
-vir_bytes offset;
-acc_t **var_acc_ptr;
-int size;
-{
- acc_t *acc;
- int i, r;
-
- acc= bf_memreq(size);
-
- *var_acc_ptr= acc;
- i=0;
-
- while (acc)
- {
- size= (vir_bytes)acc->acc_length;
-
- s_cp_req[i].v_from= proc;
- s_cp_req[i].v_to= SELF;
- s_cp_req[i].v_gid= gid;
- s_cp_req[i].v_offset= offset;
- s_cp_req[i].v_addr= (vir_bytes) ptr2acc_data(acc);
- s_cp_req[i].v_bytes= size;
-
- offset += size;
- acc= acc->acc_next;
- i++;
-
- if (acc == NULL && i == 1)
- {
- r= sys_safecopyfrom(s_cp_req[0].v_from,
- s_cp_req[0].v_gid, s_cp_req[0].v_offset,
- s_cp_req[0].v_addr, s_cp_req[0].v_bytes);
- if (r <0)
- {
- printf("sys_safecopyfrom failed: %d\n", r);
- bf_afree(*var_acc_ptr);
- *var_acc_ptr= 0;
- return r;
- }
- i= 0;
- continue;
- }
- if (i == SCPVEC_NR || acc == NULL)
- {
- r= sys_vsafecopy(s_cp_req, i);
-
- if (r <0)
- {
- printf("cp_u2b: sys_vsafecopy failed: %d\n",
- r);
- bf_afree(*var_acc_ptr);
- *var_acc_ptr= 0;
- return r;
- }
- i= 0;
- }
- }
- return OK;
-}
-
-static int cp_b2u(acc_ptr, proc, gid, offset)
-acc_t *acc_ptr;
-endpoint_t proc;
-cp_grant_id_t gid;
-vir_bytes offset;
-{
- acc_t *acc;
- int i, r, size;
-
- acc= acc_ptr;
- i=0;
-
- while (acc)
- {
- size= (vir_bytes)acc->acc_length;
-
- if (size)
- {
- s_cp_req[i].v_from= SELF;
- s_cp_req[i].v_to= proc;
- s_cp_req[i].v_gid= gid;
- s_cp_req[i].v_offset= offset;
- s_cp_req[i].v_addr= (vir_bytes) ptr2acc_data(acc);
- s_cp_req[i].v_bytes= size;
-
- i++;
- }
-
- offset += size;
- acc= acc->acc_next;
-
- if (acc == NULL && i == 1)
- {
- r= sys_safecopyto(s_cp_req[0].v_to,
- s_cp_req[0].v_gid, s_cp_req[0].v_offset,
- s_cp_req[0].v_addr, s_cp_req[0].v_bytes);
- if (r <0)
- {
- printf("sys_safecopyto failed: %d\n", r);
- bf_afree(acc_ptr);
- return r;
- }
- i= 0;
- continue;
- }
- if (i == SCPVEC_NR || acc == NULL)
- {
- r= sys_vsafecopy(s_cp_req, i);
-
- if (r <0)
- {
- printf("cp_b2u: sys_vsafecopy failed: %d\n",
- r);
- bf_afree(acc_ptr);
- return r;
- }
- i= 0;
- }
- }
- bf_afree(acc_ptr);
- return OK;
-}
-
-/*
- * $PchId: sr.c,v 1.17 2005/06/28 14:26:16 philip Exp $
- */
+++ /dev/null
-/*
-inet/sr_int.h
-
-SR internals
-
-Created: Aug 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
-*/
-
-#define FD_NR (16*IP_PORT_MAX)
-
-typedef struct sr_fd
-{
- int srf_flags;
- int srf_fd;
- int srf_port;
- endpoint_t srf_select_proc;
- sr_open_t srf_open;
- sr_close_t srf_close;
- sr_write_t srf_write;
- sr_read_t srf_read;
- sr_ioctl_t srf_ioctl;
- sr_cancel_t srf_cancel;
- sr_select_t srf_select;
- mq_t *srf_ioctl_q, *srf_ioctl_q_tail;
- mq_t *srf_read_q, *srf_read_q_tail;
- mq_t *srf_write_q, *srf_write_q_tail;
- event_t srf_ioctl_ev;
- event_t srf_read_ev;
- event_t srf_write_ev;
-} sr_fd_t;
-
-# define SFF_FREE 0x00
-# define SFF_MINOR 0x01
-# define SFF_INUSE 0x02
-#define SFF_BUSY 0x1C
-# define SFF_IOCTL_IP 0x04
-# define SFF_READ_IP 0x08
-# define SFF_WRITE_IP 0x10
-#define SFF_SUSPENDED 0x1C0
-# define SFF_IOCTL_SUSP 0x40
-# define SFF_READ_SUSP 0x80
-# define SFF_WRITE_SUSP 0x100
-#define SFF_IOCTL_FIRST 0x200
-#define SFF_READ_FIRST 0x400
-#define SFF_WRITE_FIRST 0x800
-
-EXTERN sr_fd_t sr_fd_table[FD_NR];
-
-/*
- * $PchId: sr_int.h,v 1.2 2005/06/28 14:28:17 philip Exp $
- */
+++ /dev/null
-/*
-version.c
-*/
-
-#include "inet.h"
-
-char version[]= "inet 0.79, last compiled on " __DATE__ " " __TIME__;
-
-/*
- * $PchId: version.c,v 1.54 2005/06/28 14:35:01 philip Exp $
- */
proc_e, m_ptr->m_source);
} else {
/*
- * Some services (e.g., inet) use the same infrastructure for
- * nonblocking and cancelled requests, resulting in one of
- * EINTR or EAGAIN when the other is really the appropriate
- * code. Thus, cdev_cancel converts EAGAIN into EINTR, and we
- * convert EINTR into EAGAIN here.
+ * Some services use the same infrastructure for nonblocking
+ * and cancelled requests, resulting in one of EINTR or EAGAIN
+ * when the other is really the appropriate code. Thus,
+ * cdev_cancel converts EAGAIN into EINTR, and we convert EINTR
+ * into EAGAIN here. TODO: this may be obsolete by now..?
*/
r = m_ptr->m_lchardriver_vfs_reply.status;
revive(proc_e, (r == EINTR) ? EAGAIN : r);
banner=Welcome to the MINIX 3 installation CD
banner================================================================================
banner=
-menu=Regular MINIX 3:multiboot /kernel bootcd=1 cdproberoot=1 rootdevname=ram disable=inet
-menu=Regular MINIX 3 (with AHCI):multiboot /kernel bootcd=1 cdproberoot=1 rootdevname=ram disable=inet ahci=yes
+menu=Regular MINIX 3:multiboot /kernel bootcd=1 cdproberoot=1 rootdevname=ram
+menu=Regular MINIX 3 (with AHCI):multiboot /kernel bootcd=1 cdproberoot=1 rootdevname=ram ahci=yes
menu=Edit menu option:edit
menu=Drop to boot prompt:prompt
clear=1
banner=Welcome to the MINIX 3 installation CD
banner================================================================================
banner=
-menu=Regular MINIX 3:multiboot /boot/minix_default/kernel bootcd=1 cdproberoot=1 disable=inet
-menu=Regular MINIX 3 (with AHCI):multiboot /boot/minix_default/kernel bootcd=1 cdproberoot=1 disable=inet ahci=yes
+menu=Regular MINIX 3:multiboot /boot/minix_default/kernel bootcd=1 cdproberoot=1
+menu=Regular MINIX 3 (with AHCI):multiboot /boot/minix_default/kernel bootcd=1 cdproberoot=1 ahci=yes
menu=Edit menu option:edit
menu=Drop to boot prompt:prompt
clear=1
echo "qemu-system-i386 --enable-kvm -cdrom `pwd`/${IMG}"
echo ""
echo "To boot this image on kvm:"
-echo "cd ${MODDIR} && qemu-system-i386 --enable-kvm -kernel kernel -append \"bootcd=1 cdproberoot=1 disable=inet\" -initrd \"${mods}\" -cdrom `pwd`/${IMG}"
+echo "cd ${MODDIR} && qemu-system-i386 --enable-kvm -kernel kernel -append \"bootcd=1 cdproberoot=1\" -initrd \"${mods}\" -cdrom `pwd`/${IMG}"