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,6 +284,9 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
if (*dev == NULL)
{
if(skb->localroute)
rt = ip_rt_local(daddr, &optmem, &src);
else
rt = ip_rt_route(daddr, &optmem, &src);
if (rt == NULL)
{
......@@ -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.
*/
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
......
......@@ -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,12 +142,12 @@ 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;
......@@ -159,35 +159,51 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
" 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);
/*
* 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;
/* Get and verify the address. */
if (usin) {
if (addr_len < sizeof(sin)) return(-EINVAL);
/*
* 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);
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 (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) {
while (skb == NULL)
{
if(sk->err!=0)
{
err= -sk->err;
......@@ -199,7 +215,8 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
skb = sk->prot->wmalloc(sk,
len + sk->prot->max_header,
0, GFP_KERNEL);
if (skb == NULL) {
if (skb == NULL)
{
int tmp;
DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
......@@ -220,31 +237,35 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
}
}
skb->sk = sk;
skb->free = 1;
skb->localroute = sk->localroute | (flags&MSG_DONTROUTE);
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) {
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);
/* 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;
struct iphdr *iph;
buff = skb->data;
buff += tmp;
iph = (struct iphdr *)buff;
iph->saddr = sk->saddr;
}
......@@ -257,16 +278,14 @@ raw_sendto(struct sock *sk, unsigned char *from, int 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));
}
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;
......
......@@ -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,7 +25,8 @@
/* This is an entry in the IP routing table. */
struct rtable {
struct rtable
{
struct rtable *rt_next;
unsigned long rt_dst;
unsigned long rt_mask;
......@@ -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;
......
......@@ -673,28 +673,35 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
* We need to grab some memory, and put together an ack,
* and then put it into the queue to be sent.
*/
buff = sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
if (buff == NULL) {
if (buff == NULL)
{
/* Force it to send an ack. */
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);
}
if (inet_debug == DBG_SLIP) printk("\rtcp_ack: malloc failed\n");
if (inet_debug == DBG_SLIP)
printk("\rtcp_ack: malloc failed\n");
return;
}
buff->len = sizeof(struct tcphdr);
buff->sk = sk;
buff->localroute = sk->localroute;
t1 =(struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */
tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) {
if (tmp < 0)
{
buff->free=1;
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;
}
buff->len += tmp;
......@@ -703,12 +710,14 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
/* FIXME: */
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->source = th->dest;
t1->seq = ntohl(sequence);
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->res1 = 0;
t1->res2 = 0;
......@@ -717,7 +726,8 @@ tcp_send_ack(unsigned long sequence, unsigned long ack,
t1->syn = 0;
t1->psh = 0;
t1->fin = 0;
if (ack == sk->acked_seq) {
if (ack == sk->acked_seq)
{
sk->ack_backlog = 0;
sk->bytes_rcv = 0;
sk->ack_timed = 0;
......@@ -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,
* and starts the transmit system.
*/
static int
tcp_write(struct sock *sk, unsigned char *from,
static int tcp_write(struct sock *sk, unsigned char *from,
int len, int nonblock, unsigned flags)
{
int copied = 0;
......@@ -784,69 +793,92 @@ tcp_write(struct sock *sk, unsigned char *from,
sk->inuse=1;
prot = sk->prot;
while(len > 0) {
if (sk->err) { /* Stop on an error */
while(len > 0)
{
if (sk->err)
{ /* Stop on an error */
release_sock(sk);
if (copied) return(copied);
if (copied)
return(copied);
tmp = -sk->err;
sk->err = 0;
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);
sk->err = EPIPE;
if (copied) return(copied);
if (copied)
return(copied);
sk->err = 0;
return(-EPIPE);
}
/* Wait for a connection to finish. */
/*
* Wait for a connection to finish.
*/
while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) {
if (sk->err) {
while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
{
if (sk->err)
{
release_sock(sk);
if (copied) return(copied);
if (copied)
return(copied);
tmp = -sk->err;
sk->err = 0;
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);
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;
sk->err = 0;
return(tmp);
}
if (sk->keepopen) {
if (sk->keepopen)
{
send_sig(SIGPIPE, current, 0);
}
return(-EPIPE);
}
if (nonblock || copied) {
if (nonblock || copied)
{
release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 2\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(-EAGAIN);
}
release_sock(sk);
cli();
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);
if (current->signal & ~current->blocked) {
if (current->signal & ~current->blocked)
{
sti();
DPRINTF((DBG_TCP, "tcp_write: return 3\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(-ERESTARTSYS);
}
}
......@@ -854,7 +886,7 @@ tcp_write(struct sock *sk, unsigned char *from,
sti();
}
/*
/*
* 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).
* sk->mtu is constant once SYN processing is finished. I.e. we
......@@ -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.
*/
/* 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;
/* IP header + TCP header */
......@@ -875,10 +911,12 @@ tcp_write(struct sock *sk, unsigned char *from,
+ sizeof(struct tcphdr);
/* 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);
/* FIXME: this is really a bug. */
if (copy <= 0) {
if (copy <= 0)
{
printk("TCP: **bug**: \"copy\" <= 0!!\n");
copy = 0;
}
......@@ -891,8 +929,7 @@ tcp_write(struct sock *sk, unsigned char *from,
sk->write_seq += copy;
}
if ((skb->len - hdrlen) >= sk->mss ||
(flags & MSG_OOB) ||
!sk->packets_out)
(flags & MSG_OOB) || !sk->packets_out)
tcp_send_skb(sk, skb);
else
tcp_enqueue_partial(skb, sk);
......@@ -917,45 +954,71 @@ tcp_write(struct sock *sk, unsigned char *from,
if (copy > len)
copy = len;
/* We should really check the window here also. */
/*
* We should really check the window here also.
*/
send_tmp = NULL;
if (copy < sk->mss && !(flags & MSG_OOB)) {
/* We will release the socket incase we sleep here. */
if (copy < sk->mss && !(flags & MSG_OOB))
{
/*
* We will release the socket incase we sleep here.
*/
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);
sk->inuse = 1;
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);
skb = prot->wmalloc(sk, copy + prot->max_header , 0, GFP_KERNEL);
sk->inuse = 1;
}
/* If we didn't get any memory, we need to sleep. */
if (skb == NULL) {
if (nonblock /* || copied */) {
/*
* If we didn't get any memory, we need to sleep.
*/
if (skb == NULL)
{
if (nonblock /* || copied */)
{
release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 4\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(-EAGAIN);
}
/* FIXME: here is another race condition. */
/*
* FIXME: here is another race condition.
*/
tmp = sk->wmem_alloc;
release_sock(sk);
cli();
/* Again we will try to avoid it. */
/*
* Again we will try to avoid it.
*/
if (tmp <= sk->wmem_alloc &&
(sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
&& sk->err == 0) {
&& sk->err == 0)
{
interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked) {
if (current->signal & ~current->blocked)
{
sti();
DPRINTF((DBG_TCP, "tcp_write: return 5\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(-ERESTARTSYS);
}
}
......@@ -967,6 +1030,7 @@ tcp_write(struct sock *sk, unsigned char *from,
skb->len = 0;
skb->sk = sk;
skb->free = 0;
skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
buff = skb->data;
......@@ -974,13 +1038,16 @@ tcp_write(struct sock *sk, unsigned char *from,
* FIXME: we need to optimize this.
* Perhaps some hints here would be good.
*/
tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
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);
release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 6\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(tmp);
}
skb->len += tmp;
......@@ -988,15 +1055,18 @@ tcp_write(struct sock *sk, unsigned char *from,
buff += tmp;
skb->h.th =(struct tcphdr *) buff;
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);
release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 7\n"));
if (copied) return(copied);
if (copied)
return(copied);
return(tmp);
}
if (flags & MSG_OOB) {
if (flags & MSG_OOB)
{
((struct tcphdr *)buff)->urg = 1;
((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
}
......@@ -1010,7 +1080,8 @@ tcp_write(struct sock *sk, unsigned char *from,
skb->free = 0;
sk->write_seq += copy;
if (send_tmp != NULL && sk->packets_out) {
if (send_tmp != NULL && sk->packets_out)
{
tcp_enqueue_partial(send_tmp, sk);
continue;
}
......@@ -1025,32 +1096,39 @@ tcp_write(struct sock *sk, unsigned char *from,
* on my slow slip link - Alan
*/
/* Avoid possible race on send_tmp - c/o Johannes Stille */
if(sk->partial &&
((!sk->packets_out)
/*
* Avoid possible race on send_tmp - c/o Johannes Stille
*/
if(sk->partial && ((!sk->packets_out)
/* If not nagling we can send on the before case too.. */
|| (sk->nonagle && before(sk->write_seq , sk->window_seq))
))
tcp_send_partial(sk);
/* -- */
release_sock(sk);
DPRINTF((DBG_TCP, "tcp_write: return 8\n"));
return(copied);
}
static int
tcp_sendto(struct sock *sk, unsigned char *from,
static int tcp_sendto(struct sock *sk, unsigned char *from,
int len, int nonblock, unsigned flags,
struct sockaddr_in *addr, int addr_len)
{
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));
if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
if (sin.sin_port != sk->dummy_th.dest) return(-EINVAL);
if (sin.sin_addr.s_addr != sk->daddr) return(-EINVAL);
if (sin.sin_family && sin.sin_family != AF_INET)
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));
}
......@@ -1064,7 +1142,8 @@ tcp_read_wakeup(struct sock *sk)
struct sk_buff *buff;
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
......@@ -1076,8 +1155,10 @@ tcp_read_wakeup(struct sock *sk)
* We need to grab some memory, and put together an ack,
* and then put it into the queue to be sent.
*/
buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
if (buff == NULL) {
if (buff == NULL)
{
/* Try again real soon. */
reset_timer(sk, TIME_WRITE, 10);
return;
......@@ -1085,11 +1166,16 @@ tcp_read_wakeup(struct sock *sk)
buff->len = sizeof(struct tcphdr);
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,
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0) {
if (tmp < 0)
{
buff->free=1;
sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
return;
......@@ -1125,8 +1211,8 @@ tcp_read_wakeup(struct sock *sk)
* It should consider sending an ACK to let the
* 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;
int left;
......@@ -1144,6 +1230,7 @@ cleanup_rbuf(struct sock *sk)
* We have to loop through all the buffer headers,
* and try to free up all the space we can.
*/
while((skb=skb_peek(&sk->receive_queue)) != NULL)
{
if (!skb->used)
......@@ -1161,6 +1248,7 @@ cleanup_rbuf(struct sock *sk)
* in the window, and the amount of space is bigger than
* TCP_WINDOW_DIFF.
*/
DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n",
sk->window - sk->bytes_rcv, sk->prot->rspace(sk)));
......@@ -1180,7 +1268,7 @@ cleanup_rbuf(struct sock *sk)
* the user reads some more.
*/
sk->ack_backlog++;
/*
/*
* 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
* (called sk->mtu here). In theory there's no connection between send
......@@ -1188,15 +1276,21 @@ cleanup_rbuf(struct sock *sk)
* 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.
*/
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. */
tcp_read_wakeup(sk);
} else {
}
else
{
/* Force it to send an ack soon. */
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);
} else
}
else
add_timer(&sk->timer);
}
}
......@@ -1407,8 +1501,8 @@ static int tcp_read(struct sock *sk, unsigned char *to,
* Send a FIN without closing the connection.
* 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 tcphdr *t1, *th;
......@@ -1423,12 +1517,21 @@ tcp_shutdown(struct sock *sk, int how)
* Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
* 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;
/* Clear out any half completed packets. */
/*
* Clear out any half completed packets.
*/
if (sk->partial)
tcp_send_partial(sk);
......@@ -1436,20 +1539,28 @@ tcp_shutdown(struct sock *sk, int how)
th =(struct tcphdr *)&sk->dummy_th;
release_sock(sk); /* incase the malloc sleeps. */
buff = prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
if (buff == NULL) return;
if (buff == NULL)
return;
sk->inuse = 1;
DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff));
buff->sk = sk;
buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
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,
IPPROTO_TCP, sk->opt,
sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
if (tmp < 0) {
/* Finish anyway, treat this as a send that got lost. */
if (tmp < 0)
{
/*
* Finish anyway, treat this as a send that got lost.
*/
buff->free=1;
prot->wfree(sk,buff->mem_addr, buff->mem_len);
if(sk->state==TCP_ESTABLISHED)
......@@ -1480,20 +1591,27 @@ tcp_shutdown(struct sock *sk, int how)
* Can't just queue this up.
* 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;
if (buff->next != NULL) {
if (buff->next != NULL)
{
printk("tcp_shutdown: next != NULL\n");
skb_unlink(buff);
}
skb_queue_tail(&sk->write_queue, buff);
} else {
}
else
{
sk->sent_seq = sk->write_seq;
sk->prot->queue_xmit(sk, dev, buff, 0);
}
if (sk->state == TCP_ESTABLISHED) sk->state = TCP_FIN_WAIT1;
else sk->state = TCP_FIN_WAIT2;
if (sk->state == TCP_ESTABLISHED)
sk->state = TCP_FIN_WAIT1;
else
sk->state = TCP_FIN_WAIT2;
release_sock(sk);
}
......@@ -1536,9 +1654,11 @@ tcp_recvfrom(struct sock *sk, unsigned char *to,
}
/* This routine will send an RST to the other tcp. */
static void
tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
/*
* This routine will send an RST to the other tcp.
*/
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 sk_buff *buff;
......@@ -1546,10 +1666,11 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
int tmp;
struct device *ndev=NULL;
/*
/*
* We need to grab some memory, and put together an RST,
* and then put it into the queue to be sent.
*/
buff = prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
if (buff == NULL)
return;
......@@ -1558,22 +1679,31 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
buff->len = sizeof(*t1);
buff->sk = NULL;
buff->dev = dev;
buff->localroute = 0;
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,
sizeof(struct tcphdr),tos,ttl);
if (tmp < 0) {
if (tmp < 0)
{
buff->free = 1;
prot->wfree(NULL, buff->mem_addr, buff->mem_len);
return;
}
t1 =(struct tcphdr *)((char *)t1 +tmp);
buff->len += tmp;
memcpy(t1, th, sizeof(*t1));
/* Swap the send and the receive. */
/*
* Swap the send and the receive.
*/
t1->dest = th->source;
t1->source = th->dest;
t1->rst = 1;
......@@ -1755,6 +1885,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk->pair = NULL;
newsk->wmem_alloc = 0;
newsk->rmem_alloc = 0;
newsk->localroute = sk->localroute;
newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF;
......@@ -1830,6 +1961,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
buff->len = sizeof(struct tcphdr)+4;
buff->sk = newsk;
buff->localroute = newsk->localroute;
t1 =(struct tcphdr *) buff->data;
......@@ -1896,8 +2028,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
}
static void
tcp_close(struct sock *sk, int timeout)
static void tcp_close(struct sock *sk, int timeout)
{
struct sk_buff *buff;
int need_reset = 0;
......@@ -1918,7 +2049,10 @@ tcp_close(struct sock *sk, int timeout)
if (!sk->dead)
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)
{
struct sk_buff *skb;
......@@ -1934,26 +2068,34 @@ tcp_close(struct sock *sk, int timeout)
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);
}
switch(sk->state) {
switch(sk->state)
{
case TCP_FIN_WAIT1:
case TCP_FIN_WAIT2:
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.
* it seems to make most sense to use the backed off value
*/
reset_timer(sk, TIME_CLOSE, 4 * sk->rto);
if (timeout) tcp_time_wait(sk);
if (timeout)
tcp_time_wait(sk);
release_sock(sk);
return; /* break causes a double release - messy */
case TCP_TIME_WAIT:
if (timeout) {
if (timeout)
{
sk->state = TCP_CLOSE;
}
release_sock(sk);
......@@ -1972,7 +2114,8 @@ tcp_close(struct sock *sk, int timeout)
prot =(struct proto *)sk->prot;
th =(struct tcphdr *)&sk->dummy_th;
buff = prot->wmalloc(sk, MAX_FIN_SIZE, 1, GFP_ATOMIC);
if (buff == NULL) {
if (buff == NULL)
{
/* This will force it to try again later. */
/* Or it would have if someone released the socket
first. Anyway it might work now */
......@@ -1985,13 +2128,17 @@ tcp_close(struct sock *sk, int timeout)
buff->sk = sk;
buff->free = 1;
buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
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,
IPPROTO_TCP, sk->opt,
sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
if (tmp < 0) {
if (tmp < 0)
{
kfree_skb(buff,FREE_WRITE);
if(sk->state==TCP_ESTABLISHED)
sk->state=TCP_FIN_WAIT1;
......@@ -2015,7 +2162,10 @@ tcp_close(struct sock *sk, int timeout)
buff->h.seq = sk->write_seq;
t1->ack = 1;
/* Ack everything immediately from now on. */
/*
* Ack everything immediately from now on.
*/
sk->delay_acks = 0;
t1->ack_seq = ntohl(sk->acked_seq);
t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
......@@ -2026,21 +2176,28 @@ tcp_close(struct sock *sk, int timeout)
tcp_statistics.TcpOutSegs++;
if (skb_peek(&sk->write_queue) == NULL) {
if (skb_peek(&sk->write_queue) == NULL)
{
sk->sent_seq = sk->write_seq;
prot->queue_xmit(sk, dev, buff, 0);
} else {
}
else
{
reset_timer(sk, TIME_WRITE, sk->rto);
if (buff->next != NULL) {
if (buff->next != NULL)
{
printk("tcp_close: next != NULL\n");
skb_unlink(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;
} else {
}
else
{
sk->state = TCP_FIN_WAIT1;
}
}
......@@ -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
tcp_fin(struct sock *sk, struct tcphdr *th,
/*
* This deals with incoming fins. 'Linus at 9 O'clock' 8-)
*/
static int tcp_fin(struct sock *sk, struct tcphdr *th,
unsigned long saddr, struct device *dev)
{
DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n",
sk, th, saddr, dev));
if (!sk->dead) {
if (!sk->dead)
{
sk->state_change(sk);
}
switch(sk->state) {
switch(sk->state)
{
case TCP_SYN_RECV:
case TCP_SYN_SENT:
case TCP_ESTABLISHED:
......@@ -2783,7 +2944,8 @@ tcp_fin(struct sock *sk, struct tcphdr *th,
sk->fin_seq = th->seq+1;
tcp_statistics.TcpCurrEstab--;
sk->state = TCP_CLOSE_WAIT;
if (th->rst) sk->shutdown = SHUTDOWN_MASK;
if (th->rst)
sk->shutdown = SHUTDOWN_MASK;
break;
case TCP_CLOSE_WAIT:
......@@ -2861,9 +3023,11 @@ tcp_accept(struct sock *sk, int flags)
}
/* This will initiate an outgoing connection. */
static int
tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
/*
* This will initiate an outgoing connection.
*/
static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
{
struct sk_buff *buff;
struct sockaddr_in sin;
......@@ -2873,8 +3037,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
struct tcphdr *t1;
int err;
if (sk->state != TCP_CLOSE) return(-EISCONN);
if (addr_len < 8) return(-EINVAL);
if (sk->state != TCP_CLOSE)
return(-EISCONN);
if (addr_len < 8)
return(-EINVAL);
err=verify_area(VERIFY_READ, usin, addr_len);
if(err)
......@@ -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));
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)));
/* 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"));
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))
return -EBUSY;
......@@ -2906,24 +3087,35 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
release_sock(sk);
buff = sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
if (buff == NULL) {
if (buff == NULL)
{
return(-ENOMEM);
}
sk->inuse = 1;
buff->len = 24;
buff->sk = sk;
buff->free = 1;
buff->localroute = sk->localroute;
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,
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);
release_sock(sk);
return(-ENETUNREACH);
}
buff->len += tmp;
t1 = (struct tcphdr *)((char *)t1 +tmp);
......@@ -2941,11 +3133,12 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
t1->syn = 1;
t1->urg_ptr = 0;
t1->doff = 6;
/* use 512 or whatever user asked for */
/* use 512 or whatever user asked for */
if (sk->user_mss)
sk->mtu = sk->user_mss;
else {
else
{
#ifdef SUBNETSARELOCAL
if ((sk->saddr ^ sk->daddr) & default_mask(sk->saddr))
#else
......@@ -2955,10 +3148,16 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
else
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);
/* Put in the TCP options to say MTU. */
/*
* Put in the TCP options to say MTU.
*/
ptr = (unsigned char *)(t1+1);
ptr[0] = 2;
ptr[1] = 4;
......@@ -2967,7 +3166,10 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
tcp_send_check(t1, sk->saddr, sk->daddr,
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->rtt = TCP_CONNECT_TIME;
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");
* This routine sends a packet with an out of date sequence
* 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 tcphdr *t1;
......@@ -3470,18 +3672,22 @@ tcp_write_wakeup(struct sock *sk)
return;
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->free = 1;
buff->sk = sk;
buff->localroute = sk->localroute;
DPRINTF((DBG_TCP, "in tcp_write_wakeup\n"));
t1 = (struct tcphdr *) buff->data;
/* Put in the IP header and routing stuff. */
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
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);
return;
}
......
......@@ -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);
......@@ -614,6 +615,8 @@ udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
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 */
......
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