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:
David van Moolenbroek
2017-02-14 15:26:43 +00:00
parent 3ea34559da
commit c5da0dffe2
90 changed files with 36 additions and 26877 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 \

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View 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
;;

View File

@@ -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

View File

@@ -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" },

View File

@@ -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 \

View File

@@ -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 */

View File

@@ -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 $ */

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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>

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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.
...

View File

@@ -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),

View File

@@ -1,7 +1,6 @@
.include <bsd.own.mk>
.if ${MKIMAGEONLY} == "no"
SUBDIR+= inet
SUBDIR+= uds
.endif # ${MKIMAGEONLY} == "no"

View File

@@ -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>

File diff suppressed because it is too large Load Diff

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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, &eth_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(&eth_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, &eth_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(&eth_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(&eth_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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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

View File

@@ -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

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $

View File

@@ -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 $
*/

View File

@@ -1,5 +0,0 @@
service inet
{
uid 0;
};

View File

@@ -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 $
*/

View File

@@ -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= &eth_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(&eth_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 $
*/

View File

@@ -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 $
*/

View File

@@ -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(&eth_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(&eth_port->etp_osdep.etp_recvev);
rport= ecp->ec_port;
assert(rport >= 0 && rport < eth_conf_nr);
rep= &eth_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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $ */

View File

@@ -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 = &eth_port_table[ip_port->ip_dl.dl_eth.de_port];
if (eth_port->etp_flags & EPF_GOT_ADDR) {
addrptr = &eth_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);
}

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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 $
*/

View File

@@ -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);

View File

@@ -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

View File

@@ -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}"