Commit ddd9ed00 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14o

parent 28067f4d
VERSION = 0.99
PATCHLEVEL = 14
ALPHA = n
ALPHA = o
all: Version zImage
......@@ -50,7 +50,7 @@ SVGA_MODE= -DSVGA_MODE=NORMAL_VGA
# standard CFLAGS
#
CFLAGS = -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -pipe
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
ifdef CONFIG_CPP
CFLAGS := $(CFLAGS) -x c++
......
......@@ -8,8 +8,8 @@
include CONFIG
NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o)
CFLAGS := $(CFLAGS) -I../../net/inet -I../../net/socket -I../../net
CPP := $(CPP) -I../../net/inet -I../../net/socket -I../../net
CFLAGS := $(CFLAGS) -I../../net/inet
CPP := $(CPP) -I../../net/inet
# The point of the makefile...
all: net.a
......
......@@ -40,9 +40,9 @@
#include <linux/tty.h>
#include <linux/in.h>
#include "inet.h"
#include "devinet.h"
#include "dev.h"
#ifdef CONFIG_AX25
#include "ax25/ax25.h"
#include "ax25.h"
#endif
#include "eth.h"
#include "ip.h"
......
......@@ -53,19 +53,27 @@
#define MAYBE_CONTINUE(LABEL,DEV) \
{if (buffer) kfree(buffer); \
if (cont_extent){ \
int block, offset; \
int block, offset, offset1; \
struct buffer_head * bh; \
buffer = kmalloc(cont_size,GFP_KERNEL); \
block = cont_extent; \
offset = cont_offset; \
offset1 = 0; \
if(ISOFS_BUFFER_SIZE(DEV) == 1024) { \
block <<= 1; \
if (offset >= 1024) block++; \
offset &= 1023; \
if(offset + cont_size >= 1024) { \
bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \
memcpy(buffer, bh->b_data + offset, 1024 - offset); \
brelse(bh); \
offset1 = 1024 - offset; \
offset = 0; \
} \
}; \
bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
if(bh){ \
memcpy(buffer, bh->b_data, cont_size); \
memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \
brelse(bh); \
chr = (unsigned char *) buffer; \
len = cont_size; \
......@@ -291,10 +299,17 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
};
break;
case SIG('T','F'):
/* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
Try and handle this correctly for either case. */
cnt = 0; /* Rock ridge never appears on a High Sierra disk */
if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_CREATE)
inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_MODIFY)
inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_ACCESS)
inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
if(rr->u.TF.flags & TF_ATTRIBUTES)
inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
break;
case SIG('S','L'):
{int slen;
......
......@@ -59,8 +59,6 @@ struct options {
unsigned short handling;
unsigned short stream;
unsigned tcc;
int option_length;
void *option_data;
};
......
......@@ -30,14 +30,10 @@ struct linger {
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_INET 2
#define AF_AX25 3
#define AF_IPX 4
/* Protocol families, same as address families. */
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
/* Flags we can use with send/ and recv. */
#define MSG_OOB 1
......@@ -45,10 +41,6 @@ struct linger {
/* Setsockoptions(2) level. */
#define SOL_SOCKET 1
#define SOL_IP 2
#define SOL_IPX 3
#define SOL_AX25 4
#define SOL_TCP 5
/* For setsockoptions(2) */
#define SO_DEBUG 1
......@@ -64,19 +56,6 @@ struct linger {
#define SO_NO_CHECK 11
#define SO_PRIORITY 12
#define SO_LINGER 13
/* IP options */
#define IP_TOS 1
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IP_TTL 2
/* IPX options */
#define IPX_TYPE 1
/* AX.25 options */
#define AX25_WINDOW 1
/* TCP options */
#define TCP_MSS 1
#define TCP_NODELAY 2
/* The various priorities. */
#define SOPRI_INTERACTIVE 0
......
......@@ -24,11 +24,11 @@
#define IP_SET_DEV 0x2401
struct ip_config {
char name[MAX_IP_NAME];
unsigned long paddr;
unsigned long router;
unsigned long net;
unsigned int up:1,destroy:1;
char name[MAX_IP_NAME];
unsigned long paddr;
unsigned long router;
unsigned long net;
unsigned int up:1,destroy:1;
};
#endif /* FIXME: */
......
......@@ -7,17 +7,10 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
SUBDIRS := unix socket
# only these two lines should need to be changed to remove inet sockets.
# (and the inet/tcpip.o in net.o)
ifdef CONFIG_INET
SUBDIRS := $(SUBDIRS) inet
endif
ifdef CONFIG_IPX
SUBDIRS := $(SUBDIRS) ipx
endif
ifdef CONFIG_AX25
SUBDIRS := $(SUBDIRS) ax25
endif
SUBDIRS := unix inet
SUBOBJS := $(foreach f,$(SUBDIRS),$f/$f.o)
......
......@@ -30,10 +30,10 @@
# include "inet/inet.h"
#endif
#ifdef CONFIG_IPX
#include "ipx/ipxcall.h"
#include "inet/ipxcall.h"
#endif
#ifdef CONFIG_AX25
#include "ax25/ax25call.h"
#include "inet/ax25call.h"
#endif
struct ddi_proto protocols[] = {
......@@ -53,3 +53,43 @@ struct ddi_proto protocols[] = {
};
/*
* Section B: Device Driver Modules.
* This section defines which network device drivers
* get linked into the Linux kernel. It is currently
* only used by the INET protocol. Any takers for the
* other protocols like XNS or Novell?
*
* WARNING: THIS SECTION IS NOT YET USED BY THE DRIVERS !!!!!
*/
/*#include "drv/we8003/we8003.h" Western Digital WD-80[01]3 */
/*#include "drv/dp8390/dp8390.h" Donald Becker's DP8390 kit */
/*#inclde "drv/slip/slip.h" Laurence Culhane's SLIP kit */
struct ddi_device devices[] = {
#if CONF_WE8003
{ "WD80x3[EBT]",
"", 0, 1, we8003_init, NULL,
19, 0, DDI_FCHRDEV,
{ 0x280, 0, 15, 0, 32768, 0xD0000 } },
#endif
#if CONF_DP8390
{ "DP8390/WD80x3",
"", 0, 1, dpwd8003_init, NULL,
20, 0, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
{ "DP8390/NE-x000",
"", 0, 1, dpne2000_init, NULL,
20, 8, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
{ "DP8390/3C50x",
"", 0, 1, dpec503_init, NULL,
20, 16, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
#endif
{ NULL,
"", 0, 0, NULL, NULL,
0, 0, 0,
{ 0, 0, 0, 0, 0, 0 } }
};
......@@ -4,11 +4,9 @@
* but it eventually might move to an upper directory of
* the system.
*
* Version: @(#)ddi.c 1.28 27/12/93
* Version: @(#)ddi.c 1.0.5 04/22/93
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Unused pieces nobbled.
*/
#include <asm/segment.h>
#include <asm/system.h>
......@@ -20,9 +18,6 @@
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/ddi.h>
#include <linux/interrupt.h>
#include "socket/dev.h"
#undef DDI_DEBUG
......@@ -33,32 +28,64 @@
#endif
extern struct ddi_device devices[]; /* device driver map */
extern struct ddi_proto protocols[]; /* network protocols */
/*
* This function gets called with an ASCII string representing the
* ID of some DDI driver. We loop through the DDI Devices table
* and return the address of the control block that has a matching
* "name" field. It is used by upper-level layers that want to
* dynamically bind some UNIX-domain "/dev/XXXX" file name to a
* DDI device driver. The "iflink(8)" program is an example of
* this behaviour.
*/
struct ddi_device *
ddi_map(const char *id)
{
register struct ddi_device *dev;
PRINTK (("DDI: MAP: looking for \"%s\": ", id));
dev = devices;
while (dev->title != NULL) {
if (strncmp(dev->name, id, DDI_MAXNAME) == 0) {
PRINTK (("OK at 0x%X\n", dev));
return(dev);
}
dev++;
}
PRINTK (("NOT FOUND\n"));
return(NULL);
}
/*
* This is the function that is called by a kernel routine during
* system startup. Its purpose is to walk trough the "devices"
* table (defined above), and to call all moduled defined in it.
*/
void ddi_init(void)
void
ddi_init(void)
{
struct ddi_proto *pro;
struct ddi_proto *pro;
struct ddi_device *dev;
PRINTK (("DDI: Starting up!\n"));
PRINTK (("DDI: Starting up!\n"));
/* First off, kick all configured protocols. */
pro = protocols;
while (pro->name != NULL)
{
(*pro->init)(pro);
pro++;
}
/* First off, kick all configured protocols. */
pro = protocols;
while (pro->name != NULL) {
(*pro->init)(pro);
pro++;
}
dev_init();
/* Initialize the "Buffer Head" pointers. */
bh_base[INET_BH].routine = inet_bh;
/* We're all done... */
}
/* Done. Now kick all configured device drivers. */
dev = devices;
while (dev->title != NULL) {
(*dev->init)(dev);
dev++;
}
/* We're all done... */
}
......@@ -7,9 +7,6 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
CFLAGS := $(CFLAGS) -I../socket -I..
CPP := $(CPP) -I../socket -I..
.c.o:
$(CC) $(CFLAGS) -c -o $*.o $<
.s.o:
......@@ -18,8 +15,10 @@ CPP := $(CPP) -I../socket -I..
$(CC) $(CFLAGS) -S -o $*.s $<
OBJS = sockinet.o utils.o route.o proc.o timer.o protocol.o loopback.o \
eth.o packet.o arp.o devinet.o ip.o raw.o icmp.o tcp.o udp.o
OBJS = sock.o utils.o route.o proc.o timer.o protocol.o loopback.o \
eth.o packet.o arp.o dev.o ip.o raw.o icmp.o tcp.o udp.o \
datagram.o skbuff.o
# ipx.o ax25.o ax25_in.o ax25_out.o ax25_subr.o ax25_timer.o
ifdef CONFIG_INET
......
NET2Debugged 1.28 README
NET2Debugged 1.24 README
------------------------
Major Changes
o PLIP driver sort of works
o UDP and RAW have been partially rewritten for speed
o Internals heavily cleaned up, and memory monitoring of network
memory is now done. (On shift-scroll-lock)
o ARP should now not generate garbage
o Using MSG_PEEK can't cause race conditions and crashes
o Support for bootp clients.
o Supports RFC931 TAP authd
o NFS problems with certain types of network configuration are
fixed.
o Doesn't forward packets for other subnet (can cause packet storms)
o TCP won't ack rst frames causing packet storms (especially with
Lan workplace for DOS).
o Numerous fixes for solidity
o Verify_area used properly.
o MSG_PEEK is faster again
o Minor TCP fixes. Hopefully no more TCP lockups (ha!)
o Donald's promiscuous mode. Go forth and write protocol analysers...
-------------------------------------------------------------------------
NOTE:
Drivers for this stack set must be using alloc_skb() not just
......
This diff is collapsed.
......@@ -5,7 +5,7 @@
*
* Definitions for the ARP protocol module.
*
* Version: @(#)arp.h 1.28 24/12/93
* Version: @(#)arp.h 1.0.6 05/21/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
......@@ -26,31 +26,29 @@
#define ARP_QUEUE_MAGIC 0x0432447A /* magic # for queues */
/*
* This structure defines the ARP mapping cache.
*/
struct arp_table
{
struct arp_table *next;
volatile unsigned long last_used;
unsigned int flags;
unsigned long ip;
unsigned char ha[MAX_ADDR_LEN];
unsigned char hlen;
unsigned char htype;
/* This structure defines the ARP mapping cache. */
struct arp_table {
struct arp_table *next;
volatile unsigned long last_used;
unsigned int flags;
#if 1
unsigned long ip;
#else
unsigned char pa[MAX_ADDR_LEN];
unsigned char plen;
unsigned char ptype;
#endif
unsigned char ha[MAX_ADDR_LEN];
unsigned char hlen;
unsigned char htype;
};
/*
* This is also used in "sock.c" and "tcp.c" - YUCK! - FvK
*/
/* This is also used in "sock.c" and "tcp.c" - YUCK! - FvK */
extern struct sk_buff *arp_q;
extern void arp_destroy(unsigned long paddr);
extern void arp_destroy_maybe(unsigned long paddr);
extern int arp_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
extern int arp_find(unsigned char *haddr, unsigned long paddr,
......
......@@ -13,8 +13,6 @@
* Alan Cox : Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
* Alan Cox : Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
* AX.25 now works right, and SPX is feasible.
* Alan Cox : Tidied up ready for the big day.
* Alan Cox : Fixed write select of no IP protocol crash.
*/
#include <linux/config.h>
......@@ -138,13 +136,6 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
return skb;
}
/*
* Free a datagram buffer. This has some conditions to watch. We keep
* a user count so the last user may free the buffer. If however the
* buffer has a valid next pointer it was never removed and all the
* users PEEKed at it - so don't free it yet.
*/
void skb_free_datagram(struct sk_buff *skb)
{
unsigned long flags;
......@@ -194,11 +185,7 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait)
return(0);
case SEL_OUT:
if(sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
{
return(1);
}
if(sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
{
return(1);
}
......
......@@ -790,6 +790,7 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
return 0;
}
/* Perform the SIOCxIFxxx calls. */
static int
dev_ifsioc(void *arg, unsigned int getset)
......
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Interface (streams) handling functions.
*
* Version: @(#)dev.c 1.28 20/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
*
* Fixes:
* Alan Cox: check_addr returns a value for a wrong subnet
* ie not us but don't forward this!
* Alan Cox: block timer if the inet_bh handler is running
* Alan Cox: generic queue code added. A lot neater now
* C.E.Hawkins: SIOCGIFCONF only reports 'upped' interfaces
* C.E.Hawkins: IFF_PROMISC support
* Alan Cox: Supports Donald Beckers new hardware
* multicast layer, but not yet multicast lists.
* Alan Cox: ip_addr_match problems with class A/B nets.
* C.E.Hawkins IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT]
* Alan Cox: Removed bogus subnet check now the subnet code
* a) actually works for all A/B nets
* b) doesn't forward off the same interface.
* Alan Cox: Multiple extra protocols
* Alan Cox: A Couple more escaped verify_area calls die
* Alan Cox: IP_SET_DEV is gone (forever) as per Fred's comment.
* Alan Cox: Grand tidy up ready for the big day.
* Alan Cox: Handles dev_open errors correctly.
* Alan Cox: IP and generic parts split
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include "inet.h"
#include "devinet.h"
#include "eth.h"
#include "ip.h"
#include "route.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
/*
* Determine a default network mask, based on the IP address.
*/
unsigned long ip_get_mask(unsigned long addr)
{
unsigned long dst;
if (addr == 0L)
return(0L); /* special case */
dst = ntohl(addr);
if (IN_CLASSA(dst))
return(htonl(IN_CLASSA_NET));
if (IN_CLASSB(dst))
return(htonl(IN_CLASSB_NET));
if (IN_CLASSC(dst))
return(htonl(IN_CLASSC_NET));
/* Something else, probably a subnet. */
return(0);
}
/*
* See if a pair of addresses match.
*/
int ip_addr_match(unsigned long me, unsigned long him)
{
int i;
unsigned long mask=0xFFFFFFFF;
DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
/* Fast path for 99.9% of cases */
if (me == him)
return(1);
for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
{
if ((me & 0xFF) != (him & 0xFF))
{
/*
* The only way this could be a match is for
* the rest of addr1 to be 0 or 255.
*/
if (me != 0 && me != mask)
return(0);
return(1);
}
}
return(1);
}
/*
* Check the address for our address, broadcasts, etc.
*
* This routine is used a lot, and in many time critical
* places. It's already _TOO_ slow so be careful how you
* alter it.
*/
int chk_addr(unsigned long addr)
{
struct device *dev;
unsigned long dst;
DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
dst = ntohl(addr);
/*
* Accept both `all ones' and `all zeros' as BROADCAST.
* All 0's is the old BSD broadcast.
*/
if (dst == INADDR_ANY || dst == INADDR_BROADCAST)
{
DPRINTF((DBG_DEV, "BROADCAST\n"));
return(IS_BROADCAST);
}
/* Accept all of the `loopback' class A net. */
if ((dst & IN_CLASSA_NET) == 0x7F000000L)
{
DPRINTF((DBG_DEV, "LOOPBACK\n"));
/*
* We force `loopback' to be equal to MY_ADDR.
*/
return(IS_MYADDR);
/* return(IS_LOOPBACK); */
}
/* OK, now check the interface addresses. */
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (!(dev->flags&IFF_UP))
continue;
if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
return(IS_MYADDR);
/* Is it the exact IP address? */
if (addr == dev->pa_addr)
{
DPRINTF((DBG_DEV, "MYADDR\n"));
return(IS_MYADDR);
}
/* Nope. Check for a subnetwork broadcast. */
if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask))
{
if ((addr & ~dev->pa_mask) == 0)
{
DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
return(IS_BROADCAST);
}
if (((addr & ~dev->pa_mask) | dev->pa_mask)
== INADDR_BROADCAST)
{
DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
return(IS_BROADCAST);
}
}
/* Nope. Check for Network broadcast. */
if(IN_CLASSA(dst))
{
if( addr == (dev->pa_addr | 0xffffff00))
{
DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else if(IN_CLASSB(dst))
{
if( addr == (dev->pa_addr | 0xffff0000))
{
DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else
{ /* IN_CLASSC */
if( addr == (dev->pa_addr | 0xff000000))
{
DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
}
DPRINTF((DBG_DEV, "NONE\n"));
return(0); /* no match at all */
}
/*
* Retrieve our own address.
* Because the loopback address (127.0.0.1) is already recognized
* automatically, we can use the loopback interface's address as
* our "primary" interface. This is the addressed used by IP et
* al when it doesn't know which address to use (i.e. it does not
* yet know from or to which interface to go...).
*/
unsigned long my_addr(void)
{
struct device *dev;
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (dev->flags & IFF_LOOPBACK)
return(dev->pa_addr);
}
return(0);
}
/*
* Find an interface that can handle addresses for a certain address.
*/
struct device *dev_check(unsigned long addr)
{
struct device *dev;
for (dev = dev_base; dev; dev = dev->next)
if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
(addr == dev->pa_dstaddr))
return dev;
for (dev = dev_base; dev; dev = dev->next)
if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
(dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
(dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
break;
/* no need to check broadcast addresses */
return dev;
}
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the INET bits of the interfaces handler.
*
*/
#ifndef _DEVINET_H
#define _DEVINET_H
#ifndef _DEV_H
#include "dev.h"
#endif
extern int ip_addr_match(unsigned long addr1, unsigned long addr2);
extern int chk_addr(unsigned long addr);
extern struct device *dev_check(unsigned long daddr);
extern unsigned long my_addr(void);
#endif /* _DEVINET_H */
......@@ -5,27 +5,24 @@
*
* Ethernet-type device handling.
*
* Version: @(#)eth.c 1.28 20/12/93
* Version: @(#)eth.c 1.0.7 05/25/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
*
* Fixes:
* Mr Linux : Arp problems.
* Alan Cox : Generic queue tidyup (very tiny here).
* Alan Cox : eth_header ntohs should be htons.
* Mr Linux : Arp problems
* Alan Cox : Generic queue tidyup (very tiny here)
* Alan Cox : eth_header ntohs should be htons
* Alan Cox : eth_rebuild_header missing an htons and
* minor other things.
* Tegge : Arp bug fixes.
* Alan Cox : Tidy up ready for the big day.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/types.h>
......@@ -36,19 +33,18 @@
#include <linux/socket.h>
#include <linux/in.h>
#include "inet.h"
#include "devinet.h"
#include "dev.h"
#include "eth.h"
#include "ip.h"
#include "route.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
#include "sockinet.h"
#include "sock.h"
#include <linux/errno.h>
#include "arp.h"
#ifdef ETH_DEBUG
/* Display an Ethernet address in readable format. */
char *eth_print(unsigned char *ptr)
{
......@@ -61,16 +57,32 @@ char *eth_print(unsigned char *ptr)
);
return(buff);
}
#endif
#ifdef ETH_DEBUG
/*
* Display the contents of the Ethernet MAC header.
*/
void eth_setup(char *str, int *ints)
{
struct device *d = dev_base;
if (!str || !*str)
return;
while (d) {
if (!strcmp(str,d->name)) {
if (ints[0] > 0)
d->irq=ints[1];
if (ints[0] > 1)
d->base_addr=ints[2];
if (ints[0] > 2)
d->mem_start=ints[3];
if (ints[0] > 3)
d->mem_end=ints[4];
break;
}
d=d->next;
}
}
void eth_dump(struct ethhdr *eth)
/* Display the contents of the Ethernet MAC header. */
void
eth_dump(struct ethhdr *eth)
{
if (inet_debug != DBG_ETH) return;
......@@ -79,128 +91,96 @@ void eth_dump(struct ethhdr *eth)
printk("TYPE = %04X\n", ntohs(eth->h_proto));
}
#endif
/*
* Create the Ethernet MAC header.
*
* ARP might prevent this from working all in one go. See also
* the rebuild header function.
*/
int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
/* Create the Ethernet MAC header. */
int
eth_header(unsigned char *buff, struct device *dev, unsigned short type,
unsigned long daddr, unsigned long saddr, unsigned len)
{
struct ethhdr *eth;
DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
/* Fill in the basic Ethernet MAC header. */
eth = (struct ethhdr *) buff;
eth->h_proto = htons(type);
/* We don't ARP for the LOOPBACK device... */
if (dev->flags & IFF_LOOPBACK)
{
DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
/* Check if we can use the MAC BROADCAST address. */
if (chk_addr(daddr) == IS_BROADCAST)
{
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
return(dev->hard_header_len);
}
/*
* We disable interrupts here to avoid a race if the ARP
* reply is too quick.
*/
cli();
memcpy(eth->h_source, &saddr, 4);
/* No. Ask ARP to resolve the Ethernet address. */
if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr/* saddr */))
{
sti();
if(type!=ETH_P_IP)
printk("Erk: protocol %X got into an arp request state!\n",type);
return(-dev->hard_header_len);
}
else
{
memcpy(eth->h_source,dev->dev_addr,dev->addr_len); /* This was missing causing chaos if the
header built correctly! */
sti();
return(dev->hard_header_len);
}
struct ethhdr *eth;
DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
/* Fill in the basic Ethernet MAC header. */
eth = (struct ethhdr *) buff;
eth->h_proto = htons(type);
/* We don't ARP for the LOOPBACK device... */
if (dev->flags & IFF_LOOPBACK) {
DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
/* Check if we can use the MAC BROADCAST address. */
if (chk_addr(daddr) == IS_BROADCAST) {
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
return(dev->hard_header_len);
}
cli();
memcpy(eth->h_source, &saddr, 4);
/* No. Ask ARP to resolve the Ethernet address. */
if (arp_find(eth->h_dest, daddr, dev, saddr))
{
sti();
if(type!=ETH_P_IP)
printk("Erk: protocol %X got into an arp request state!\n",type);
return(-dev->hard_header_len);
}
else
{
memcpy(eth->h_source,dev->dev_addr,dev->addr_len); /* This was missing causing chaos if the
header built correctly! */
sti();
return(dev->hard_header_len);
}
}
/*
* Rebuild the Ethernet MAC header.
*
* We've got a 'stuck' packet that failed to go out before. See if
* the arp is resolved and we can finally shift it.
*/
int eth_rebuild_header(void *buff, struct device *dev)
/* Rebuild the Ethernet MAC header. */
int
eth_rebuild_header(void *buff, struct device *dev)
{
struct ethhdr *eth;
unsigned long src, dst;
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
eth = (struct ethhdr *) buff;
src = *(unsigned long *) eth->h_source;
dst = *(unsigned long *) eth->h_dest;
DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
if(eth->h_proto!=htons(ETH_P_ARP)) /* This ntohs kind of helps a bit! */
if (arp_find(eth->h_dest, dst, dev, dev->pa_addr /* src */))
/* Still not known */
return(1);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return(0);
struct ethhdr *eth;
unsigned long src, dst;
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
eth = (struct ethhdr *) buff;
src = *(unsigned long *) eth->h_source;
dst = *(unsigned long *) eth->h_dest;
DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
if(eth->h_proto!=htons(ETH_P_ARP)) /* This ntohs kind of helps a bit! */
if (arp_find(eth->h_dest, dst, dev, src)) return(1);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return(0);
}
/*
* Add an ARP entry for a host on this interface.
*/
void eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
/* Add an ARP entry for a host on this interface. */
void
eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
{
struct ethhdr *eth;
struct ethhdr *eth;
eth = (struct ethhdr *) (skb + 1);
arp_add(addr, eth->h_source, dev);
eth = (struct ethhdr *) (skb + 1);
arp_add(addr, eth->h_source, dev);
}
/*
* Determine the packet's protocol ID.
*
* Ethernet comes in two 'species' DIX (Digitial Intel Xerox) and IEE802.3
* needless to say they are different. Fortunately there is a way of telling
* them apart. All 'normal' modern DIX service ID's are >1536.
* All IEE802.3 frames have a length at this position and that cannot be
* >=1536. Note IEE802.3 frames have a second 802.2 header normally. We don't
* deal with this bit in the current kernel, but a user using SOCK_PACKET
* for 802.3 frames can do so.
*/
unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
/* Determine the packet's protocol ID. */
unsigned short
eth_type_trans(struct sk_buff *skb, struct device *dev)
{
struct ethhdr *eth;
struct ethhdr *eth;
eth = (struct ethhdr *) (skb + 1);
eth = (struct ethhdr *) (skb + 1);
if(ntohs(eth->h_proto)<1536)
return(htons(ETH_P_802_3));
return(eth->h_proto);
if(ntohs(eth->h_proto)<1536)
return(htons(ETH_P_802_3));
return(eth->h_proto);
}
This diff is collapsed.
This diff is collapsed.
......@@ -21,8 +21,8 @@
#include <linux/ip.h>
#include "sockinet.h"
#include "sock.h" /* struct sock */
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
......@@ -69,8 +69,7 @@ extern int ip_build_header(struct sk_buff *skb,
unsigned long saddr,
unsigned long daddr,
struct device **dev, int type,
struct options *opt, int len,
int tos,int ttl);
struct options *opt, int len);
extern unsigned short ip_compute_csum(unsigned char * buff, int len);
extern int ip_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
......@@ -78,6 +77,5 @@ extern void ip_queue_xmit(struct sock *sk,
struct device *dev, struct sk_buff *skb,
int free);
extern void ip_retransmit(struct sock *sk, int all);
extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
#endif /* _IP_H */
......@@ -5,77 +5,71 @@
*
* Pseudo-driver for the loopback interface.
*
* Version: @(#)loopback.c 1.28 20/12/93
* Version: @(#)loopback.c 1.0.4b 08/16/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
*
* This file should be in drivers/net, but our glorious leader
* has put it here, and who are we to argue with the Linus 8-)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
#include "inet.h"
#include "devinet.h"
#include "dev.h"
#include "eth.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
#include "sockinet.h"
#include "sock.h"
#include "arp.h"
static int loopback_xmit(struct sk_buff *skb, struct device *dev)
static int
loopback_xmit(struct sk_buff *skb, struct device *dev)
{
struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
int done;
struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
int done;
DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
if (skb == NULL || dev == NULL)
return(0);
DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
if (skb == NULL || dev == NULL) return(0);
cli();
if (dev->tbusy != 0)
{
sti();
stats->tx_errors++;
return(1);
}
dev->tbusy = 1;
sti();
cli();
if (dev->tbusy != 0) {
sti();
stats->tx_errors++;
return(1);
}
dev->tbusy = 1;
sti();
done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
if (skb->free)
kfree_skb(skb, FREE_WRITE);
done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
if (skb->free) kfree_skb(skb, FREE_WRITE);
while (done != 1)
{
done = dev_rint(NULL, 0, 0, dev);
}
stats->tx_packets++;
while (done != 1) {
done = dev_rint(NULL, 0, 0, dev);
}
stats->tx_packets++;
dev->tbusy = 0;
dev->tbusy = 0;
#if 1
__asm__("cmpl $0,_intr_count\n\t"
......@@ -92,50 +86,52 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev)
: "ax", "dx", "cx");
#endif
return(0);
return(0);
}
static struct enet_statistics *get_stats(struct device *dev)
static struct enet_statistics *
get_stats(struct device *dev)
{
return (struct enet_statistics *)dev->priv;
}
/* Initialize the rest of the LOOPBACK device. */
int loopback_init(struct device *dev)
int
loopback_init(struct device *dev)
{
dev->mtu = 2000; /* MTU */
dev->tbusy = 0;
dev->hard_start_xmit = loopback_xmit;
dev->open = NULL;
dev->mtu = 2000; /* MTU */
dev->tbusy = 0;
dev->hard_start_xmit = loopback_xmit;
dev->open = NULL;
#if 1
dev->hard_header = eth_header;
dev->add_arp = NULL;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_ETHER; /* 0x0001 */
dev->type_trans = eth_type_trans;
dev->rebuild_header = eth_rebuild_header;
dev->hard_header = eth_header;
dev->add_arp = NULL;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_ETHER; /* 0x0001 */
dev->type_trans = eth_type_trans;
dev->rebuild_header = eth_rebuild_header;
#else
dev->hard_header_length = 0;
dev->add_arp = NULL;
dev->addr_len = 0;
dev->type = 0; /* loopback_type (0) */
dev->hard_header = NULL;
dev->type_trans = NULL;
dev->rebuild_header = NULL;
dev->hard_header_length = 0;
dev->add_arp = NULL;
dev->addr_len = 0;
dev->type = 0; /* loopback_type (0) */
dev->hard_header = NULL;
dev->type_trans = NULL;
dev->rebuild_header = NULL;
#endif
dev->queue_xmit = dev_queue_xmit;
dev->queue_xmit = dev_queue_xmit;
/* New-style flags. */
dev->flags = IFF_LOOPBACK;
dev->family = AF_INET;
dev->pa_addr = in_aton("127.0.0.1");
dev->pa_brdaddr = in_aton("127.255.255.255");
dev->pa_mask = in_aton("255.0.0.0");
dev->pa_alen = sizeof(unsigned long);
dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct enet_statistics));
dev->get_stats = get_stats;
dev->flags = IFF_LOOPBACK;
dev->family = AF_INET;
dev->pa_addr = in_aton("127.0.0.1");
dev->pa_brdaddr = in_aton("127.255.255.255");
dev->pa_mask = in_aton("255.0.0.0");
dev->pa_alen = sizeof(unsigned long);
dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct enet_statistics));
dev->get_stats = get_stats;
return(0);
return(0);
};
This diff is collapsed.
......@@ -7,7 +7,7 @@
* PROC file system. It is mainly used for debugging and
* statistics.
*
* Version: @(#)proc.c 1.28 20/12/93
* Version: @(#)proc.c 1.0.5 05/27/93
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
......@@ -18,7 +18,10 @@
* using hint flag for the netinfo.
* Pauline Middelink : Pidentd support
* Alan Cox : Make /proc safer.
* Alan Cox : Final clean up.
*
* To Do:
* Put the creating userid in the proc/net/... files. This will
* allow us to write an RFC931 daemon for Linux
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -34,13 +37,13 @@
#include <linux/in.h>
#include <linux/param.h>
#include "inet.h"
#include "devinet.h"
#include "dev.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "udp.h"
#include "socket/skbuff.h"
#include "sockinet.h"
#include "skbuff.h"
#include "sock.h"
#include "raw.h"
/*
......@@ -50,83 +53,81 @@
* As in get_unix_netinfo, the buffer might be too small. If this
* happens, get__netinfo returns only part of the available infos.
*/
static int get__netinfo(struct proto *pro, char *buffer, int format)
static int
get__netinfo(struct proto *pro, char *buffer, int format)
{
struct sock **s_array;
struct sock *sp;
char *pos=buffer;
int i;
int timer_active;
unsigned long dest, src;
unsigned short destp, srcp;
s_array = pro->sock_array;
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
struct sock **s_array;
struct sock *sp;
char *pos=buffer;
int i;
int timer_active;
unsigned long dest, src;
unsigned short destp, srcp;
s_array = pro->sock_array;
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
/*
* This was very pretty but didn't work when a socket is destroyed at the wrong moment
* (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
* with timers we just concede defeat and cli().
*/
for(i = 0; i < SOCK_ARRAY_SIZE; i++)
{
cli();
sp = s_array[i];
while(sp != NULL)
{
dest = sp->daddr;
src = sp->saddr;
destp = sp->dummy_th.dest;
srcp = sp->dummy_th.source;
for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
cli();
sp = s_array[i];
while(sp != NULL) {
dest = sp->daddr;
src = sp->saddr;
destp = sp->dummy_th.dest;
srcp = sp->dummy_th.source;
/* Since we are Little Endian we need to swap the bytes :-( */
destp = ntohs(destp);
srcp = ntohs(srcp);
timer_active = del_timer(&sp->timer);
if (!timer_active)
sp->timer.expires = 0;
pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
SOCK_INODE(sp->socket)->i_uid);
if (timer_active)
add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80)
{
printk("oops, too many %s sockets for netinfo.\n",
/* Since we are Little Endian we need to swap the bytes :-( */
destp = ntohs(destp);
srcp = ntohs(srcp);
timer_active = del_timer(&sp->timer);
if (!timer_active)
sp->timer.expires = 0;
pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
SOCK_INODE(sp->socket)->i_uid);
if (timer_active)
add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80) {
printk("oops, too many %s sockets for netinfo.\n",
pro->name);
return(strlen(buffer));
}
/*
* All sockets with (port mod SOCK_ARRAY_SIZE) = i
* are kept in sock_array[i], so we must follow the
* 'next' link to get them all.
*/
sp = sp->next;
return(strlen(buffer));
}
sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
/*
* All sockets with (port mod SOCK_ARRAY_SIZE) = i
* are kept in sock_array[i], so we must follow the
* 'next' link to get them all.
*/
sp = sp->next;
}
sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
before this will clear before we jump back and cli, so its not as bad as it looks */
}
return(strlen(buffer));
}
return(strlen(buffer));
}
int tcp_get_info(char *buffer)
{
return get__netinfo(&tcp_prot, buffer,0);
return get__netinfo(&tcp_prot, buffer,0);
}
int udp_get_info(char *buffer)
{
return get__netinfo(&udp_prot, buffer,1);
return get__netinfo(&udp_prot, buffer,1);
}
int raw_get_info(char *buffer)
{
return get__netinfo(&raw_prot, buffer,1);
return get__netinfo(&raw_prot, buffer,1);
}
......@@ -5,7 +5,7 @@
*
* INET protocol dispatch tables.
*
* Version: @(#)protocol.c 1.28 20/12/93
* Version: @(#)protocol.c 1.0.5 05/25/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
......@@ -14,8 +14,7 @@
* Alan Cox : Ahah! udp icmp errors don't work because
* udp_err is never called!
* Alan Cox : Added new fields for init and ready for
* proper fragmentation (_NO_ 4K limits!).
* Alan Cox : Final clean up.
* proper fragmentation (_NO_ 4K limits!)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -31,143 +30,132 @@
#include <linux/socket.h>
#include <linux/in.h>
#include "inet.h"
#include "devinet.h"
#include "dev.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "socket/skbuff.h"
#include "sockinet.h"
#include "skbuff.h"
#include "sock.h"
#include "icmp.h"
#include "udp.h"
static struct inet_protocol tcp_protocol =
{
tcp_rcv, /* TCP handler */
NULL, /* No fragment handler (and won't be for a long time) */
tcp_err, /* TCP error control */
NULL, /* next */
IPPROTO_TCP, /* protocol ID */
0, /* copy */
NULL, /* data */
"TCP" /* name */
static struct inet_protocol tcp_protocol = {
tcp_rcv, /* TCP handler */
NULL, /* No fragment handler (and won't be for a long time) */
tcp_err, /* TCP error control */
NULL, /* next */
IPPROTO_TCP, /* protocol ID */
0, /* copy */
NULL, /* data */
"TCP" /* name */
};
static struct inet_protocol udp_protocol =
{
udp_rcv, /* UDP handler */
NULL, /* Will be UDP fraglist handler */
udp_err, /* UDP error control */
&tcp_protocol, /* next */
IPPROTO_UDP, /* protocol ID */
0, /* copy */
NULL, /* data */
"UDP" /* name */
static struct inet_protocol udp_protocol = {
udp_rcv, /* UDP handler */
NULL, /* Will be UDP fraglist handler */
udp_err, /* UDP error control */
&tcp_protocol, /* next */
IPPROTO_UDP, /* protocol ID */
0, /* copy */
NULL, /* data */
"UDP" /* name */
};
static struct inet_protocol icmp_protocol =
{
icmp_rcv, /* ICMP handler */
NULL, /* ICMP never fragments anyway */
NULL, /* ICMP error control */
&udp_protocol, /* next */
IPPROTO_ICMP, /* protocol ID */
0, /* copy */
NULL, /* data */
"ICMP" /* name */
static struct inet_protocol icmp_protocol = {
icmp_rcv, /* ICMP handler */
NULL, /* ICMP never fragments anyway */
NULL, /* ICMP error control */
&udp_protocol, /* next */
IPPROTO_ICMP, /* protocol ID */
0, /* copy */
NULL, /* data */
"ICMP" /* name */
};
struct inet_protocol *inet_protocol_base = &icmp_protocol;
struct inet_protocol *inet_protos[MAX_INET_PROTOS] =
{
NULL
struct inet_protocol *inet_protos[MAX_INET_PROTOS] = {
NULL
};
struct inet_protocol *inet_get_protocol(unsigned char prot)
struct inet_protocol *
inet_get_protocol(unsigned char prot)
{
unsigned char hash;
struct inet_protocol *p;
DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
hash = prot & (MAX_INET_PROTOS - 1);
for (p = inet_protos[hash] ; p != NULL; p=p->next)
{
DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
if (p->protocol == prot)
return((struct inet_protocol *) p);
}
return(NULL);
unsigned char hash;
struct inet_protocol *p;
DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
hash = prot & (MAX_INET_PROTOS - 1);
for (p = inet_protos[hash] ; p != NULL; p=p->next) {
DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
if (p->protocol == prot) return((struct inet_protocol *) p);
}
return(NULL);
}
void inet_add_protocol(struct inet_protocol *prot)
void
inet_add_protocol(struct inet_protocol *prot)
{
unsigned char hash;
struct inet_protocol *p2;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
prot ->next = inet_protos[hash];
inet_protos[hash] = prot;
prot->copy = 0;
/* Set the copy bit if we need to. */
p2 = (struct inet_protocol *) prot->next;
while(p2 != NULL)
{
if (p2->protocol == prot->protocol)
{
prot->copy = 1;
break;
}
p2 = (struct inet_protocol *) prot->next;
}
unsigned char hash;
struct inet_protocol *p2;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
prot ->next = inet_protos[hash];
inet_protos[hash] = prot;
prot->copy = 0;
/* Set the copy bit if we need to. */
p2 = (struct inet_protocol *) prot->next;
while(p2 != NULL) {
if (p2->protocol == prot->protocol) {
prot->copy = 1;
break;
}
p2 = (struct inet_protocol *) prot->next;
}
}
int inet_del_protocol(struct inet_protocol *prot)
int
inet_del_protocol(struct inet_protocol *prot)
{
struct inet_protocol *p;
struct inet_protocol *lp = NULL;
unsigned char hash;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
if (prot == inet_protos[hash])
{
inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
return(0);
}
p = (struct inet_protocol *) inet_protos[hash];
while(p != NULL)
{
struct inet_protocol *p;
struct inet_protocol *lp = NULL;
unsigned char hash;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
if (prot == inet_protos[hash]) {
inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
return(0);
}
p = (struct inet_protocol *) inet_protos[hash];
while(p != NULL) {
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someones copied bit.
*/
if (p->next != NULL && p->next == prot) {
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someones copied bit.
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if (p->next != NULL && p->next == prot)
{
/*
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if (p->copy == 0 && lp != NULL)
lp->copy = 0;
p->next = prot->next;
return(0);
}
if (p->next != NULL && p->next->protocol == prot->protocol)
{
lp = p;
}
p = (struct inet_protocol *) p->next;
}
return(-1);
if (p->copy == 0 && lp != NULL) lp->copy = 0;
p->next = prot->next;
return(0);
}
if (p->next != NULL && p->next->protocol == prot->protocol) {
lp = p;
}
p = (struct inet_protocol *) p->next;
}
return(-1);
}
This diff is collapsed.
......@@ -47,18 +47,18 @@ static struct rtable *rt_base = NULL;
static struct rtable *rt_loopback = NULL;
/* Dump the contents of a routing table entry. */
static void rt_print(struct rtable *rt)
static void
rt_print(struct rtable *rt)
{
if (rt == NULL || inet_debug != DBG_RT)
return;
if (rt == NULL || inet_debug != DBG_RT) return;
printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
(long) rt, (long) rt->rt_next, rt->rt_flags);
printk(" TARGET=%s ", in_ntoa(rt->rt_dst));
printk("GW=%s ", in_ntoa(rt->rt_gateway));
printk(" DEV=%s USE=%ld REF=%d\n",
(rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
rt->rt_use, rt->rt_refcnt);
printk(" TARGET=%s ", in_ntoa(rt->rt_dst));
printk("GW=%s ", in_ntoa(rt->rt_gateway));
printk(" DEV=%s USE=%ld REF=%d\n",
(rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
rt->rt_use, rt->rt_refcnt);
}
......@@ -162,8 +162,8 @@ static inline struct device * get_gw_dev(unsigned long gw)
/*
* rewrote rt_add(), as the old one was weird. Linus
*/
void rt_add(short flags, unsigned long dst, unsigned long mask,
unsigned long gw, struct device *dev)
void
rt_add(short flags, unsigned long dst, unsigned long mask, unsigned long gw, struct device *dev)
{
struct rtable *r, *rt;
struct rtable **rp;
......@@ -280,35 +280,38 @@ static int rt_new(struct rtentry *r)
}
static int rt_kill(struct rtentry *r)
static int
rt_kill(struct rtentry *r)
{
struct sockaddr_in *trg;
struct sockaddr_in *trg;
trg = (struct sockaddr_in *) &r->rt_dst;
rt_del(trg->sin_addr.s_addr);
return 0;
trg = (struct sockaddr_in *) &r->rt_dst;
rt_del(trg->sin_addr.s_addr);
return(0);
}
/* Called from the PROCfs module. */
int rt_get_info(char *buffer)
int
rt_get_info(char *buffer)
{
struct rtable *r;
char *pos;
struct rtable *r;
char *pos;
pos = buffer;
pos = buffer;
pos += sprintf(pos,
"Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
pos += sprintf(pos,
"Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
/* This isn't quite right -- r->rt_dst is a struct! */
for (r = rt_base; r != NULL; r = r->rt_next) {
pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
r->rt_dev->name, r->rt_dst, r->rt_gateway,
r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
r->rt_mask);
}
return pos - buffer;
/* This isn't quite right -- r->rt_dst is a struct! */
for (r = rt_base; r != NULL; r = r->rt_next) {
pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
r->rt_dev->name, r->rt_dst, r->rt_gateway,
r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
r->rt_mask);
}
return(pos - buffer);
}
/*
......@@ -337,41 +340,39 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
}
int rt_ioctl(unsigned int cmd, void *arg)
int
rt_ioctl(unsigned int cmd, void *arg)
{
struct device *dev;
struct rtentry rt;
char namebuf[32];
int ret;
int err;
struct device *dev;
struct rtentry rt;
char namebuf[32];
int ret;
int err;
switch(cmd) {
switch(cmd) {
case DDIOCSDBG:
ret = dbg_ioctl(arg, DBG_RT);
break;
case SIOCADDRT:
case SIOCDELRT:
if (!suser())
return -EPERM;
err = verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
if (!suser()) return(-EPERM);
err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
if(err)
return err;
memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
if (rt.rt_dev) {
err = verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
if(err)
return err;
memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
dev = dev_get(namebuf);
rt.rt_dev = dev;
err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
if(err)
return err;
memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
dev = dev_get(namebuf);
rt.rt_dev = dev;
}
ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
break;
default:
ret = -EINVAL;
}
}
return ret;
return(ret);
}
......@@ -24,15 +24,15 @@
/* This is an entry in the IP routing table. */
struct rtable {
struct rtable *rt_next;
unsigned long rt_dst;
unsigned long rt_mask;
unsigned long rt_gateway;
u_char rt_flags;
u_char rt_metric;
short rt_refcnt;
u_long rt_use;
struct device *rt_dev;
struct rtable *rt_next;
unsigned long rt_dst;
unsigned long rt_mask;
unsigned long rt_gateway;
u_char rt_flags;
u_char rt_metric;
short rt_refcnt;
u_long rt_use;
struct device *rt_dev;
};
......
......@@ -303,9 +303,6 @@ struct sk_buff *skb_peek(struct sk_buff *volatile* list)
return *list;
}
#ifdef UNUSED_NOW
/*
* Get a clone of an sk_buff. This is the safe way to peek at
* a socket queue without accidents. Its a bit long but most
......@@ -371,8 +368,6 @@ struct sk_buff *skb_peek_copy(struct sk_buff *volatile* list)
restore_flags(flags);
return(newsk);
}
#endif
/*
* Free an sk_buff. This still knows about things it should
......@@ -381,42 +376,40 @@ struct sk_buff *skb_peek_copy(struct sk_buff *volatile* list)
void kfree_skb(struct sk_buff *skb, int rw)
{
if (skb == NULL) {
printk("kfree_skb: skb = NULL\n");
return;
}
IS_SKB(skb);
if(skb->free == 2)
printk("Warning: kfree_skb passed an skb that nobody set the free flag on!\n");
if(skb->list)
printk("Warning: kfree_skb passed an skb still on a list.\n");
skb->magic = 0;
if (skb->sk)
{
if(skb->sk->prot!=NULL)
{
if (rw)
skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
else
skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
}
else
{
/* Non INET - default wmalloc/rmalloc handler */
if (rw)
skb->sk->rmem_alloc-=skb->mem_len;
else
skb->sk->wmem_alloc-=skb->mem_len;
if(!skb->sk->dead)
skb->sk->write_space(skb->sk);
kfree_skbmem(skb->mem_addr,skb->mem_len);
}
}
else
if (skb == NULL) {
printk("kfree_skb: skb = NULL\n");
return;
}
IS_SKB(skb);
if(skb->free == 2)
printk("Warning: kfree_skb passed an skb that nobody set the free flag on!\n");
if(skb->list)
printk("Warning: kfree_skb passed an skb still on a list.\n");
skb->magic = 0;
if (skb->sk)
{
if(skb->sk->prot!=NULL)
{
if (rw)
skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
else
skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
}
else
{
kfree_skbmem(skb->mem_addr, skb->mem_len);
/* Non INET - default wmalloc/rmalloc handler */
if (rw)
skb->sk->rmem_alloc-=skb->mem_len;
else
skb->sk->wmem_alloc-=skb->mem_len;
if(!skb->sk->dead)
wake_up(skb->sk->sleep);
kfree_skbmem(skb->mem_addr,skb->mem_len);
}
}
else
kfree_skbmem(skb->mem_addr, skb->mem_len);
}
/*
......
......@@ -17,7 +17,6 @@
* Alan Cox : Fraglist support (idea by Donald Becker)
* Alan Cox : 'users' counter. Combines with datagram changes to avoid skb_peek_copy
* being used.
* Alan Cox : Extra fields for RAW fixes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -29,7 +28,7 @@
#include <linux/malloc.h>
#ifdef CONFIG_IPX
#include "ipx/ipx.h"
#include "ipx.h"
#endif
#define HAVE_ALLOC_SKB /* For the drivers to know */
......@@ -39,46 +38,43 @@
#define FREE_WRITE 0
struct sk_buff
{
unsigned long magic_debug_cookie;
struct sk_buff *volatile next;
struct sk_buff *volatile prev;
struct sk_buff *volatile link3;
struct sk_buff *volatile* list;
struct sock *sk;
volatile unsigned long when; /* used to compute rtt's */
struct device *dev;
void *mem_addr;
union
{
struct tcphdr *th;
struct ethhdr *eth;
struct iphdr *iph;
struct udphdr *uh;
struct arphdr *arp;
unsigned char *raw;
unsigned long seq;
struct sk_buff {
unsigned long magic_debug_cookie;
struct sk_buff *volatile next;
struct sk_buff *volatile prev;
struct sk_buff *volatile link3;
struct sk_buff *volatile* list;
struct sock *sk;
volatile unsigned long when; /* used to compute rtt's */
struct device *dev;
void *mem_addr;
union {
struct tcphdr *th;
struct ethhdr *eth;
struct iphdr *iph;
struct udphdr *uh;
struct arphdr *arp;
unsigned char *raw;
unsigned long seq;
#ifdef CONFIG_IPX
ipx_packet *ipx;
ipx_packet *ipx;
#endif
} h;
struct iphdr * ip_hdr;
unsigned long mem_len;
unsigned long len;
unsigned long fraglen;
struct sk_buff *fraglist; /* Fragment list */
unsigned long truesize;
unsigned long saddr;
unsigned long daddr;
int magic;
volatile char acked,
} h;
unsigned long mem_len;
unsigned long len;
unsigned long fraglen;
struct sk_buff *fraglist; /* Fragment list */
unsigned long truesize;
unsigned long saddr;
unsigned long daddr;
int magic;
volatile char acked,
used,
free,
arp,
urg_used;
unsigned char tries,lock; /* Lock is now unused */
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
unsigned char tries,lock; /* Lock is now unused */
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
};
#define SK_WMEM_MAX 8192
......
This diff is collapsed.
/*
* Definitions for the socket handler
*
* Version: @(#)sock.h 1.28 26/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Corey Minyard <wf-rch!minyard@relay.EU.net>
* Florian La Roche <flla@stud.uni-sb.de>
*
* Fixes:
* Alan Cox : Volatiles in skbuff pointers. See
* skbuff comments. May be overdone,
* better to prove they can be removed
* than the reverse.
* Alan Cox : Added a zapped field for tcp to note
* a socket is reset and must stay shut up
* Alan Cox : New fields for options
* Pauline Middelink : identd support
* Alan Cox : Split into sock.h and sockinet.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _SOCKINET_H
#define _SOCKINET_H
#ifndef _SOCK_H
#include "socket/sock.h"
#endif
#ifndef _PROTOCOL_H_
#include "protocol.h"
#endif
struct proto {
void *(*wmalloc)(struct sock *sk,
unsigned long size, int force,
int priority);
void *(*rmalloc)(struct sock *sk,
unsigned long size, int force,
int priority);
void (*wfree)(struct sock *sk, void *mem,
unsigned long size);
void (*rfree)(struct sock *sk, void *mem,
unsigned long size);
unsigned long (*rspace)(struct sock *sk);
unsigned long (*wspace)(struct sock *sk);
void (*close)(struct sock *sk, int timeout);
int (*read)(struct sock *sk, unsigned char *to,
int len, int nonblock, unsigned flags);
int (*write)(struct sock *sk, unsigned char *to,
int len, int nonblock, unsigned flags);
int (*sendto)(struct sock *sk,
unsigned char *from, int len, int noblock,
unsigned flags, struct sockaddr_in *usin,
int addr_len);
int (*recvfrom)(struct sock *sk,
unsigned char *from, int len, int noblock,
unsigned flags, struct sockaddr_in *usin,
int *addr_len);
int (*build_header)(struct sk_buff *skb,
unsigned long saddr,
unsigned long daddr,
struct device **dev, int type,
struct options *opt, int len,
int ttl, int tos);
int (*connect)(struct sock *sk,
struct sockaddr_in *usin, int addr_len);
struct sock *(*accept) (struct sock *sk, int flags);
void (*queue_xmit)(struct sock *sk,
struct device *dev, struct sk_buff *skb,
int free);
void (*retransmit)(struct sock *sk, int all);
void (*write_wakeup)(struct sock *sk);
void (*read_wakeup)(struct sock *sk);
int (*rcv)(struct sk_buff *buff, struct device *dev,
struct options *opt, unsigned long daddr,
unsigned short len, unsigned long saddr,
int redo, struct inet_protocol *protocol);
int (*select)(struct sock *sk, int which,
select_table *wait);
int (*ioctl)(struct sock *sk, int cmd,
unsigned long arg);
int (*init)(struct sock *sk);
void (*shutdown)(struct sock *sk, int how);
int (*setsockopt)(struct sock *sk, int level, int optname,
char *optval, int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
char *optval, int *option);
unsigned short max_header;
unsigned long retransmits;
struct sock *sock_array[SOCK_ARRAY_SIZE];
char name[80];
};
extern void destroy_sock(struct sock *sk);
extern unsigned short get_new_socknum(struct proto *, unsigned short);
extern void put_sock(unsigned short, struct sock *);
extern void release_sock(struct sock *sk);
extern struct sock *get_sock(struct proto *, unsigned short,
unsigned long, unsigned short,
unsigned long);
/* declarations from timer.c */
extern struct sock *timer_base;
void delete_timer (struct sock *);
void reset_timer (struct sock *, int, unsigned long);
void net_timer (unsigned long);
#endif
This diff is collapsed.
......@@ -75,46 +75,43 @@
* normal compare so long as neither of the numbers is within
* 4K of wrapping. Otherwise we must check for the wrap.
*/
static inline int before (unsigned long seq1, unsigned long seq2)
static inline int
before (unsigned long seq1, unsigned long seq2)
{
/* this inequality is strict. */
if (seq1 == seq2)
return(0);
if (seq1 < seq2)
{
if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL)
{
return(1);
}
else
{
return(0);
}
}
/*
* Now we know seq1 > seq2. So all we need to do is check
* to see if seq1 has wrapped.
*/
if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL))
{
/* this inequality is strict. */
if (seq1 == seq2) return(0);
if (seq1 < seq2) {
if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL) {
return(1);
}
return(0);
} else {
return(0);
}
}
/*
* Now we know seq1 > seq2. So all we need to do is check
* to see if seq1 has wrapped.
*/
if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL)) {
return(1);
}
return(0);
}
static inline int after(unsigned long seq1, unsigned long seq2)
static inline int
after(unsigned long seq1, unsigned long seq2)
{
return(before(seq2, seq1));
return(before(seq2, seq1));
}
/* is s2<=s1<=s3 ? */
static inline int between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
static inline int
between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
{
return(after(seq1+1, seq2) && before(seq1, seq3+1));
return(after(seq1+1, seq2) && before(seq1, seq3+1));
}
......@@ -124,11 +121,12 @@ static inline int between(unsigned long seq1, unsigned long seq2, unsigned long
* convinced that this is the solution for the 'getpeername(2)'
* problem. Thanks to Stephen A. Wood <saw@cebaf.gov> -FvK
*/
static inline const int tcp_connected(const int state)
static inline const int
tcp_connected(const int state)
{
return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT ||
state == TCP_FIN_WAIT1 || state == TCP_FIN_WAIT2 ||
state == TCP_SYN_RECV);
return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT ||
state == TCP_FIN_WAIT1 || state == TCP_FIN_WAIT2 ||
state == TCP_SYN_RECV);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment