Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
de0eab26
Commit
de0eab26
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.6
parent
37b4c9bd
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1319 additions
and
1058 deletions
+1319
-1058
Makefile
Makefile
+1
-1
drivers/net/d_link.c
drivers/net/d_link.c
+9
-1
drivers/net/depca.c
drivers/net/depca.c
+1
-34
drivers/net/slip.c
drivers/net/slip.c
+7
-1
include/linux/skbuff.h
include/linux/skbuff.h
+1
-1
include/linux/socket.h
include/linux/socket.h
+1
-0
kernel/exit.c
kernel/exit.c
+18
-18
net/inet/dev.c
net/inet/dev.c
+1
-1
net/inet/ip.c
net/inet/ip.c
+8
-2
net/inet/ipx.c
net/inet/ipx.c
+5
-3
net/inet/raw.c
net/inet/raw.c
+125
-106
net/inet/route.c
net/inet/route.c
+36
-0
net/inet/route.h
net/inet/route.h
+15
-11
net/inet/sock.c
net/inet/sock.c
+5
-3
net/inet/sock.h
net/inet/sock.h
+1
-0
net/inet/tcp.c
net/inet/tcp.c
+1063
-857
net/inet/udp.c
net/inet/udp.c
+22
-19
No files found.
Makefile
View file @
de0eab26
VERSION
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
5
SUBLEVEL
=
6
all
:
Version zImage
...
...
drivers/net/d_link.c
View file @
de0eab26
...
...
@@ -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
drivers/net/depca.c
View file @
de0eab26
...
...
@@ -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
;
}
...
...
drivers/net/slip.c
View file @
de0eab26
...
...
@@ -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
;
...
...
include/linux/skbuff.h
View file @
de0eab26
...
...
@@ -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
];
...
...
include/linux/socket.h
View file @
de0eab26
...
...
@@ -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
...
...
kernel/exit.c
View file @
de0eab26
...
...
@@ -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
)
{
v
free
(
current
->
ldt
)
;
v
oid
*
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
...
...
net/inet/dev.c
View file @
de0eab26
...
...
@@ -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
*/
...
...
net/inet/ip.c
View file @
de0eab26
...
...
@@ -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
...
...
net/inet/ipx.c
View file @
de0eab26
...
...
@@ -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
),
...
...
net/inet/raw.c
View file @
de0eab26
...
...
@@ -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
;
...
...
net/inet/route.c
View file @
de0eab26
...
...
@@ -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
*/
...
...
net/inet/route.h
View file @
de0eab26
...
...
@@ -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
);
...
...
net/inet/sock.c
View file @
de0eab26
...
...
@@ -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
);
...
...
net/inet/sock.h
View file @
de0eab26
...
...
@@ -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
;
...
...
net/inet/tcp.c
View file @
de0eab26
...
...
@@ -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
(
"
\r
tcp_ack: malloc failed
\n
"
);
if
(
inet_debug
==
DBG_SLIP
)
printk
(
"
\r
tcp_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
(
"
\r
tcp_ack: build_header failed
\n
"
);
if
(
inet_debug
==
DBG_SLIP
)
printk
(
"
\r
tcp_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
;
}
...
...
net/inet/udp.c
View file @
de0eab26
...
...
@@ -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 */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment