Commit de0eab26 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.6

parent 37b4c9bd
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 5 SUBLEVEL = 6
all: Version zImage all: Version zImage
......
...@@ -201,9 +201,10 @@ static unsigned int d_link_debug = D_LINK_DEBUG; ...@@ -201,9 +201,10 @@ static unsigned int d_link_debug = D_LINK_DEBUG;
/* /*
* Index to functions, as function prototypes. * Index to functions, as function prototypes.
*/ */
#if 0
/* For tricking tcp.c to announce a small max window (max 2 fast packets please :-) */ /* For tricking tcp.c to announce a small max window (max 2 fast packets please :-) */
static unsigned long d_link_rspace(struct sock *sk); static unsigned long d_link_rspace(struct sock *sk);
#endif
/* Routines used internally. (See "convenience macros") */ /* Routines used internally. (See "convenience macros") */
static int d_link_read_status(struct device *dev); static int d_link_read_status(struct device *dev);
...@@ -689,6 +690,10 @@ adapter_init(struct device *dev) ...@@ -689,6 +690,10 @@ adapter_init(struct device *dev)
sti(); sti();
} }
#if 0
/*
* The new router code (coming soon 8-) ) will fix this properly.
*/
#define D_LINK_MIN_WINDOW 1024 #define D_LINK_MIN_WINDOW 1024
#define D_LINK_MAX_WINDOW 2048 #define D_LINK_MAX_WINDOW 2048
#define D_LINK_TCP_WINDOW_DIFF 1024 #define D_LINK_TCP_WINDOW_DIFF 1024
...@@ -724,3 +729,6 @@ d_link_rspace(struct sock *sk) ...@@ -724,3 +729,6 @@ d_link_rspace(struct sock *sk)
} }
return(0); return(0);
} }
#endif
...@@ -644,32 +644,7 @@ depca_probe1(struct device *dev, short ioaddr) ...@@ -644,32 +644,7 @@ depca_probe1(struct device *dev, short ioaddr)
dev->mem_start = 0; dev->mem_start = 0;
/* Fill in the generic field of the device structure. */ /* Fill in the generic field of the device structure. */
for (i = 0; i < DEV_NUMBUFFS; i++) { ether_setup(dev);
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);
} }
} else { } else {
status = -ENXIO; status = -ENXIO;
...@@ -832,14 +807,6 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -832,14 +807,6 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev)
return 0; 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) { if (skb->len <= 0) {
return 0; return 0;
} }
......
...@@ -1030,6 +1030,12 @@ int sl_set_mac_address(struct device *dev, void *addr) ...@@ -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 */ memcpy_fromfs(dev->dev_addr,addr,7); /* addr is an AX.25 shifted ASCII mac address */
return 0; return 0;
} }
static int sl_set_dev_mac_address(struct device *dev, void *addr)
{
memcpy(dev->dev_addr,addr,7);
return 0;
}
#endif #endif
...@@ -1144,7 +1150,7 @@ slip_init(struct device *dev) ...@@ -1144,7 +1150,7 @@ slip_init(struct device *dev)
dev->get_stats = sl_get_stats; dev->get_stats = sl_get_stats;
#ifdef HAVE_SET_MAC_ADDR #ifdef HAVE_SET_MAC_ADDR
#ifdef CONFIG_AX25 #ifdef CONFIG_AX25
dev->set_mac_address = sl_set_mac_address; dev->set_mac_address = sl_set_dev_mac_address;
#endif #endif
#endif #endif
dev->hard_header_len = 0; dev->hard_header_len = 0;
......
...@@ -68,7 +68,7 @@ struct sk_buff { ...@@ -68,7 +68,7 @@ struct sk_buff {
used, used,
free, free,
arp; 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 short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
unsigned long padding[0]; unsigned long padding[0];
unsigned char data[0]; unsigned char data[0];
......
...@@ -42,6 +42,7 @@ struct linger { ...@@ -42,6 +42,7 @@ struct linger {
/* Flags we can use with send/ and recv. */ /* Flags we can use with send/ and recv. */
#define MSG_OOB 1 #define MSG_OOB 1
#define MSG_PEEK 2 #define MSG_PEEK 2
#define MSG_DONTROUTE 4
/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */ /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
#define SOL_SOCKET 1 #define SOL_SOCKET 1
......
...@@ -364,17 +364,6 @@ NORET_TYPE void do_exit(long code) ...@@ -364,17 +364,6 @@ NORET_TYPE void do_exit(long code)
sem_exit(); sem_exit();
if (current->shm) if (current->shm)
shm_exit(); 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. */ /* Release all of the old mmap stuff. */
{ {
...@@ -390,17 +379,28 @@ NORET_TYPE void do_exit(long code) ...@@ -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) { if (current->ldt) {
vfree(current->ldt); void * ldt = current->ldt;
current->ldt = NULL; current->ldt = NULL;
for (i=1 ; i<NR_TASKS ; i++) { vfree(ldt);
if (task[i] == current) {
set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, &default_ldt, 1);
load_ldt(i);
}
}
} }
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 * Check to see if any process groups have become orphaned
* as a result of our exiting, and if they have any stopped * as a result of our exiting, and if they have any stopped
......
...@@ -549,7 +549,7 @@ void dev_transmit(void) ...@@ -549,7 +549,7 @@ void dev_transmit(void)
for (dev = dev_base; dev != NULL; dev = dev->next) for (dev = dev_base; dev != NULL; dev = dev->next)
{ {
if (!dev->tbusy) { if (dev->flags != 0 && !dev->tbusy) {
/* /*
* Kick the device * Kick the device
*/ */
......
...@@ -284,6 +284,9 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd ...@@ -284,6 +284,9 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
if (*dev == NULL) if (*dev == NULL)
{ {
if(skb->localroute)
rt = ip_rt_local(daddr, &optmem, &src);
else
rt = ip_rt_route(daddr, &optmem, &src); rt = ip_rt_route(daddr, &optmem, &src);
if (rt == NULL) if (rt == NULL)
{ {
...@@ -308,6 +311,9 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd ...@@ -308,6 +311,9 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
/* /*
* We still need the address of the first hop. * We still need the address of the first hop.
*/ */
if(skb->localroute)
rt = ip_rt_local(daddr, &optmem, &src);
else
rt = ip_rt_route(daddr, &optmem, &src); rt = ip_rt_route(daddr, &optmem, &src);
/* /*
* If the frame is from us and going off machine it MUST MUST MUST * If the frame is from us and going off machine it MUST MUST MUST
......
...@@ -503,6 +503,7 @@ static int ipx_create(struct socket *sock, int protocol) ...@@ -503,6 +503,7 @@ static int ipx_create(struct socket *sock, int protocol)
sk->type=sock->type; sk->type=sock->type;
sk->ipx_type=0; /* General user level IPX */ sk->ipx_type=0; /* General user level IPX */
sk->debug=0; sk->debug=0;
sk->localroute=0;
memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr)); memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr));
memset(&sk->ipx_source_addr,'\0',sizeof(sk->ipx_source_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, ...@@ -836,7 +837,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
int size; int size;
ipx_route *rt; ipx_route *rt;
if(flags) if(flags&~MSG_DONTROUTE)
return -EINVAL; return -EINVAL;
if(len<0) if(len<0)
return -EINVAL; return -EINVAL;
...@@ -882,7 +883,8 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock, ...@@ -882,7 +883,8 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
/* Find out where this has to go */ /* Find out where this has to go */
rt=ipxrtr_get_dev(sipx.sipx_network); 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; return -ENETUNREACH;
} }
...@@ -917,7 +919,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock, ...@@ -917,7 +919,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
skb->dev=rt->dev; skb->dev=rt->dev;
dev->hard_header(skb->data,skb->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, (rt->flags&IPX_RT_ROUTED)?rt->router_node:sipx.sipx_node,
NULL, NULL,
len+sizeof(ipx_packet), len+sizeof(ipx_packet),
......
...@@ -142,12 +142,12 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, ...@@ -142,12 +142,12 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
return(0); 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,
static int int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
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 sk_buff *skb;
struct device *dev=NULL; struct device *dev=NULL;
...@@ -159,35 +159,51 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -159,35 +159,51 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
" usin=%X, addr_len = %d)\n", sk, from, len, noblock, " usin=%X, addr_len = %d)\n", sk, from, len, noblock,
flags, usin, addr_len)); flags, usin, addr_len));
/* Check the flags. */ /*
if (flags) return(-EINVAL); * Check the flags. Only MSG_DONTROUTE is permitted.
if (len < 0) return(-EINVAL); */
if (flags&MSG_DONTROUTE)
return(-EINVAL);
if (len < 0)
return(-EINVAL);
err=verify_area(VERIFY_READ,from,len); err=verify_area(VERIFY_READ,from,len);
if(err) if(err)
return err; return err;
/* Get and verify the address. */ /*
if (usin) { * Get and verify the address.
if (addr_len < sizeof(sin)) return(-EINVAL); */
if (usin)
{
if (addr_len < sizeof(sin))
return(-EINVAL);
err=verify_area (VERIFY_READ, usin, sizeof (sin)); err=verify_area (VERIFY_READ, usin, sizeof (sin));
if(err) if(err)
return err; return err;
memcpy_fromfs(&sin, usin, sizeof(sin)); memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL); if (sin.sin_family && sin.sin_family != AF_INET)
} else { return(-EINVAL);
if (sk->state != TCP_ESTABLISHED) return(-EINVAL); }
else
{
if (sk->state != TCP_ESTABLISHED)
return(-EINVAL);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = sk->protocol; sin.sin_port = sk->protocol;
sin.sin_addr.s_addr = sk->daddr; sin.sin_addr.s_addr = sk->daddr;
} }
if (sin.sin_port == 0) sin.sin_port = sk->protocol; if (sin.sin_port == 0)
sin.sin_port = sk->protocol;
if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST) if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES; return -EACCES;
sk->inuse = 1; sk->inuse = 1;
skb = NULL; skb = NULL;
while (skb == NULL) { while (skb == NULL)
{
if(sk->err!=0) if(sk->err!=0)
{ {
err= -sk->err; err= -sk->err;
...@@ -199,7 +215,8 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -199,7 +215,8 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
skb = sk->prot->wmalloc(sk, skb = sk->prot->wmalloc(sk,
len + sk->prot->max_header, len + sk->prot->max_header,
0, GFP_KERNEL); 0, GFP_KERNEL);
if (skb == NULL) { if (skb == NULL)
{
int tmp; int tmp;
DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n")); DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
...@@ -220,31 +237,35 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -220,31 +237,35 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
} }
} }
skb->sk = sk; skb->sk = sk;
skb->free = 1; skb->free = 1;
skb->localroute = sk->localroute | (flags&MSG_DONTROUTE);
tmp = sk->prot->build_header(skb, sk->saddr, tmp = sk->prot->build_header(skb, sk->saddr,
sin.sin_addr.s_addr, &dev, sin.sin_addr.s_addr, &dev,
sk->protocol, sk->opt, skb->mem_len, sk->ip_tos,sk->ip_ttl); sk->protocol, sk->opt, skb->mem_len, sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n")); DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
kfree_skb(skb,FREE_WRITE); kfree_skb(skb,FREE_WRITE);
release_sock(sk); release_sock(sk);
return(tmp); 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) { if(sk->protocol==IPPROTO_RAW)
{
unsigned char *buff; unsigned char *buff;
struct iphdr *iph; struct iphdr *iph;
buff = skb->data; buff = skb->data;
buff += tmp; buff += tmp;
iph = (struct iphdr *)buff; iph = (struct iphdr *)buff;
iph->saddr = sk->saddr; iph->saddr = sk->saddr;
} }
...@@ -257,16 +278,14 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -257,16 +278,14 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
} }
static int static int raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
unsigned flags) unsigned flags)
{ {
return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0)); return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
} }
static void static void raw_close(struct sock *sk, int timeout)
raw_close(struct sock *sk, int timeout)
{ {
sk->inuse = 1; sk->inuse = 1;
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
......
...@@ -573,6 +573,42 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l ...@@ -573,6 +573,42 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l
return NULL; 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 * Backwards compatibility
*/ */
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* *
* Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -23,7 +25,8 @@ ...@@ -23,7 +25,8 @@
/* This is an entry in the IP routing table. */ /* This is an entry in the IP routing table. */
struct rtable { struct rtable
{
struct rtable *rt_next; struct rtable *rt_next;
unsigned long rt_dst; unsigned long rt_dst;
unsigned long rt_mask; unsigned long rt_mask;
...@@ -41,6 +44,7 @@ extern void ip_rt_flush(struct device *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, extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask,
unsigned long gw, struct device *dev); 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_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 rt_get_info(char * buffer, char **start, off_t offset, int length);
extern int ip_rt_ioctl(unsigned int cmd, void *arg); extern int ip_rt_ioctl(unsigned int cmd, void *arg);
......
...@@ -489,7 +489,8 @@ int sock_setsockopt(struct sock *sk, int level, int optname, ...@@ -489,7 +489,8 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
case SO_DEBUG: case SO_DEBUG:
sk->debug=val?1:0; sk->debug=val?1:0;
case SO_DONTROUTE: /* Still to be implemented */ case SO_DONTROUTE:
sk->localroute=val?1:0;
return(0); return(0);
case SO_BROADCAST: case SO_BROADCAST:
sk->broadcast=val?1:0; sk->broadcast=val?1:0;
...@@ -580,8 +581,8 @@ int sock_getsockopt(struct sock *sk, int level, int optname, ...@@ -580,8 +581,8 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
val = sk->debug; val = sk->debug;
break; break;
case SO_DONTROUTE: /* One last option to implement */ case SO_DONTROUTE:
val = 0; val = sk->localroute;
break; break;
case SO_BROADCAST: case SO_BROADCAST:
...@@ -852,6 +853,7 @@ inet_create(struct socket *sock, int protocol) ...@@ -852,6 +853,7 @@ inet_create(struct socket *sock, int protocol)
sk->send_head = NULL; sk->send_head = NULL;
sk->timeout = 0; sk->timeout = 0;
sk->broadcast = 0; sk->broadcast = 0;
sk->localroute = 0;
sk->timer.data = (unsigned long)sk; sk->timer.data = (unsigned long)sk;
sk->timer.function = &net_timer; sk->timer.function = &net_timer;
skb_queue_head_init(&sk->back_log); skb_queue_head_init(&sk->back_log);
......
...@@ -132,6 +132,7 @@ struct sock { ...@@ -132,6 +132,7 @@ struct sock {
unsigned short rcvbuf; unsigned short rcvbuf;
unsigned short sndbuf; unsigned short sndbuf;
unsigned short type; unsigned short type;
unsigned char localroute; /* Route locally only */
#ifdef CONFIG_IPX #ifdef CONFIG_IPX
ipx_address ipx_source_addr,ipx_dest_addr; ipx_address ipx_source_addr,ipx_dest_addr;
unsigned short ipx_type; unsigned short ipx_type;
......
...@@ -673,28 +673,35 @@ tcp_send_ack(unsigned long sequence, unsigned long ack, ...@@ -673,28 +673,35 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
* We need to grab some memory, and put together an ack, * We need to grab some memory, and put together an ack,
* and then put it into the queue to be sent. * and then put it into the queue to be sent.
*/ */
buff = sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC); buff = sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
if (buff == NULL) { if (buff == NULL)
{
/* Force it to send an ack. */ /* Force it to send an ack. */
sk->ack_backlog++; sk->ack_backlog++;
if (sk->timeout != TIME_WRITE && tcp_connected(sk->state)) { if (sk->timeout != TIME_WRITE && tcp_connected(sk->state))
{
reset_timer(sk, TIME_WRITE, 10); reset_timer(sk, TIME_WRITE, 10);
} }
if (inet_debug == DBG_SLIP) printk("\rtcp_ack: malloc failed\n"); if (inet_debug == DBG_SLIP)
printk("\rtcp_ack: malloc failed\n");
return; return;
} }
buff->len = sizeof(struct tcphdr); buff->len = sizeof(struct tcphdr);
buff->sk = sk; buff->sk = sk;
buff->localroute = sk->localroute;
t1 =(struct tcphdr *) buff->data; t1 =(struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /* Put in the IP header and routing stuff. */
tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev, tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl); IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
buff->free=1; buff->free=1;
sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n"); if (inet_debug == DBG_SLIP)
printk("\rtcp_ack: build_header failed\n");
return; return;
} }
buff->len += tmp; buff->len += tmp;
...@@ -703,12 +710,14 @@ tcp_send_ack(unsigned long sequence, unsigned long ack, ...@@ -703,12 +710,14 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
/* FIXME: */ /* FIXME: */
memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */ memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
/* swap the send and the receive. */ /*
* Swap the send and the receive.
*/
t1->dest = th->source; t1->dest = th->source;
t1->source = th->dest; t1->source = th->dest;
t1->seq = ntohl(sequence); t1->seq = ntohl(sequence);
t1->ack = 1; t1->ack = 1;
sk->window = tcp_select_window(sk);/*sk->prot->rspace(sk);*/ sk->window = tcp_select_window(sk);
t1->window = ntohs(sk->window); t1->window = ntohs(sk->window);
t1->res1 = 0; t1->res1 = 0;
t1->res2 = 0; t1->res2 = 0;
...@@ -717,7 +726,8 @@ tcp_send_ack(unsigned long sequence, unsigned long ack, ...@@ -717,7 +726,8 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
t1->syn = 0; t1->syn = 0;
t1->psh = 0; t1->psh = 0;
t1->fin = 0; t1->fin = 0;
if (ack == sk->acked_seq) { if (ack == sk->acked_seq)
{
sk->ack_backlog = 0; sk->ack_backlog = 0;
sk->bytes_rcv = 0; sk->bytes_rcv = 0;
sk->ack_timed = 0; sk->ack_timed = 0;
...@@ -766,8 +776,7 @@ tcp_build_header(struct tcphdr *th, struct sock *sk, int push) ...@@ -766,8 +776,7 @@ tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
* This routine copies from a user buffer into a socket, * This routine copies from a user buffer into a socket,
* and starts the transmit system. * and starts the transmit system.
*/ */
static int static int tcp_write(struct sock *sk, unsigned char *from,
tcp_write(struct sock *sk, unsigned char *from,
int len, int nonblock, unsigned flags) int len, int nonblock, unsigned flags)
{ {
int copied = 0; int copied = 0;
...@@ -784,69 +793,92 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -784,69 +793,92 @@ tcp_write(struct sock *sk, unsigned char *from,
sk->inuse=1; sk->inuse=1;
prot = sk->prot; prot = sk->prot;
while(len > 0) { while(len > 0)
if (sk->err) { /* Stop on an error */ {
if (sk->err)
{ /* Stop on an error */
release_sock(sk); release_sock(sk);
if (copied) return(copied); if (copied)
return(copied);
tmp = -sk->err; tmp = -sk->err;
sk->err = 0; sk->err = 0;
return(tmp); return(tmp);
} }
/* First thing we do is make sure that we are established. */ /*
if (sk->shutdown & SEND_SHUTDOWN) { * First thing we do is make sure that we are established.
*/
if (sk->shutdown & SEND_SHUTDOWN)
{
release_sock(sk); release_sock(sk);
sk->err = EPIPE; sk->err = EPIPE;
if (copied) return(copied); if (copied)
return(copied);
sk->err = 0; sk->err = 0;
return(-EPIPE); return(-EPIPE);
} }
/* Wait for a connection to finish. */ /*
* Wait for a connection to finish.
*/
while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) { while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
if (sk->err) { {
if (sk->err)
{
release_sock(sk); release_sock(sk);
if (copied) return(copied); if (copied)
return(copied);
tmp = -sk->err; tmp = -sk->err;
sk->err = 0; sk->err = 0;
return(tmp); return(tmp);
} }
if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) { if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
{
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 1\n")); DPRINTF((DBG_TCP, "tcp_write: return 1\n"));
if (copied) return(copied); if (copied)
return(copied);
if (sk->err) { if (sk->err)
{
tmp = -sk->err; tmp = -sk->err;
sk->err = 0; sk->err = 0;
return(tmp); return(tmp);
} }
if (sk->keepopen) { if (sk->keepopen)
{
send_sig(SIGPIPE, current, 0); send_sig(SIGPIPE, current, 0);
} }
return(-EPIPE); return(-EPIPE);
} }
if (nonblock || copied) { if (nonblock || copied)
{
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 2\n")); DPRINTF((DBG_TCP, "tcp_write: return 2\n"));
if (copied) return(copied); if (copied)
return(copied);
return(-EAGAIN); return(-EAGAIN);
} }
release_sock(sk); release_sock(sk);
cli(); cli();
if (sk->state != TCP_ESTABLISHED && if (sk->state != TCP_ESTABLISHED &&
sk->state != TCP_CLOSE_WAIT && sk->err == 0) { sk->state != TCP_CLOSE_WAIT && sk->err == 0)
{
interruptible_sleep_on(sk->sleep); interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked) { if (current->signal & ~current->blocked)
{
sti(); sti();
DPRINTF((DBG_TCP, "tcp_write: return 3\n")); DPRINTF((DBG_TCP, "tcp_write: return 3\n"));
if (copied) return(copied); if (copied)
return(copied);
return(-ERESTARTSYS); return(-ERESTARTSYS);
} }
} }
...@@ -854,7 +886,7 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -854,7 +886,7 @@ tcp_write(struct sock *sk, unsigned char *from,
sti(); sti();
} }
/* /*
* The following code can result in copy <= if sk->mss is ever * The following code can result in copy <= if sk->mss is ever
* decreased. It shouldn't be. sk->mss is min(sk->mtu, sk->max_window). * decreased. It shouldn't be. sk->mss is min(sk->mtu, sk->max_window).
* sk->mtu is constant once SYN processing is finished. I.e. we * sk->mtu is constant once SYN processing is finished. I.e. we
...@@ -866,8 +898,12 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -866,8 +898,12 @@ tcp_write(struct sock *sk, unsigned char *from,
* end has a window of 0, max_window and thus mss will both be 0. * end has a window of 0, max_window and thus mss will both be 0.
*/ */
/* Now we need to check if we have a half built packet. */ /*
if ((skb = tcp_dequeue_partial(sk)) != NULL) { * Now we need to check if we have a half built packet.
*/
if ((skb = tcp_dequeue_partial(sk)) != NULL)
{
int hdrlen; int hdrlen;
/* IP header + TCP header */ /* IP header + TCP header */
...@@ -875,10 +911,12 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -875,10 +911,12 @@ tcp_write(struct sock *sk, unsigned char *from,
+ sizeof(struct tcphdr); + sizeof(struct tcphdr);
/* Add more stuff to the end of skb->len */ /* Add more stuff to the end of skb->len */
if (!(flags & MSG_OOB)) { if (!(flags & MSG_OOB))
{
copy = min(sk->mss - (skb->len - hdrlen), len); copy = min(sk->mss - (skb->len - hdrlen), len);
/* FIXME: this is really a bug. */ /* FIXME: this is really a bug. */
if (copy <= 0) { if (copy <= 0)
{
printk("TCP: **bug**: \"copy\" <= 0!!\n"); printk("TCP: **bug**: \"copy\" <= 0!!\n");
copy = 0; copy = 0;
} }
...@@ -891,8 +929,7 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -891,8 +929,7 @@ tcp_write(struct sock *sk, unsigned char *from,
sk->write_seq += copy; sk->write_seq += copy;
} }
if ((skb->len - hdrlen) >= sk->mss || if ((skb->len - hdrlen) >= sk->mss ||
(flags & MSG_OOB) || (flags & MSG_OOB) || !sk->packets_out)
!sk->packets_out)
tcp_send_skb(sk, skb); tcp_send_skb(sk, skb);
else else
tcp_enqueue_partial(skb, sk); tcp_enqueue_partial(skb, sk);
...@@ -917,45 +954,71 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -917,45 +954,71 @@ tcp_write(struct sock *sk, unsigned char *from,
if (copy > len) if (copy > len)
copy = len; copy = len;
/* We should really check the window here also. */ /*
* We should really check the window here also.
*/
send_tmp = NULL; send_tmp = NULL;
if (copy < sk->mss && !(flags & MSG_OOB)) { if (copy < sk->mss && !(flags & MSG_OOB))
/* We will release the socket incase we sleep here. */ {
/*
* We will release the socket incase we sleep here.
*/
release_sock(sk); release_sock(sk);
/* NB: following must be mtu, because mss can be increased. /*
* mss is always <= mtu */ * NB: following must be mtu, because mss can be increased.
* mss is always <= mtu
*/
skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header, 0, GFP_KERNEL); skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header, 0, GFP_KERNEL);
sk->inuse = 1; sk->inuse = 1;
send_tmp = skb; send_tmp = skb;
} else { }
/* We will release the socket incase we sleep here. */ else
{
/*
* We will release the socket incase we sleep here.
*/
release_sock(sk); release_sock(sk);
skb = prot->wmalloc(sk, copy + prot->max_header , 0, GFP_KERNEL); skb = prot->wmalloc(sk, copy + prot->max_header , 0, GFP_KERNEL);
sk->inuse = 1; sk->inuse = 1;
} }
/* If we didn't get any memory, we need to sleep. */ /*
if (skb == NULL) { * If we didn't get any memory, we need to sleep.
if (nonblock /* || copied */) { */
if (skb == NULL)
{
if (nonblock /* || copied */)
{
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 4\n")); DPRINTF((DBG_TCP, "tcp_write: return 4\n"));
if (copied) return(copied); if (copied)
return(copied);
return(-EAGAIN); return(-EAGAIN);
} }
/* FIXME: here is another race condition. */ /*
* FIXME: here is another race condition.
*/
tmp = sk->wmem_alloc; tmp = sk->wmem_alloc;
release_sock(sk); release_sock(sk);
cli(); cli();
/* Again we will try to avoid it. */ /*
* Again we will try to avoid it.
*/
if (tmp <= sk->wmem_alloc && if (tmp <= sk->wmem_alloc &&
(sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT) (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
&& sk->err == 0) { && sk->err == 0)
{
interruptible_sleep_on(sk->sleep); interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked) { if (current->signal & ~current->blocked)
{
sti(); sti();
DPRINTF((DBG_TCP, "tcp_write: return 5\n")); DPRINTF((DBG_TCP, "tcp_write: return 5\n"));
if (copied) return(copied); if (copied)
return(copied);
return(-ERESTARTSYS); return(-ERESTARTSYS);
} }
} }
...@@ -967,6 +1030,7 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -967,6 +1030,7 @@ tcp_write(struct sock *sk, unsigned char *from,
skb->len = 0; skb->len = 0;
skb->sk = sk; skb->sk = sk;
skb->free = 0; skb->free = 0;
skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
buff = skb->data; buff = skb->data;
...@@ -974,13 +1038,16 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -974,13 +1038,16 @@ tcp_write(struct sock *sk, unsigned char *from,
* FIXME: we need to optimize this. * FIXME: we need to optimize this.
* Perhaps some hints here would be good. * Perhaps some hints here would be good.
*/ */
tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev, tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl); IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
if (tmp < 0 ) { if (tmp < 0 )
{
prot->wfree(sk, skb->mem_addr, skb->mem_len); prot->wfree(sk, skb->mem_addr, skb->mem_len);
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 6\n")); DPRINTF((DBG_TCP, "tcp_write: return 6\n"));
if (copied) return(copied); if (copied)
return(copied);
return(tmp); return(tmp);
} }
skb->len += tmp; skb->len += tmp;
...@@ -988,15 +1055,18 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -988,15 +1055,18 @@ tcp_write(struct sock *sk, unsigned char *from,
buff += tmp; buff += tmp;
skb->h.th =(struct tcphdr *) buff; skb->h.th =(struct tcphdr *) buff;
tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy); tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
if (tmp < 0) { if (tmp < 0)
{
prot->wfree(sk, skb->mem_addr, skb->mem_len); prot->wfree(sk, skb->mem_addr, skb->mem_len);
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 7\n")); DPRINTF((DBG_TCP, "tcp_write: return 7\n"));
if (copied) return(copied); if (copied)
return(copied);
return(tmp); return(tmp);
} }
if (flags & MSG_OOB) { if (flags & MSG_OOB)
{
((struct tcphdr *)buff)->urg = 1; ((struct tcphdr *)buff)->urg = 1;
((struct tcphdr *)buff)->urg_ptr = ntohs(copy); ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
} }
...@@ -1010,7 +1080,8 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -1010,7 +1080,8 @@ tcp_write(struct sock *sk, unsigned char *from,
skb->free = 0; skb->free = 0;
sk->write_seq += copy; sk->write_seq += copy;
if (send_tmp != NULL && sk->packets_out) { if (send_tmp != NULL && sk->packets_out)
{
tcp_enqueue_partial(send_tmp, sk); tcp_enqueue_partial(send_tmp, sk);
continue; continue;
} }
...@@ -1025,32 +1096,39 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -1025,32 +1096,39 @@ tcp_write(struct sock *sk, unsigned char *from,
* on my slow slip link - Alan * on my slow slip link - Alan
*/ */
/* Avoid possible race on send_tmp - c/o Johannes Stille */ /*
if(sk->partial && * Avoid possible race on send_tmp - c/o Johannes Stille
((!sk->packets_out) */
if(sk->partial && ((!sk->packets_out)
/* If not nagling we can send on the before case too.. */ /* If not nagling we can send on the before case too.. */
|| (sk->nonagle && before(sk->write_seq , sk->window_seq)) || (sk->nonagle && before(sk->write_seq , sk->window_seq))
)) ))
tcp_send_partial(sk); tcp_send_partial(sk);
/* -- */
release_sock(sk); release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 8\n")); DPRINTF((DBG_TCP, "tcp_write: return 8\n"));
return(copied); return(copied);
} }
static int static int tcp_sendto(struct sock *sk, unsigned char *from,
tcp_sendto(struct sock *sk, unsigned char *from,
int len, int nonblock, unsigned flags, int len, int nonblock, unsigned flags,
struct sockaddr_in *addr, int addr_len) struct sockaddr_in *addr, int addr_len)
{ {
struct sockaddr_in sin; struct sockaddr_in sin;
if (addr_len < sizeof(sin)) return(-EINVAL); if (flags & ~(MSG_OOB|MSG_DONTROUTE))
return -EINVAL;
if (addr_len < sizeof(sin))
return(-EINVAL);
memcpy_fromfs(&sin, addr, sizeof(sin)); memcpy_fromfs(&sin, addr, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL); if (sin.sin_family && sin.sin_family != AF_INET)
if (sin.sin_port != sk->dummy_th.dest) return(-EINVAL); return(-EINVAL);
if (sin.sin_addr.s_addr != sk->daddr) return(-EINVAL); if (sin.sin_port != sk->dummy_th.dest)
return(-EINVAL);
if (sin.sin_addr.s_addr != sk->daddr)
return(-EINVAL);
return(tcp_write(sk, from, len, nonblock, flags)); return(tcp_write(sk, from, len, nonblock, flags));
} }
...@@ -1064,7 +1142,8 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1064,7 +1142,8 @@ tcp_read_wakeup(struct sock *sk)
struct sk_buff *buff; struct sk_buff *buff;
DPRINTF((DBG_TCP, "in tcp read wakeup\n")); DPRINTF((DBG_TCP, "in tcp read wakeup\n"));
if (!sk->ack_backlog) return; if (!sk->ack_backlog)
return;
/* /*
* FIXME: we need to put code here to prevent this routine from * FIXME: we need to put code here to prevent this routine from
...@@ -1076,8 +1155,10 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1076,8 +1155,10 @@ tcp_read_wakeup(struct sock *sk)
* We need to grab some memory, and put together an ack, * We need to grab some memory, and put together an ack,
* and then put it into the queue to be sent. * and then put it into the queue to be sent.
*/ */
buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC); buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
if (buff == NULL) { if (buff == NULL)
{
/* Try again real soon. */ /* Try again real soon. */
reset_timer(sk, TIME_WRITE, 10); reset_timer(sk, TIME_WRITE, 10);
return; return;
...@@ -1085,11 +1166,16 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1085,11 +1166,16 @@ tcp_read_wakeup(struct sock *sk)
buff->len = sizeof(struct tcphdr); buff->len = sizeof(struct tcphdr);
buff->sk = sk; buff->sk = sk;
buff->localroute = sk->localroute;
/*
* Put in the IP header and routing stuff.
*/
/* Put in the IP header and routing stuff. */
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev, tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl); IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
buff->free=1; buff->free=1;
sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
return; return;
...@@ -1125,8 +1211,8 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1125,8 +1211,8 @@ tcp_read_wakeup(struct sock *sk)
* It should consider sending an ACK to let the * It should consider sending an ACK to let the
* other end know we now have a bigger window. * other end know we now have a bigger window.
*/ */
static void
cleanup_rbuf(struct sock *sk) static void cleanup_rbuf(struct sock *sk)
{ {
unsigned long flags; unsigned long flags;
int left; int left;
...@@ -1144,6 +1230,7 @@ cleanup_rbuf(struct sock *sk) ...@@ -1144,6 +1230,7 @@ cleanup_rbuf(struct sock *sk)
* We have to loop through all the buffer headers, * We have to loop through all the buffer headers,
* and try to free up all the space we can. * and try to free up all the space we can.
*/ */
while((skb=skb_peek(&sk->receive_queue)) != NULL) while((skb=skb_peek(&sk->receive_queue)) != NULL)
{ {
if (!skb->used) if (!skb->used)
...@@ -1161,6 +1248,7 @@ cleanup_rbuf(struct sock *sk) ...@@ -1161,6 +1248,7 @@ cleanup_rbuf(struct sock *sk)
* in the window, and the amount of space is bigger than * in the window, and the amount of space is bigger than
* TCP_WINDOW_DIFF. * TCP_WINDOW_DIFF.
*/ */
DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n", DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n",
sk->window - sk->bytes_rcv, sk->prot->rspace(sk))); sk->window - sk->bytes_rcv, sk->prot->rspace(sk)));
...@@ -1180,7 +1268,7 @@ cleanup_rbuf(struct sock *sk) ...@@ -1180,7 +1268,7 @@ cleanup_rbuf(struct sock *sk)
* the user reads some more. * the user reads some more.
*/ */
sk->ack_backlog++; sk->ack_backlog++;
/* /*
* It's unclear whether to use sk->mtu or sk->mss here. They differ only * It's unclear whether to use sk->mtu or sk->mss here. They differ only
* if the other end is offering a window smaller than the agreed on MSS * if the other end is offering a window smaller than the agreed on MSS
* (called sk->mtu here). In theory there's no connection between send * (called sk->mtu here). In theory there's no connection between send
...@@ -1188,15 +1276,21 @@ cleanup_rbuf(struct sock *sk) ...@@ -1188,15 +1276,21 @@ cleanup_rbuf(struct sock *sk)
* small packets. For the moment I'm using the hack of reducing the mss * small packets. For the moment I'm using the hack of reducing the mss
* only on the send side, so I'm putting mtu here. * only on the send side, so I'm putting mtu here.
*/ */
if ((sk->prot->rspace(sk) > (sk->window - sk->bytes_rcv + sk->mtu))) {
if ((sk->prot->rspace(sk) > (sk->window - sk->bytes_rcv + sk->mtu)))
{
/* Send an ack right now. */ /* Send an ack right now. */
tcp_read_wakeup(sk); tcp_read_wakeup(sk);
} else { }
else
{
/* Force it to send an ack soon. */ /* Force it to send an ack soon. */
int was_active = del_timer(&sk->timer); int was_active = del_timer(&sk->timer);
if (!was_active || TCP_ACK_TIME < sk->timer.expires) { if (!was_active || TCP_ACK_TIME < sk->timer.expires)
{
reset_timer(sk, TIME_WRITE, TCP_ACK_TIME); reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
} else }
else
add_timer(&sk->timer); add_timer(&sk->timer);
} }
} }
...@@ -1407,8 +1501,8 @@ static int tcp_read(struct sock *sk, unsigned char *to, ...@@ -1407,8 +1501,8 @@ static int tcp_read(struct sock *sk, unsigned char *to,
* Send a FIN without closing the connection. * Send a FIN without closing the connection.
* Not called at interrupt time. * Not called at interrupt time.
*/ */
void
tcp_shutdown(struct sock *sk, int how) void tcp_shutdown(struct sock *sk, int how)
{ {
struct sk_buff *buff; struct sk_buff *buff;
struct tcphdr *t1, *th; struct tcphdr *t1, *th;
...@@ -1423,12 +1517,21 @@ tcp_shutdown(struct sock *sk, int how) ...@@ -1423,12 +1517,21 @@ tcp_shutdown(struct sock *sk, int how)
* Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92. * Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
* Most of this is guesswork, so maybe it will work... * Most of this is guesswork, so maybe it will work...
*/ */
/* If we've already sent a FIN, return. */
if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) return; /*
if (!(how & SEND_SHUTDOWN)) return; * If we've already sent a FIN, return.
*/
if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2)
return;
if (!(how & SEND_SHUTDOWN))
return;
sk->inuse = 1; sk->inuse = 1;
/* Clear out any half completed packets. */ /*
* Clear out any half completed packets.
*/
if (sk->partial) if (sk->partial)
tcp_send_partial(sk); tcp_send_partial(sk);
...@@ -1436,20 +1539,28 @@ tcp_shutdown(struct sock *sk, int how) ...@@ -1436,20 +1539,28 @@ tcp_shutdown(struct sock *sk, int how)
th =(struct tcphdr *)&sk->dummy_th; th =(struct tcphdr *)&sk->dummy_th;
release_sock(sk); /* incase the malloc sleeps. */ release_sock(sk); /* incase the malloc sleeps. */
buff = prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL); buff = prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
if (buff == NULL) return; if (buff == NULL)
return;
sk->inuse = 1; sk->inuse = 1;
DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff)); DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff));
buff->sk = sk; buff->sk = sk;
buff->len = sizeof(*t1); buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
t1 =(struct tcphdr *) buff->data; t1 =(struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /*
* Put in the IP header and routing stuff.
*/
tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev, tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, IPPROTO_TCP, sk->opt,
sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl); sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
/* Finish anyway, treat this as a send that got lost. */ {
/*
* Finish anyway, treat this as a send that got lost.
*/
buff->free=1; buff->free=1;
prot->wfree(sk,buff->mem_addr, buff->mem_len); prot->wfree(sk,buff->mem_addr, buff->mem_len);
if(sk->state==TCP_ESTABLISHED) if(sk->state==TCP_ESTABLISHED)
...@@ -1480,20 +1591,27 @@ tcp_shutdown(struct sock *sk, int how) ...@@ -1480,20 +1591,27 @@ tcp_shutdown(struct sock *sk, int how)
* Can't just queue this up. * Can't just queue this up.
* It should go at the end of the write queue. * It should go at the end of the write queue.
*/ */
if (skb_peek(&sk->write_queue) != NULL) {
if (skb_peek(&sk->write_queue) != NULL)
{
buff->free=0; buff->free=0;
if (buff->next != NULL) { if (buff->next != NULL)
{
printk("tcp_shutdown: next != NULL\n"); printk("tcp_shutdown: next != NULL\n");
skb_unlink(buff); skb_unlink(buff);
} }
skb_queue_tail(&sk->write_queue, buff); skb_queue_tail(&sk->write_queue, buff);
} else { }
else
{
sk->sent_seq = sk->write_seq; sk->sent_seq = sk->write_seq;
sk->prot->queue_xmit(sk, dev, buff, 0); sk->prot->queue_xmit(sk, dev, buff, 0);
} }
if (sk->state == TCP_ESTABLISHED) sk->state = TCP_FIN_WAIT1; if (sk->state == TCP_ESTABLISHED)
else sk->state = TCP_FIN_WAIT2; sk->state = TCP_FIN_WAIT1;
else
sk->state = TCP_FIN_WAIT2;
release_sock(sk); release_sock(sk);
} }
...@@ -1536,9 +1654,11 @@ tcp_recvfrom(struct sock *sk, unsigned char *to, ...@@ -1536,9 +1654,11 @@ tcp_recvfrom(struct sock *sk, unsigned char *to,
} }
/* This routine will send an RST to the other tcp. */ /*
static void * This routine will send an RST to the other tcp.
tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, */
static void tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl) struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl)
{ {
struct sk_buff *buff; struct sk_buff *buff;
...@@ -1546,10 +1666,11 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, ...@@ -1546,10 +1666,11 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
int tmp; int tmp;
struct device *ndev=NULL; struct device *ndev=NULL;
/* /*
* We need to grab some memory, and put together an RST, * We need to grab some memory, and put together an RST,
* and then put it into the queue to be sent. * and then put it into the queue to be sent.
*/ */
buff = prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC); buff = prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
if (buff == NULL) if (buff == NULL)
return; return;
...@@ -1558,22 +1679,31 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, ...@@ -1558,22 +1679,31 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
buff->len = sizeof(*t1); buff->len = sizeof(*t1);
buff->sk = NULL; buff->sk = NULL;
buff->dev = dev; buff->dev = dev;
buff->localroute = 0;
t1 =(struct tcphdr *) buff->data; t1 =(struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /*
* Put in the IP header and routing stuff.
*/
tmp = prot->build_header(buff, saddr, daddr, &ndev, IPPROTO_TCP, opt, tmp = prot->build_header(buff, saddr, daddr, &ndev, IPPROTO_TCP, opt,
sizeof(struct tcphdr),tos,ttl); sizeof(struct tcphdr),tos,ttl);
if (tmp < 0) { if (tmp < 0)
{
buff->free = 1; buff->free = 1;
prot->wfree(NULL, buff->mem_addr, buff->mem_len); prot->wfree(NULL, buff->mem_addr, buff->mem_len);
return; return;
} }
t1 =(struct tcphdr *)((char *)t1 +tmp); t1 =(struct tcphdr *)((char *)t1 +tmp);
buff->len += tmp; buff->len += tmp;
memcpy(t1, th, sizeof(*t1)); memcpy(t1, th, sizeof(*t1));
/* Swap the send and the receive. */ /*
* Swap the send and the receive.
*/
t1->dest = th->source; t1->dest = th->source;
t1->source = th->dest; t1->source = th->dest;
t1->rst = 1; t1->rst = 1;
...@@ -1755,6 +1885,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -1755,6 +1885,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk->pair = NULL; newsk->pair = NULL;
newsk->wmem_alloc = 0; newsk->wmem_alloc = 0;
newsk->rmem_alloc = 0; newsk->rmem_alloc = 0;
newsk->localroute = sk->localroute;
newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF; newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF;
...@@ -1830,6 +1961,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -1830,6 +1961,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
buff->len = sizeof(struct tcphdr)+4; buff->len = sizeof(struct tcphdr)+4;
buff->sk = newsk; buff->sk = newsk;
buff->localroute = newsk->localroute;
t1 =(struct tcphdr *) buff->data; t1 =(struct tcphdr *) buff->data;
...@@ -1896,8 +2028,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -1896,8 +2028,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
} }
static void static void tcp_close(struct sock *sk, int timeout)
tcp_close(struct sock *sk, int timeout)
{ {
struct sk_buff *buff; struct sk_buff *buff;
int need_reset = 0; int need_reset = 0;
...@@ -1918,7 +2049,10 @@ tcp_close(struct sock *sk, int timeout) ...@@ -1918,7 +2049,10 @@ tcp_close(struct sock *sk, int timeout)
if (!sk->dead) if (!sk->dead)
sk->state_change(sk); sk->state_change(sk);
/* We need to flush the recv. buffs. */ /*
* We need to flush the recv. buffs.
*/
if (skb_peek(&sk->receive_queue) != NULL) if (skb_peek(&sk->receive_queue) != NULL)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1934,26 +2068,34 @@ tcp_close(struct sock *sk, int timeout) ...@@ -1934,26 +2068,34 @@ tcp_close(struct sock *sk, int timeout)
printk("Cleaned.\n"); printk("Cleaned.\n");
} }
/* Get rid off any half-completed packets. */ /*
if (sk->partial) { * Get rid off any half-completed packets.
*/
if (sk->partial)
{
tcp_send_partial(sk); tcp_send_partial(sk);
} }
switch(sk->state) { switch(sk->state)
{
case TCP_FIN_WAIT1: case TCP_FIN_WAIT1:
case TCP_FIN_WAIT2: case TCP_FIN_WAIT2:
case TCP_LAST_ACK: case TCP_LAST_ACK:
/* start a timer. */ /*
/* original code was 4 * sk->rtt. In converting to the * Start a timer.
* original code was 4 * sk->rtt. In converting to the
* new rtt representation, we can't quite use that. * new rtt representation, we can't quite use that.
* it seems to make most sense to use the backed off value * it seems to make most sense to use the backed off value
*/ */
reset_timer(sk, TIME_CLOSE, 4 * sk->rto); reset_timer(sk, TIME_CLOSE, 4 * sk->rto);
if (timeout) tcp_time_wait(sk); if (timeout)
tcp_time_wait(sk);
release_sock(sk); release_sock(sk);
return; /* break causes a double release - messy */ return; /* break causes a double release - messy */
case TCP_TIME_WAIT: case TCP_TIME_WAIT:
if (timeout) { if (timeout)
{
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
} }
release_sock(sk); release_sock(sk);
...@@ -1972,7 +2114,8 @@ tcp_close(struct sock *sk, int timeout) ...@@ -1972,7 +2114,8 @@ tcp_close(struct sock *sk, int timeout)
prot =(struct proto *)sk->prot; prot =(struct proto *)sk->prot;
th =(struct tcphdr *)&sk->dummy_th; th =(struct tcphdr *)&sk->dummy_th;
buff = prot->wmalloc(sk, MAX_FIN_SIZE, 1, GFP_ATOMIC); buff = prot->wmalloc(sk, MAX_FIN_SIZE, 1, GFP_ATOMIC);
if (buff == NULL) { if (buff == NULL)
{
/* This will force it to try again later. */ /* This will force it to try again later. */
/* Or it would have if someone released the socket /* Or it would have if someone released the socket
first. Anyway it might work now */ first. Anyway it might work now */
...@@ -1985,13 +2128,17 @@ tcp_close(struct sock *sk, int timeout) ...@@ -1985,13 +2128,17 @@ tcp_close(struct sock *sk, int timeout)
buff->sk = sk; buff->sk = sk;
buff->free = 1; buff->free = 1;
buff->len = sizeof(*t1); buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
t1 =(struct tcphdr *) buff->data; t1 =(struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /*
* Put in the IP header and routing stuff.
*/
tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev, tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, IPPROTO_TCP, sk->opt,
sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl); sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
kfree_skb(buff,FREE_WRITE); kfree_skb(buff,FREE_WRITE);
if(sk->state==TCP_ESTABLISHED) if(sk->state==TCP_ESTABLISHED)
sk->state=TCP_FIN_WAIT1; sk->state=TCP_FIN_WAIT1;
...@@ -2015,7 +2162,10 @@ tcp_close(struct sock *sk, int timeout) ...@@ -2015,7 +2162,10 @@ tcp_close(struct sock *sk, int timeout)
buff->h.seq = sk->write_seq; buff->h.seq = sk->write_seq;
t1->ack = 1; t1->ack = 1;
/* Ack everything immediately from now on. */ /*
* Ack everything immediately from now on.
*/
sk->delay_acks = 0; sk->delay_acks = 0;
t1->ack_seq = ntohl(sk->acked_seq); t1->ack_seq = ntohl(sk->acked_seq);
t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/); t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
...@@ -2026,21 +2176,28 @@ tcp_close(struct sock *sk, int timeout) ...@@ -2026,21 +2176,28 @@ tcp_close(struct sock *sk, int timeout)
tcp_statistics.TcpOutSegs++; tcp_statistics.TcpOutSegs++;
if (skb_peek(&sk->write_queue) == NULL) { if (skb_peek(&sk->write_queue) == NULL)
{
sk->sent_seq = sk->write_seq; sk->sent_seq = sk->write_seq;
prot->queue_xmit(sk, dev, buff, 0); prot->queue_xmit(sk, dev, buff, 0);
} else { }
else
{
reset_timer(sk, TIME_WRITE, sk->rto); reset_timer(sk, TIME_WRITE, sk->rto);
if (buff->next != NULL) { if (buff->next != NULL)
{
printk("tcp_close: next != NULL\n"); printk("tcp_close: next != NULL\n");
skb_unlink(buff); skb_unlink(buff);
} }
skb_queue_tail(&sk->write_queue, buff); skb_queue_tail(&sk->write_queue, buff);
} }
if (sk->state == TCP_CLOSE_WAIT) { if (sk->state == TCP_CLOSE_WAIT)
{
sk->state = TCP_FIN_WAIT2; sk->state = TCP_FIN_WAIT2;
} else { }
else
{
sk->state = TCP_FIN_WAIT1; sk->state = TCP_FIN_WAIT1;
} }
} }
...@@ -2762,19 +2919,23 @@ static inline int tcp_urg(struct sock *sk, struct tcphdr *th, ...@@ -2762,19 +2919,23 @@ static inline int tcp_urg(struct sock *sk, struct tcphdr *th,
} }
/* This deals with incoming fins. 'Linus at 9 O'clock' 8-) */ /*
static int * This deals with incoming fins. 'Linus at 9 O'clock' 8-)
tcp_fin(struct sock *sk, struct tcphdr *th, */
static int tcp_fin(struct sock *sk, struct tcphdr *th,
unsigned long saddr, struct device *dev) unsigned long saddr, struct device *dev)
{ {
DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n", DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n",
sk, th, saddr, dev)); sk, th, saddr, dev));
if (!sk->dead) { if (!sk->dead)
{
sk->state_change(sk); sk->state_change(sk);
} }
switch(sk->state) { switch(sk->state)
{
case TCP_SYN_RECV: case TCP_SYN_RECV:
case TCP_SYN_SENT: case TCP_SYN_SENT:
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
...@@ -2783,7 +2944,8 @@ tcp_fin(struct sock *sk, struct tcphdr *th, ...@@ -2783,7 +2944,8 @@ tcp_fin(struct sock *sk, struct tcphdr *th,
sk->fin_seq = th->seq+1; sk->fin_seq = th->seq+1;
tcp_statistics.TcpCurrEstab--; tcp_statistics.TcpCurrEstab--;
sk->state = TCP_CLOSE_WAIT; sk->state = TCP_CLOSE_WAIT;
if (th->rst) sk->shutdown = SHUTDOWN_MASK; if (th->rst)
sk->shutdown = SHUTDOWN_MASK;
break; break;
case TCP_CLOSE_WAIT: case TCP_CLOSE_WAIT:
...@@ -2861,9 +3023,11 @@ tcp_accept(struct sock *sk, int flags) ...@@ -2861,9 +3023,11 @@ tcp_accept(struct sock *sk, int flags)
} }
/* This will initiate an outgoing connection. */ /*
static int * This will initiate an outgoing connection.
tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) */
static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
{ {
struct sk_buff *buff; struct sk_buff *buff;
struct sockaddr_in sin; struct sockaddr_in sin;
...@@ -2873,8 +3037,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2873,8 +3037,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
struct tcphdr *t1; struct tcphdr *t1;
int err; int err;
if (sk->state != TCP_CLOSE) return(-EISCONN); if (sk->state != TCP_CLOSE)
if (addr_len < 8) return(-EINVAL); return(-EISCONN);
if (addr_len < 8)
return(-EINVAL);
err=verify_area(VERIFY_READ, usin, addr_len); err=verify_area(VERIFY_READ, usin, addr_len);
if(err) if(err)
...@@ -2882,17 +3048,32 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2882,17 +3048,32 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
memcpy_fromfs(&sin,usin, min(sizeof(sin), addr_len)); memcpy_fromfs(&sin,usin, min(sizeof(sin), addr_len));
if (sin.sin_family && sin.sin_family != AF_INET) return(-EAFNOSUPPORT); if (sin.sin_family && sin.sin_family != AF_INET)
return(-EAFNOSUPPORT);
DPRINTF((DBG_TCP, "TCP connect daddr=%s\n", in_ntoa(sin.sin_addr.s_addr))); DPRINTF((DBG_TCP, "TCP connect daddr=%s\n", in_ntoa(sin.sin_addr.s_addr)));
/* Don't want a TCP connection going to a broadcast address */ /*
if (ip_chk_addr(sin.sin_addr.s_addr) == IS_BROADCAST) { * connect() to INADDR_ANY means loopback (BSD'ism).
*/
if(sin.sin_addr.s_addr==INADDR_ANY)
sin.sin_addr.s_addr=ip_my_addr();
/*
* Don't want a TCP connection going to a broadcast address
*/
if (ip_chk_addr(sin.sin_addr.s_addr) == IS_BROADCAST)
{
DPRINTF((DBG_TCP, "TCP connection to broadcast address not allowed\n")); DPRINTF((DBG_TCP, "TCP connection to broadcast address not allowed\n"));
return(-ENETUNREACH); return(-ENETUNREACH);
} }
/* Connect back to the same socket: Blows up so disallow it */ /*
* Connect back to the same socket: Blows up so disallow it
*/
if(sk->saddr == sin.sin_addr.s_addr && sk->num==ntohs(sin.sin_port)) if(sk->saddr == sin.sin_addr.s_addr && sk->num==ntohs(sin.sin_port))
return -EBUSY; return -EBUSY;
...@@ -2906,24 +3087,35 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2906,24 +3087,35 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
release_sock(sk); release_sock(sk);
buff = sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL); buff = sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
if (buff == NULL) { if (buff == NULL)
{
return(-ENOMEM); return(-ENOMEM);
} }
sk->inuse = 1; sk->inuse = 1;
buff->len = 24; buff->len = 24;
buff->sk = sk; buff->sk = sk;
buff->free = 1; buff->free = 1;
buff->localroute = sk->localroute;
t1 = (struct tcphdr *) buff->data; t1 = (struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /*
/* We need to build the routing stuff fromt the things saved in skb. */ * Put in the IP header and routing stuff.
*/
/*
* We need to build the routing stuff fromt the things saved in skb.
*/
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev, tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl); IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
release_sock(sk); release_sock(sk);
return(-ENETUNREACH); return(-ENETUNREACH);
} }
buff->len += tmp; buff->len += tmp;
t1 = (struct tcphdr *)((char *)t1 +tmp); t1 = (struct tcphdr *)((char *)t1 +tmp);
...@@ -2941,11 +3133,12 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2941,11 +3133,12 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
t1->syn = 1; t1->syn = 1;
t1->urg_ptr = 0; t1->urg_ptr = 0;
t1->doff = 6; t1->doff = 6;
/* use 512 or whatever user asked for */
/* use 512 or whatever user asked for */
if (sk->user_mss) if (sk->user_mss)
sk->mtu = sk->user_mss; sk->mtu = sk->user_mss;
else { else
{
#ifdef SUBNETSARELOCAL #ifdef SUBNETSARELOCAL
if ((sk->saddr ^ sk->daddr) & default_mask(sk->saddr)) if ((sk->saddr ^ sk->daddr) & default_mask(sk->saddr))
#else #else
...@@ -2955,10 +3148,16 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2955,10 +3148,16 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
else else
sk->mtu = MAX_WINDOW; sk->mtu = MAX_WINDOW;
} }
/* but not bigger than device MTU */ /*
* but not bigger than device MTU
*/
sk->mtu = min(sk->mtu, dev->mtu - HEADER_SIZE); sk->mtu = min(sk->mtu, dev->mtu - HEADER_SIZE);
/* Put in the TCP options to say MTU. */ /*
* Put in the TCP options to say MTU.
*/
ptr = (unsigned char *)(t1+1); ptr = (unsigned char *)(t1+1);
ptr[0] = 2; ptr[0] = 2;
ptr[1] = 4; ptr[1] = 4;
...@@ -2967,7 +3166,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -2967,7 +3166,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
tcp_send_check(t1, sk->saddr, sk->daddr, tcp_send_check(t1, sk->saddr, sk->daddr,
sizeof(struct tcphdr) + 4, sk); sizeof(struct tcphdr) + 4, sk);
/* This must go first otherwise a really quick response will get reset. */ /*
* This must go first otherwise a really quick response will get reset.
*/
sk->state = TCP_SYN_SENT; sk->state = TCP_SYN_SENT;
sk->rtt = TCP_CONNECT_TIME; sk->rtt = TCP_CONNECT_TIME;
reset_timer(sk, TIME_WRITE, TCP_CONNECT_TIME); /* Timer for repeating the SYN until an answer */ reset_timer(sk, TIME_WRITE, TCP_CONNECT_TIME); /* Timer for repeating the SYN until an answer */
...@@ -3454,8 +3656,8 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n"); ...@@ -3454,8 +3656,8 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
* This routine sends a packet with an out of date sequence * This routine sends a packet with an out of date sequence
* number. It assumes the other end will try to ack it. * number. It assumes the other end will try to ack it.
*/ */
static void
tcp_write_wakeup(struct sock *sk) static void tcp_write_wakeup(struct sock *sk)
{ {
struct sk_buff *buff; struct sk_buff *buff;
struct tcphdr *t1; struct tcphdr *t1;
...@@ -3470,18 +3672,22 @@ tcp_write_wakeup(struct sock *sk) ...@@ -3470,18 +3672,22 @@ tcp_write_wakeup(struct sock *sk)
return; return;
buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC); buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
if (buff == NULL) return; if (buff == NULL)
return;
buff->len = sizeof(struct tcphdr); buff->len = sizeof(struct tcphdr);
buff->free = 1; buff->free = 1;
buff->sk = sk; buff->sk = sk;
buff->localroute = sk->localroute;
DPRINTF((DBG_TCP, "in tcp_write_wakeup\n")); DPRINTF((DBG_TCP, "in tcp_write_wakeup\n"));
t1 = (struct tcphdr *) buff->data; t1 = (struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */ /* Put in the IP header and routing stuff. */
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev, tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl); IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) { if (tmp < 0)
{
sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
return; return;
} }
......
...@@ -250,7 +250,7 @@ static void udp_send_check(struct udphdr *uh, unsigned long saddr, ...@@ -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, 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 sk_buff *skb;
struct device *dev; struct device *dev;
...@@ -281,6 +281,7 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin, ...@@ -281,6 +281,7 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin,
skb->sk = NULL; /* to avoid changing sk->saddr */ skb->sk = NULL; /* to avoid changing sk->saddr */
skb->free = 1; skb->free = 1;
skb->localroute = sk->localroute|(rt&MSG_DONTROUTE);
/* /*
* Now build the IP and MAC header. * 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 ...@@ -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 * Check the flags. We support no flags for UDP sending
*/ */
if (flags) if (flags&~MSG_DONTROUTE)
return(-EINVAL); return(-EINVAL);
if (len < 0) if (len < 0)
return(-EINVAL); return(-EINVAL);
...@@ -400,7 +401,7 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock ...@@ -400,7 +401,7 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
sk->inuse = 1; sk->inuse = 1;
/* Send the packet. */ /* 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. */ /* The datagram has been sent off. Release the socket. */
release_sock(sk); release_sock(sk);
...@@ -614,6 +615,8 @@ udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -614,6 +615,8 @@ udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
memcpy_fromfs(&sin, usin, sizeof(sin)); memcpy_fromfs(&sin, usin, sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET) if (sin.sin_family && sin.sin_family != AF_INET)
return(-EAFNOSUPPORT); 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) if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
return -EACCES; /* Must turn broadcast on first */ return -EACCES; /* Must turn broadcast on first */
......
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