Commit de0eab26 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.6

parent 37b4c9bd
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 5
SUBLEVEL = 6
all: Version zImage
......
......@@ -201,9 +201,10 @@ static unsigned int d_link_debug = D_LINK_DEBUG;
/*
* Index to functions, as function prototypes.
*/
#if 0
/* For tricking tcp.c to announce a small max window (max 2 fast packets please :-) */
static unsigned long d_link_rspace(struct sock *sk);
#endif
/* Routines used internally. (See "convenience macros") */
static int d_link_read_status(struct device *dev);
......@@ -689,6 +690,10 @@ adapter_init(struct device *dev)
sti();
}
#if 0
/*
* The new router code (coming soon 8-) ) will fix this properly.
*/
#define D_LINK_MIN_WINDOW 1024
#define D_LINK_MAX_WINDOW 2048
#define D_LINK_TCP_WINDOW_DIFF 1024
......@@ -724,3 +729,6 @@ d_link_rspace(struct sock *sk)
}
return(0);
}
#endif
......@@ -644,32 +644,7 @@ depca_probe1(struct device *dev, short ioaddr)
dev->mem_start = 0;
/* Fill in the generic field of the device structure. */
for (i = 0; i < DEV_NUMBUFFS; i++) {
dev->buffs[i] = NULL;
}
dev->hard_header = eth_header;
dev->add_arp = eth_add_arp;
dev->queue_xmit = dev_queue_xmit;
dev->rebuild_header = eth_rebuild_header;
dev->type_trans = eth_type_trans;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = 1500; /* eth_mtu */
dev->addr_len = ETH_ALEN;
for (i = 0; i < dev->addr_len; i++) {
dev->broadcast[i]=0xff;
}
/* New-style flags. */
dev->flags = IFF_BROADCAST;
dev->family = AF_INET;
dev->pa_addr = 0;
dev->pa_brdaddr = 0;
dev->pa_mask = 0;
dev->pa_alen = sizeof(unsigned long);
ether_setup(dev);
}
} else {
status = -ENXIO;
......@@ -832,14 +807,6 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev)
return 0;
}
/* Fill in the ethernet header. */
if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
}
skb->arp=1;
if (skb->len <= 0) {
return 0;
}
......
......@@ -1030,6 +1030,12 @@ int sl_set_mac_address(struct device *dev, void *addr)
memcpy_fromfs(dev->dev_addr,addr,7); /* addr is an AX.25 shifted ASCII mac address */
return 0;
}
static int sl_set_dev_mac_address(struct device *dev, void *addr)
{
memcpy(dev->dev_addr,addr,7);
return 0;
}
#endif
......@@ -1144,7 +1150,7 @@ slip_init(struct device *dev)
dev->get_stats = sl_get_stats;
#ifdef HAVE_SET_MAC_ADDR
#ifdef CONFIG_AX25
dev->set_mac_address = sl_set_mac_address;
dev->set_mac_address = sl_set_dev_mac_address;
#endif
#endif
dev->hard_header_len = 0;
......
......@@ -68,7 +68,7 @@ struct sk_buff {
used,
free,
arp;
unsigned char tries,lock;
unsigned char tries,lock,localroute;
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
unsigned long padding[0];
unsigned char data[0];
......
......@@ -42,6 +42,7 @@ struct linger {
/* Flags we can use with send/ and recv. */
#define MSG_OOB 1
#define MSG_PEEK 2
#define MSG_DONTROUTE 4
/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
#define SOL_SOCKET 1
......
......@@ -364,17 +364,6 @@ NORET_TYPE void do_exit(long code)
sem_exit();
if (current->shm)
shm_exit();
free_page_tables(current);
for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i])
sys_close(i);
forget_original_parent(current);
iput(current->pwd);
current->pwd = NULL;
iput(current->root);
current->root = NULL;
iput(current->executable);
current->executable = NULL;
/* Release all of the old mmap stuff. */
{
......@@ -390,17 +379,28 @@ NORET_TYPE void do_exit(long code)
}
}
/* forget local segments */
__asm__ __volatile__("mov %w0,%%fs ; mov %w0,%%gs ; lldt %w0"
: /* no outputs */
: "r" (0));
current->tss.ldt = 0;
if (current->ldt) {
vfree(current->ldt);
void * ldt = current->ldt;
current->ldt = NULL;
for (i=1 ; i<NR_TASKS ; i++) {
if (task[i] == current) {
set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, &default_ldt, 1);
load_ldt(i);
}
}
vfree(ldt);
}
free_page_tables(current);
for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i])
sys_close(i);
forget_original_parent(current);
iput(current->pwd);
current->pwd = NULL;
iput(current->root);
current->root = NULL;
iput(current->executable);
current->executable = NULL;
/*
* Check to see if any process groups have become orphaned
* as a result of our exiting, and if they have any stopped
......
......@@ -549,7 +549,7 @@ void dev_transmit(void)
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (!dev->tbusy) {
if (dev->flags != 0 && !dev->tbusy) {
/*
* Kick the device
*/
......
......@@ -284,7 +284,10 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
if (*dev == NULL)
{
rt = ip_rt_route(daddr, &optmem, &src);
if(skb->localroute)
rt = ip_rt_local(daddr, &optmem, &src);
else
rt = ip_rt_route(daddr, &optmem, &src);
if (rt == NULL)
{
ip_statistics.IpOutNoRoutes++;
......@@ -308,7 +311,10 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
/*
* We still need the address of the first hop.
*/
rt = ip_rt_route(daddr, &optmem, &src);
if(skb->localroute)
rt = ip_rt_local(daddr, &optmem, &src);
else
rt = ip_rt_route(daddr, &optmem, &src);
/*
* If the frame is from us and going off machine it MUST MUST MUST
* have the output device ip address and never the loopback
......
......@@ -503,6 +503,7 @@ static int ipx_create(struct socket *sock, int protocol)
sk->type=sock->type;
sk->ipx_type=0; /* General user level IPX */
sk->debug=0;
sk->localroute=0;
memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr));
memset(&sk->ipx_source_addr,'\0',sizeof(sk->ipx_source_addr));
......@@ -836,7 +837,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
int size;
ipx_route *rt;
if(flags)
if(flags&~MSG_DONTROUTE)
return -EINVAL;
if(len<0)
return -EINVAL;
......@@ -882,7 +883,8 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
/* Find out where this has to go */
rt=ipxrtr_get_dev(sipx.sipx_network);
if(rt==NULL)
/* No suitable route - no gateways when not routing */
if(rt==NULL || ((flags&IPX_RT_ROUTED)&& ((flags&MSG_DONTROUTE)||sk->localroute)))
{
return -ENETUNREACH;
}
......@@ -917,7 +919,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
skb->dev=rt->dev;
dev->hard_header(skb->data,skb->dev,
(rt->flags&IPX_RT_BLUEBOOK)?ntohs(ETH_P_IPX):ntohs(len+sizeof(ipx_packet)),
(rt->flags&IPX_RT_BLUEBOOK)?ETH_P_IPX:ETH_P_802_3),
(rt->flags&IPX_RT_ROUTED)?rt->router_node:sipx.sipx_node,
NULL,
len+sizeof(ipx_packet),
......
......@@ -142,143 +142,162 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
return(0);
}
/*
* Send a RAW IP packet.
*/
/* This will do terrible things if len + ipheader + devheader > dev->mtu */
static int
raw_sendto(struct sock *sk, unsigned char *from, int len,
int noblock,
unsigned flags, struct sockaddr_in *usin, int addr_len)
static int raw_sendto(struct sock *sk, unsigned char *from,
int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
{
struct sk_buff *skb;
struct device *dev=NULL;
struct sockaddr_in sin;
int tmp;
int err;
DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
" usin=%X, addr_len = %d)\n", sk, from, len, noblock,
flags, usin, addr_len));
/* Check the flags. */
if (flags) return(-EINVAL);
if (len < 0) return(-EINVAL);
err=verify_area(VERIFY_READ,from,len);
if(err)
return err;
/* Get and verify the address. */
if (usin) {
if (addr_len < sizeof(sin)) return(-EINVAL);
err=verify_area (VERIFY_READ, usin, sizeof (sin));
struct sk_buff *skb;
struct device *dev=NULL;
struct sockaddr_in sin;
int tmp;
int err;
DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
" usin=%X, addr_len = %d)\n", sk, from, len, noblock,
flags, usin, addr_len));
/*
* Check the flags. Only MSG_DONTROUTE is permitted.
*/
if (flags&MSG_DONTROUTE)
return(-EINVAL);
if (len < 0)
return(-EINVAL);
err=verify_area(VERIFY_READ,from,len);
if(err)
return err;
memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
} else {
if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
sin.sin_family = AF_INET;
sin.sin_port = sk->protocol;
sin.sin_addr.s_addr = sk->daddr;
}
if (sin.sin_port == 0) sin.sin_port = sk->protocol;
/*
* Get and verify the address.
*/
if (usin)
{
if (addr_len < sizeof(sin))
return(-EINVAL);
err=verify_area (VERIFY_READ, usin, sizeof (sin));
if(err)
return err;
memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET)
return(-EINVAL);
}
else
{
if (sk->state != TCP_ESTABLISHED)
return(-EINVAL);
sin.sin_family = AF_INET;
sin.sin_port = sk->protocol;
sin.sin_addr.s_addr = sk->daddr;
}
if (sin.sin_port == 0)
sin.sin_port = sk->protocol;
if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES;
sk->inuse = 1;
skb = NULL;
while (skb == NULL) {
if(sk->err!=0)
{
err= -sk->err;
sk->err=0;
release_sock(sk);
return(err);
}
if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES;
sk->inuse = 1;
skb = NULL;
while (skb == NULL)
{
if(sk->err!=0)
{
err= -sk->err;
sk->err=0;
release_sock(sk);
return(err);
}
skb = sk->prot->wmalloc(sk,
len + sk->prot->max_header,
0, GFP_KERNEL);
if (skb == NULL) {
int tmp;
DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
if (noblock)
return(-EAGAIN);
tmp = sk->wmem_alloc;
release_sock(sk);
cli();
if (tmp <= sk->wmem_alloc) {
interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked) {
sti();
return(-ERESTARTSYS);
skb = sk->prot->wmalloc(sk,
len + sk->prot->max_header,
0, GFP_KERNEL);
if (skb == NULL)
{
int tmp;
DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
if (noblock)
return(-EAGAIN);
tmp = sk->wmem_alloc;
release_sock(sk);
cli();
if (tmp <= sk->wmem_alloc) {
interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked) {
sti();
return(-ERESTARTSYS);
}
}
sk->inuse = 1;
sti();
}
sk->inuse = 1;
sti();
}
}
skb->sk = sk;
skb->sk = sk;
skb->free = 1;
skb->localroute = sk->localroute | (flags&MSG_DONTROUTE);
skb->free = 1;
tmp = sk->prot->build_header(skb, sk->saddr,
tmp = sk->prot->build_header(skb, sk->saddr,
sin.sin_addr.s_addr, &dev,
sk->protocol, sk->opt, skb->mem_len, sk->ip_tos,sk->ip_ttl);
if (tmp < 0) {
DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
kfree_skb(skb,FREE_WRITE);
release_sock(sk);
return(tmp);
}
if (tmp < 0)
{
DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
kfree_skb(skb,FREE_WRITE);
release_sock(sk);
return(tmp);
}
/* verify_area(VERIFY_WRITE, from, len);*/
memcpy_fromfs(skb->data + tmp, from, len);
memcpy_fromfs(skb->data + tmp, from, len);
/* If we are using IPPROTO_RAW, we need to fill in the source address in
the IP header */
/*
* If we are using IPPROTO_RAW, we need to fill in the source address in
* the IP header
*/
if(sk->protocol==IPPROTO_RAW) {
unsigned char *buff;
struct iphdr *iph;
if(sk->protocol==IPPROTO_RAW)
{
unsigned char *buff;
struct iphdr *iph;
buff = skb->data;
buff += tmp;
iph = (struct iphdr *)buff;
iph->saddr = sk->saddr;
}
buff = skb->data;
buff += tmp;
skb->len = tmp + len;
iph = (struct iphdr *)buff;
iph->saddr = sk->saddr;
}
skb->len = tmp + len;
sk->prot->queue_xmit(sk, dev, skb, 1);
release_sock(sk);
return(len);
sk->prot->queue_xmit(sk, dev, skb, 1);
release_sock(sk);
return(len);
}
static int
raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
static int raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
unsigned flags)
{
return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
}
static void
raw_close(struct sock *sk, int timeout)
static void raw_close(struct sock *sk, int timeout)
{
sk->inuse = 1;
sk->state = TCP_CLOSE;
sk->inuse = 1;
sk->state = TCP_CLOSE;
DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
((struct inet_protocol *)sk->pair)->protocol));
if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
DPRINTF((DBG_RAW, "raw_close: del_protocol failed.\n"));
kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
sk->pair = NULL;
release_sock(sk);
kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
sk->pair = NULL;
release_sock(sk);
}
......
......@@ -573,6 +573,42 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l
return NULL;
}
struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr)
{
struct rtable *rt;
for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
{
/*
* No routed addressing.
*/
if (rt->rt_flags&RTF_GATEWAY)
continue;
if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
break;
/*
* broadcast addresses can be special cases..
*/
if ((rt->rt_dev->flags & IFF_BROADCAST) &&
rt->rt_dev->pa_brdaddr == daddr)
break;
}
if(src_addr!=NULL)
*src_addr= rt->rt_dev->pa_addr;
if (daddr == rt->rt_dev->pa_addr) {
if ((rt = rt_loopback) == NULL)
goto no_route;
}
rt->rt_use++;
return rt;
no_route:
return NULL;
}
/*
* Backwards compatibility
*/
......
......@@ -9,6 +9,8 @@
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Fixes:
* Alan Cox : Reformatted. Added ip_rt_local()
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -23,17 +25,18 @@
/* 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;
unsigned char rt_flags;
unsigned char rt_metric;
short rt_refcnt;
unsigned long rt_use;
unsigned short rt_mss, rt_mtu;
struct device *rt_dev;
struct rtable
{
struct rtable *rt_next;
unsigned long rt_dst;
unsigned long rt_mask;
unsigned long rt_gateway;
unsigned char rt_flags;
unsigned char rt_metric;
short rt_refcnt;
unsigned long rt_use;
unsigned short rt_mss, rt_mtu;
struct device *rt_dev;
};
......@@ -41,6 +44,7 @@ extern void ip_rt_flush(struct device *dev);
extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask,
unsigned long gw, struct device *dev);
extern struct rtable *ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern struct rtable *ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern int rt_get_info(char * buffer, char **start, off_t offset, int length);
extern int ip_rt_ioctl(unsigned int cmd, void *arg);
......
......@@ -489,7 +489,8 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
case SO_DEBUG:
sk->debug=val?1:0;
case SO_DONTROUTE: /* Still to be implemented */
case SO_DONTROUTE:
sk->localroute=val?1:0;
return(0);
case SO_BROADCAST:
sk->broadcast=val?1:0;
......@@ -580,8 +581,8 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
val = sk->debug;
break;
case SO_DONTROUTE: /* One last option to implement */
val = 0;
case SO_DONTROUTE:
val = sk->localroute;
break;
case SO_BROADCAST:
......@@ -852,6 +853,7 @@ inet_create(struct socket *sock, int protocol)
sk->send_head = NULL;
sk->timeout = 0;
sk->broadcast = 0;
sk->localroute = 0;
sk->timer.data = (unsigned long)sk;
sk->timer.function = &net_timer;
skb_queue_head_init(&sk->back_log);
......
......@@ -132,6 +132,7 @@ struct sock {
unsigned short rcvbuf;
unsigned short sndbuf;
unsigned short type;
unsigned char localroute; /* Route locally only */
#ifdef CONFIG_IPX
ipx_address ipx_source_addr,ipx_dest_addr;
unsigned short ipx_type;
......
This diff is collapsed.
......@@ -250,7 +250,7 @@ static void udp_send_check(struct udphdr *uh, unsigned long saddr,
static int udp_send(struct sock *sk, struct sockaddr_in *sin,
unsigned char *from, int len)
unsigned char *from, int len, int rt)
{
struct sk_buff *skb;
struct device *dev;
......@@ -281,6 +281,7 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin,
skb->sk = NULL; /* to avoid changing sk->saddr */
skb->free = 1;
skb->localroute = sk->localroute|(rt&MSG_DONTROUTE);
/*
* Now build the IP and MAC header.
......@@ -357,7 +358,7 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
/*
* Check the flags. We support no flags for UDP sending
*/
if (flags)
if (flags&~MSG_DONTROUTE)
return(-EINVAL);
if (len < 0)
return(-EINVAL);
......@@ -400,7 +401,7 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
sk->inuse = 1;
/* Send the packet. */
tmp = udp_send(sk, &sin, from, len);
tmp = udp_send(sk, &sin, from, len, flags);
/* The datagram has been sent off. Release the socket. */
release_sock(sk);
......@@ -601,27 +602,29 @@ int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
int
udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
{
struct sockaddr_in sin;
int er;
struct sockaddr_in sin;
int er;
if (addr_len < sizeof(sin))
return(-EINVAL);
if (addr_len < sizeof(sin))
return(-EINVAL);
er=verify_area(VERIFY_READ, usin, sizeof(sin));
if(er)
return er;
er=verify_area(VERIFY_READ, usin, sizeof(sin));
if(er)
return er;
memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET)
return(-EAFNOSUPPORT);
memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET)
return(-EAFNOSUPPORT);
if (sin.sin_addr.s_addr==INADDR_ANY)
sin.sin_addr.s_addr=ip_my_addr();
if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES; /* Must turn broadcast on first */
if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES; /* Must turn broadcast on first */
sk->daddr = sin.sin_addr.s_addr;
sk->dummy_th.dest = sin.sin_port;
sk->state = TCP_ESTABLISHED;
return(0);
sk->daddr = sin.sin_addr.s_addr;
sk->dummy_th.dest = sin.sin_port;
sk->state = TCP_ESTABLISHED;
return(0);
}
......
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