Retire inet: the previous MINIX TCP/IP service
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
This commit is contained in:
@@ -100,7 +100,7 @@
|
||||
./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
|
||||
@@ -148,13 +148,13 @@
|
||||
./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
|
||||
@@ -175,7 +175,7 @@
|
||||
./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
|
||||
@@ -231,7 +231,7 @@
|
||||
./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
|
||||
|
||||
@@ -1231,7 +1231,7 @@
|
||||
./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
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
./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
|
||||
|
||||
@@ -3253,17 +3253,17 @@
|
||||
./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
|
||||
@@ -3402,7 +3402,7 @@
|
||||
./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
|
||||
|
||||
@@ -104,8 +104,8 @@ BIN1+= \
|
||||
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 \
|
||||
@@ -320,7 +320,6 @@ install-etc-files: .PHONY .MAKE check_DESTDIR MAKEDEV
|
||||
.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 \
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
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
|
||||
80
etc/rs.inet
80
etc/rs.inet
@@ -1,80 +0,0 @@
|
||||
#!/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
|
||||
44
etc/usr/rc
44
etc/usr/rc
@@ -105,11 +105,7 @@ up()
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -155,8 +151,6 @@ capemgr() {
|
||||
done
|
||||
}
|
||||
|
||||
DAEMONS=/etc/rc.daemons
|
||||
|
||||
case $action in
|
||||
start)
|
||||
# Select console font.
|
||||
@@ -192,8 +186,6 @@ start)
|
||||
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`"
|
||||
|
||||
@@ -214,9 +206,6 @@ start)
|
||||
|
||||
echo .
|
||||
|
||||
# Network initialization.
|
||||
(: </dev/tcp) 2>/dev/null && net=t # Is there a TCP/IP server?
|
||||
|
||||
echo -n "Starting daemons:"
|
||||
daemonize update
|
||||
|
||||
@@ -355,37 +344,6 @@ start)
|
||||
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)
|
||||
|
||||
|
||||
@@ -130,35 +130,6 @@ do
|
||||
;;
|
||||
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
|
||||
;;
|
||||
|
||||
@@ -30,7 +30,6 @@ RAMDISK_DEVICES="
|
||||
ttyc1 ttyc2 ttyc3 tty00 tty01 tty02 tty03
|
||||
"
|
||||
|
||||
#eth => ip tcp udp
|
||||
STD_DEVICES="
|
||||
${RAMDISK_DEVICES}
|
||||
bmp085b1s77 bmp085b2s77 bmp085b3s77
|
||||
@@ -40,7 +39,7 @@ STD_DEVICES="
|
||||
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
|
||||
@@ -128,7 +127,6 @@ Where key is one of the following:
|
||||
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
|
||||
@@ -277,20 +275,6 @@ do
|
||||
|
||||
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
|
||||
|
||||
@@ -125,7 +125,6 @@ service_get_policies(struct policies * pol, index_t slot)
|
||||
{ .label = "ptyfs", .policy_str = "" },
|
||||
{ .label = "vbfs", .policy_str = "" },
|
||||
/* net */
|
||||
{ .label = "inet", .policy_str = "reset" },
|
||||
{ .label = "lwip", .policy_str = "" },
|
||||
/* servers */
|
||||
{ .label = "devman", .policy_str = "restart" },
|
||||
|
||||
@@ -15,7 +15,7 @@ INCS+= acpi.h audio_fw.h bitmap.h \
|
||||
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 \
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#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 */
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* 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 $ */
|
||||
@@ -51,7 +51,7 @@
|
||||
#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
|
||||
|
||||
@@ -27,7 +27,7 @@ up to and including file descriptor
|
||||
, 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
|
||||
|
||||
@@ -49,6 +49,4 @@ Could not allocate a file descriptor.
|
||||
.BR shutdown(2),
|
||||
.BR getsockopt(2),
|
||||
.BR setsockopt(2),
|
||||
.BR ip(4),
|
||||
.BR inet(8),
|
||||
.BR unix(8)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
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
|
||||
@@ -9,8 +9,5 @@ MLINKS += controller.4 esdi.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>
|
||||
|
||||
@@ -179,9 +179,8 @@ The
|
||||
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* .
|
||||
@@ -215,7 +214,6 @@ All MINIX 3 devices
|
||||
.BR console (4),
|
||||
.BR fd (4),
|
||||
.BR controller (4),
|
||||
.BR ip (4),
|
||||
.BR uds (4),
|
||||
.BR tty (4),
|
||||
.BR MAKEDEV (8).
|
||||
@@ -223,8 +221,8 @@ All MINIX 3 devices
|
||||
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
|
||||
|
||||
1466
minix/man/man4/ip.4
1466
minix/man/man4/ip.4
File diff suppressed because it is too large
Load Diff
@@ -45,8 +45,6 @@ System configuration and data files; see also \fB/usr/etc/\fP.
|
||||
\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)
|
||||
@@ -132,8 +130,7 @@ Contains source and majority of system utilities and files
|
||||
\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.
|
||||
...
|
||||
|
||||
|
||||
@@ -179,23 +179,6 @@ on this. Note also the
|
||||
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 ,
|
||||
@@ -238,56 +221,6 @@ Number of active file locks by
|
||||
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),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.if ${MKIMAGEONLY} == "no"
|
||||
SUBDIR+= inet
|
||||
SUBDIR+= uds
|
||||
.endif # ${MKIMAGEONLY} == "no"
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# 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>
|
||||
1253
minix/net/inet/buf.c
1253
minix/net/inet/buf.c
File diff suppressed because it is too large
Load Diff
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
#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 $
|
||||
*/
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,495 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,722 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,678 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,513 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,818 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,594 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,145 +0,0 @@
|
||||
.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 $
|
||||
@@ -1,370 +0,0 @@
|
||||
/* 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 $
|
||||
*/
|
||||
@@ -1,5 +0,0 @@
|
||||
service inet
|
||||
{
|
||||
uid 0;
|
||||
};
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,434 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,786 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,384 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,150 +0,0 @@
|
||||
/* 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 $
|
||||
*/
|
||||
@@ -1,44 +0,0 @@
|
||||
/* 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 $ */
|
||||
@@ -1,435 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -1,836 +0,0 @@
|
||||
/* 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 $
|
||||
*/
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
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 $
|
||||
*/
|
||||
@@ -463,11 +463,11 @@ cdev_generic_reply(message * m_ptr)
|
||||
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);
|
||||
|
||||
@@ -63,8 +63,8 @@ cat >$CDFILES/boot.cfg <<END_BOOT_CFG
|
||||
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
|
||||
|
||||
@@ -39,8 +39,8 @@ cat >${ROOT_DIR}/boot.cfg <<END_BOOT_CFG
|
||||
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
|
||||
@@ -88,4 +88,4 @@ echo "To boot this image on kvm using the bootloader:"
|
||||
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}"
|
||||
|
||||
Reference in New Issue
Block a user