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
nexedi
linux
Commits
c1d630b5
Commit
c1d630b5
authored
Mar 12, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Resolve merge conflict
parents
44879cd0
c3a12cc5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
272 additions
and
328 deletions
+272
-328
net/ipv4/ipmr.c
net/ipv4/ipmr.c
+1
-2
net/ipx/af_spx.c
net/ipx/af_spx.c
+271
-326
No files found.
net/ipv4/ipmr.c
View file @
c1d630b5
...
...
@@ -855,8 +855,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
switch
(
optname
)
{
case
MRT_INIT
:
if
(
sk
->
type
!=
SOCK_RAW
||
inet_sk
(
sk
)
->
num
!=
IPPROTO_IGMP
)
if
(
sk
->
type
!=
SOCK_RAW
||
inet_sk
(
sk
)
->
num
!=
IPPROTO_IGMP
)
return
-
EOPNOTSUPP
;
if
(
optlen
!=
sizeof
(
int
))
return
-
ENOPROTOOPT
;
...
...
net/ipx/af_spx.c
View file @
c1d630b5
...
...
@@ -8,6 +8,7 @@
* Developers:
* Jay Schulist <jschlst@samba.org>
* Jim Freeman <jfree@caldera.com>
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* Changes:
* Alan Cox : Fixed an skb_unshare check for NULL
...
...
@@ -22,6 +23,8 @@
* of the alloc count to follow rmt_seq.
* Arnaldo C. Melo : Use a private slabcache for the old tp_pinfo
* struct sock member, use spx_sk and ipx_sk
* Arnaldo C. Melo : Big CodingStyle cleanup, fixes some lock leaks,
* removes a leftover of the slabcache patch.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -44,7 +47,7 @@
#include <linux/unistd.h>
#include <linux/poll.h>
static
struct
proto_ops
*
ipx_op
eration
s
;
static
struct
proto_ops
*
ipx_ops
;
static
struct
proto_ops
spx_ops
;
static
__u16
connids
;
...
...
@@ -60,7 +63,8 @@ extern void ipx_remove_socket(struct sock *sk);
but the right spx buffers are looked at and
there is no question on the type of the socket
*/
static
unsigned
int
spx_datagram_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
)
static
unsigned
int
spx_datagram_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
...
...
@@ -84,15 +88,14 @@ static unsigned int spx_datagram_poll(struct file * file, struct socket *sock, p
mask
|=
POLLHUP
;
/* connection hasn't started yet? */
if
(
sk
->
state
==
TCP_SYN_SENT
)
return
mask
;
goto
out
;
/* writable? */
if
(
sock_writeable
(
sk
))
mask
|=
POLLOUT
|
POLLWRNORM
|
POLLWRBAND
;
else
set_bit
(
SOCK_ASYNC_NOSPACE
,
&
sk
->
socket
->
flags
);
return
mask
;
out:
return
mask
;
}
/* Create the SPX specific data */
...
...
@@ -123,43 +126,42 @@ static int spx_sock_init(struct sock *sk)
skb_queue_head_init
(
&
pdata
->
transmit_queue
);
skb_queue_head_init
(
&
pdata
->
retransmit_queue
);
return
(
0
)
;
return
0
;
}
static
int
spx_create
(
struct
socket
*
sock
,
int
protocol
)
{
struct
sock
*
sk
;
int
rc
=
-
ENOMEM
;
MOD_INC_USE_COUNT
;
/*
* Called on connection receive so cannot be GFP_KERNEL
*/
/* Called on connection receive so cannot be GFP_KERNEL */
sk
=
sk_alloc
(
PF_IPX
,
GFP_ATOMIC
,
1
);
if
(
sk
==
NULL
)
return
(
-
ENOMEM
)
;
if
(
!
sk
)
goto
decmod
;
switch
(
sock
->
type
)
{
rc
=
-
ESOCKTNOSUPPORT
;
switch
(
sock
->
type
)
{
case
SOCK_SEQPACKET
:
sock
->
ops
=
&
spx_ops
;
break
;
default:
sk_free
(
sk
);
return
(
-
ESOCKTNOSUPPORT
)
;
goto
out
;
}
rc
=
0
;
sock_init_data
(
sock
,
sk
);
spx_sock_init
(
sk
);
sk
->
data_ready
=
spx_rcv
;
sk
->
destruct
=
NULL
;
sk
->
no_check
=
1
;
MOD_INC_USE_COUNT
;
return
(
0
);
out:
return
rc
;
decmod:
MOD_DEC_USE_COUNT
;
goto
out
;
}
void
spx_close_socket
(
struct
sock
*
sk
)
{
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
...
...
@@ -173,18 +175,12 @@ void spx_close_socket(struct sock *sk)
void
spx_destroy_socket
(
struct
sock
*
sk
)
{
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sk_buff
*
skb
;
ipx_remove_socket
(
sk
);
while
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
!=
NULL
)
kfree_skb
(
skb
);
while
((
skb
=
skb_dequeue
(
&
pdata
->
transmit_queue
))
!=
NULL
)
kfree_skb
(
skb
);
while
((
skb
=
skb_dequeue
(
&
pdata
->
retransmit_queue
))
!=
NULL
)
kfree_skb
(
skb
);
while
((
skb
=
skb_dequeue
(
&
pdata
->
rcv_queue
))
!=
NULL
)
kfree_skb
(
skb
);
skb_queue_purge
(
&
sk
->
receive_queue
);
skb_queue_purge
(
&
pdata
->
transmit_queue
);
skb_queue_purge
(
&
pdata
->
retransmit_queue
);
skb_queue_purge
(
&
pdata
->
rcv_queue
);
sk_free
(
sk
);
MOD_DEC_USE_COUNT
;
}
...
...
@@ -195,14 +191,13 @@ static int spx_release(struct socket *sock)
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
if
(
sk
==
NULL
)
return
(
0
)
;
if
(
!
sk
->
dead
)
if
(
!
sk
)
goto
out
;
if
(
!
sk
->
dead
)
sk
->
state_change
(
sk
);
sk
->
dead
=
1
;
if
(
pdata
->
state
!=
SPX_CLOSED
)
{
if
(
pdata
->
state
!=
SPX_CLOSED
)
{
spx_transmit
(
sk
,
NULL
,
DISCON
,
0
);
spx_close_socket
(
sk
);
}
...
...
@@ -210,111 +205,101 @@ static int spx_release(struct socket *sock)
sock
->
sk
=
NULL
;
sk
->
socket
=
NULL
;
spx_destroy_socket
(
sk
);
return
(
0
);
out:
return
0
;
}
/* Move a socket into listening state. */
static
int
spx_listen
(
struct
socket
*
sock
,
int
backlog
)
{
struct
sock
*
sk
=
sock
->
sk
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
(
-
EINVAL
);
if
(
sock
->
type
!=
SOCK_SEQPACKET
)
return
(
-
EOPNOTSUPP
);
if
(
sk
->
zapped
!=
0
)
return
(
-
EAGAIN
);
int
rc
=
-
EINVAL
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
goto
out
;
rc
=
-
EOPNOTSUPP
;
if
(
sock
->
type
!=
SOCK_SEQPACKET
)
goto
out
;
rc
=
-
EAGAIN
;
if
(
sk
->
zapped
)
goto
out
;
rc
=
0
;
sk
->
max_ack_backlog
=
backlog
;
if
(
sk
->
state
!=
TCP_LISTEN
)
{
if
(
sk
->
state
!=
TCP_LISTEN
)
{
sk
->
ack_backlog
=
0
;
sk
->
state
=
TCP_LISTEN
;
}
sk
->
socket
->
flags
|=
__SO_ACCEPTCON
;
return
(
0
);
out:
return
rc
;
}
/* Accept a pending SPX connection */
static
int
spx_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
struct
sock
*
sk
;
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
newsk
;
struct
sk_buff
*
skb
;
int
err
;
if
(
sock
->
sk
==
NULL
)
return
(
-
EINVAL
);
sk
=
sock
->
sk
;
if
((
sock
->
state
!=
SS_UNCONNECTED
)
||
!
(
sock
->
flags
&
__SO_ACCEPTCON
))
return
(
-
EINVAL
);
if
(
sock
->
type
!=
SOCK_SEQPACKET
)
return
(
-
EOPNOTSUPP
);
if
(
sk
->
state
!=
TCP_LISTEN
)
return
(
-
EINVAL
);
int
rc
=
-
EINVAL
;
if
(
!
sk
||
sk
->
state
!=
TCP_LISTEN
||
sock
->
state
!=
SS_UNCONNECTED
||
!
(
sock
->
flags
&
__SO_ACCEPTCON
))
goto
out
;
rc
=
-
EOPNOTSUPP
;
if
(
sock
->
type
!=
SOCK_SEQPACKET
)
goto
out
;
cli
();
do
{
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
skb
==
NULL
)
{
if
(
flags
&
O_NONBLOCK
)
{
sti
();
return
(
-
EWOULDBLOCK
);
}
if
(
!
skb
)
{
rc
=
-
EWOULDBLOCK
;
if
(
flags
&
O_NONBLOCK
)
goto
out_unlock
;
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
{
sti
();
return
(
-
ERESTARTSYS
);
}
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
out_unlock
;
}
}
while
(
skb
==
NULL
);
}
while
(
!
skb
);
newsk
=
skb
->
sk
;
newsk
->
pair
=
NULL
;
sti
();
err
=
spx_transmit
(
newsk
,
skb
,
CONACK
,
0
);
/* Connection ACK */
if
(
err
)
return
(
err
);
rc
=
spx_transmit
(
newsk
,
skb
,
CONACK
,
0
);
/* Connection ACK */
if
(
rc
)
goto
out
;
/* Now attach up the new socket */
sock
->
sk
=
NULL
;
sk
->
ack_backlog
--
;
newsock
->
sk
=
newsk
;
newsk
->
state
=
TCP_ESTABLISHED
;
ipx_sk
(
newsk
)
->
dest_addr
=
spx_sk
(
newsk
)
->
dest_addr
;
return
(
0
);
out:
return
rc
;
out_unlock:
sti
();
goto
out
;
}
/* Build a connection to an SPX socket */
static
int
spx_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
,
int
flags
)
int
addr_len
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sockaddr_ipx
src
;
struct
sk_buff
*
skb
;
int
size
,
err
;
int
size
=
sizeof
(
src
);
int
rc
=
ipx_ops
->
getname
(
sock
,
(
struct
sockaddr
*
)
&
src
,
&
size
,
0
);
size
=
sizeof
(
src
);
err
=
ipx_operations
->
getname
(
sock
,
(
struct
sockaddr
*
)
&
src
,
&
size
,
0
);
if
(
err
)
return
(
err
);
if
(
rc
)
goto
out
;
pdata
->
source_addr
.
net
=
src
.
sipx_network
;
memcpy
(
pdata
->
source_addr
.
node
,
src
.
sipx_node
,
IPX_NODE_LEN
);
pdata
->
source_addr
.
sock
=
(
unsigned
short
)
src
.
sipx_port
;
err
=
ipx_operation
s
->
connect
(
sock
,
uaddr
,
addr_len
,
flags
);
if
(
err
)
return
(
err
)
;
rc
=
ipx_op
s
->
connect
(
sock
,
uaddr
,
addr_len
,
flags
);
if
(
rc
)
goto
out
;
pdata
->
dest_addr
=
ipx_sk
(
sk
)
->
dest_addr
;
pdata
->
state
=
SPX_CONNECTING
;
...
...
@@ -322,42 +307,36 @@ static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
sk
->
state
=
TCP_SYN_SENT
;
/* Send Connection request */
err
=
spx_transmit
(
sk
,
NULL
,
CONREQ
,
0
);
if
(
err
)
return
(
err
)
;
rc
=
spx_transmit
(
sk
,
NULL
,
CONREQ
,
0
);
if
(
rc
)
goto
out
;
cli
();
do
{
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
skb
==
NULL
)
{
if
(
flags
&
O_NONBLOCK
)
{
sti
();
return
(
-
EWOULDBLOCK
);
}
if
(
!
skb
)
{
rc
=
-
EWOULDBLOCK
;
if
(
flags
&
O_NONBLOCK
)
goto
unlock
;
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
{
sti
();
return
(
-
ERESTARTSYS
);
}
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
unlock
;
}
}
while
(
skb
==
NULL
);
}
while
(
!
skb
);
if
(
pdata
->
state
==
SPX_CLOSED
)
{
sti
();
rc
=
-
ETIMEDOUT
;
if
(
pdata
->
state
==
SPX_CLOSED
)
{
del_timer
(
&
pdata
->
watchdog
);
return
(
-
ETIMEDOUT
)
;
goto
unlock
;
}
rc
=
0
;
sock
->
state
=
SS_CONNECTED
;
sk
->
state
=
TCP_ESTABLISHED
;
kfree_skb
(
skb
);
sti
();
return
(
0
);
unlock:
sti
();
out:
return
rc
;
}
/*
...
...
@@ -371,56 +350,59 @@ static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
*/
static
inline
unsigned
long
spx_calc_rtt
(
int
tries
)
{
if
(
tries
<
1
)
return
(
RETRY_TIME
);
if
(
tries
>
5
)
return
(
MAX_RETRY_DELAY
);
return
(
tries
*
HZ
);
int
rc
;
if
(
tries
<
1
)
rc
=
RETRY_TIME
;
else
if
(
tries
>
5
)
rc
=
MAX_RETRY_DELAY
;
else
rc
=
tries
*
HZ
;
return
rc
;
}
static
int
spx_route_skb
(
struct
spx_opt
*
pdata
,
struct
sk_buff
*
skb
,
int
type
)
{
struct
sk_buff
*
skb2
;
int
err
=
0
;
int
rc
=
-
ENOBUFS
;
skb
=
skb_unshare
(
skb
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
return
(
-
ENOBUFS
);
switch
(
type
)
{
case
(
CONREQ
):
case
(
DATA
):
if
(
!
skb_queue_empty
(
&
pdata
->
retransmit_queue
))
{
if
(
!
skb
)
goto
out
;
rc
=
0
;
switch
(
type
)
{
case
CONREQ
:
case
DATA
:
if
(
!
skb_queue_empty
(
&
pdata
->
retransmit_queue
))
{
skb_queue_tail
(
&
pdata
->
transmit_queue
,
skb
);
return
0
;
goto
out
;
}
case
(
TQUEUE
):
case
TQUEUE
:
{
struct
sk_buff
*
skb2
;
pdata
->
retransmit
.
expires
=
jiffies
+
spx_calc_rtt
(
0
);
add_timer
(
&
pdata
->
retransmit
);
skb2
=
skb_clone
(
skb
,
GFP_NOIO
);
if
(
skb2
==
NULL
)
return
-
ENOBUFS
;
if
(
!
skb2
)
{
rc
=
-
ENOBUFS
;
goto
out
;
}
skb_queue_tail
(
&
pdata
->
retransmit_queue
,
skb2
);
case
(
ACK
):
case
(
CONACK
)
:
case
(
WDREQ
)
:
case
(
WDACK
)
:
case
(
DISCON
)
:
case
(
DISACK
)
:
case
(
RETRAN
)
:
default
:
/* Send data */
err
=
ipxrtr_route_skb
(
skb
);
if
(
err
)
/* Fall thru */
}
case
ACK
:
case
CONACK
:
case
WDREQ
:
case
WDACK
:
case
DISCON
:
case
DISACK
:
case
RETRAN
:
default:
/* Send data */
rc
=
ipxrtr_route_skb
(
skb
);
if
(
rc
)
kfree_skb
(
skb
);
}
return
(
err
);
out:
return
rc
;
}
/* SPX packet transmit engine */
...
...
@@ -429,25 +411,27 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
ipxspxhdr
*
ipxh
;
unsigned
long
flags
;
int
err
;
int
rc
;
if
(
skb
==
NULL
)
{
if
(
!
skb
)
{
int
offset
=
ipx_if_offset
(
pdata
->
dest_addr
.
net
);
int
size
=
offset
+
sizeof
(
struct
ipxspxhdr
);
if
(
offset
<
0
)
/* ENETUNREACH */
return
(
-
ENETUNREACH
);
rc
=
-
ENETUNREACH
;
if
(
offset
<
0
)
goto
out
;
save_flags
(
flags
);
cli
();
skb
=
sock_alloc_send_skb
(
sk
,
size
,
0
,
&
err
);
if
(
skb
==
NULL
)
{
rc
=
-
ENOMEM
;
if
(
!
skb
)
{
restore_flags
(
flags
);
return
(
-
ENOMEM
)
;
goto
out
;
}
skb_reserve
(
skb
,
offset
);
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxspxhdr
));
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxspxhdr
));
restore_flags
(
flags
);
}
...
...
@@ -471,40 +455,39 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
/* Reset/Set WD timer */
mod_timer
(
&
pdata
->
watchdog
,
jiffies
+
VERIFY_TIMEOUT
);
switch
(
type
)
{
case
(
DATA
):
/* Data */
switch
(
type
)
{
case
DATA
:
/* Data */
ipxh
->
ipx
.
ipx_pktsize
=
htons
(
SPX_SYS_PKT_LEN
+
len
);
ipxh
->
spx
.
cctl
=
(
CCTL_ACK
|
CCTL_EOM
);
pdata
->
sequence
++
;
break
;
case
(
ACK
)
:
/* ACK */
case
ACK
:
/* ACK */
pdata
->
rmt_seq
++
;
case
(
WDACK
)
:
/* WD ACK */
case
(
CONACK
)
:
/* Connection ACK */
case
WDACK
:
/* WD ACK */
case
CONACK
:
/* Connection ACK */
ipxh
->
spx
.
cctl
=
CCTL_SYS
;
ipxh
->
spx
.
ackseq
=
htons
(
pdata
->
rmt_seq
);
break
;
case
(
CONREQ
)
:
/* Connection Request */
case
CONREQ
:
/* Connection Request */
del_timer
(
&
pdata
->
watchdog
);
case
(
WDREQ
)
:
/* WD Request */
case
WDREQ
:
/* WD Request */
pdata
->
source_connid
=
htons
(
connids
++
);
pdata
->
dest_connid
=
0xFFFF
;
pdata
->
alloc
=
3
+
pdata
->
rmt_seq
;
ipxh
->
spx
.
cctl
=
(
CCTL_ACK
|
CCTL_SYS
)
;
ipxh
->
spx
.
cctl
=
CCTL_ACK
|
CCTL_SYS
;
ipxh
->
spx
.
sconn
=
pdata
->
source_connid
;
ipxh
->
spx
.
dconn
=
pdata
->
dest_connid
;
ipxh
->
spx
.
allocseq
=
htons
(
pdata
->
alloc
);
break
;
case
(
DISCON
)
:
/* Informed Disconnect */
case
DISCON
:
/* Informed Disconnect */
ipxh
->
spx
.
cctl
=
CCTL_ACK
;
ipxh
->
spx
.
dtype
=
SPX_DTYPE_ECONN
;
break
;
case
(
DISACK
)
:
/* Informed Disconnect ACK */
case
DISACK
:
/* Informed Disconnect ACK */
ipxh
->
spx
.
cctl
=
0
;
ipxh
->
spx
.
dtype
=
SPX_DTYPE_ECACK
;
ipxh
->
spx
.
sequence
=
0
;
...
...
@@ -512,11 +495,13 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
break
;
default:
return
(
-
EOPNOTSUPP
);
rc
=
-
EOPNOTSUPP
;
goto
out
;
}
/* Send data */
return
(
spx_route_skb
(
pdata
,
skb
,
type
));
rc
=
spx_route_skb
(
pdata
,
skb
,
type
);
out:
return
rc
;
}
/* Check the state of the connection and send a WD request if needed. */
...
...
@@ -526,19 +511,16 @@ static void spx_watchdog(unsigned long data)
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
del_timer
(
&
pdata
->
watchdog
);
if
(
pdata
->
state
==
SPX_CLOSED
)
return
;
if
(
pdata
->
retries
>
pdata
->
max_retries
)
{
if
(
pdata
->
state
==
SPX_CLOSED
)
goto
out
;
if
(
pdata
->
retries
>
pdata
->
max_retries
)
{
spx_close_socket
(
sk
);
/* Unilateral Abort */
return
;
goto
out
;
}
/* Send WD request */
spx_transmit
(
sk
,
NULL
,
WDREQ
,
0
);
pdata
->
retries
++
;
return
;
out:
;
}
static
void
spx_retransmit
(
unsigned
long
data
)
...
...
@@ -547,22 +529,19 @@ static void spx_retransmit(unsigned long data)
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sk_buff
*
skb
;
unsigned
long
flags
;
int
err
;
del_timer
(
&
pdata
->
retransmit
);
if
(
pdata
->
state
==
SPX_CLOSED
)
return
;
if
(
pdata
->
retransmits
>
RETRY_COUNT
)
{
if
(
pdata
->
state
==
SPX_CLOSED
)
goto
out
;
if
(
pdata
->
retransmits
>
RETRY_COUNT
)
{
spx_close_socket
(
sk
);
/* Unilateral Abort */
return
;
goto
out
;
}
/* Need to leave skb on the queue, aye the fear */
save_flags
(
flags
);
cli
();
skb
=
skb_peek
(
&
pdata
->
retransmit_queue
);
if
(
skb_cloned
(
skb
))
if
(
skb_cloned
(
skb
))
skb
=
skb_copy
(
skb
,
GFP_ATOMIC
);
else
skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
...
...
@@ -571,67 +550,60 @@ static void spx_retransmit(unsigned long data)
pdata
->
retransmit
.
expires
=
jiffies
+
spx_calc_rtt
(
pdata
->
retransmits
);
add_timer
(
&
pdata
->
retransmit
);
err
=
spx_route_skb
(
pdata
,
skb
,
RETRAN
);
spx_route_skb
(
pdata
,
skb
,
RETRAN
);
pdata
->
retransmits
++
;
return
;
out:
;
}
/* Check packet for retransmission, ConReqAck aware */
static
int
spx_retransmit_chk
(
struct
spx_opt
*
pdata
,
int
ackseq
,
int
type
)
{
struct
ipxspxhdr
*
ipxh
;
struct
sk_buff
*
skb
;
skb
=
skb_dequeue
(
&
pdata
->
retransmit_queue
);
if
(
!
skb
)
return
(
-
ENOENT
);
int
rc
=
-
ENOENT
;
struct
sk_buff
*
skb
=
skb_dequeue
(
&
pdata
->
retransmit_queue
);
if
(
!
skb
)
goto
out
;
rc
=
0
;
/* Check Data/ACK seq */
switch
(
type
)
{
switch
(
type
)
{
case
ACK
:
/* Check Sequence, Should == 1 */
ipxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
if
(
!
(
ntohs
(
ipxh
->
spx
.
sequence
)
-
htons
(
ackseq
)))
if
(
!
(
ntohs
(
ipxh
->
spx
.
sequence
)
-
htons
(
ackseq
)))
break
;
case
CONACK
:
del_timer
(
&
pdata
->
retransmit
);
pdata
->
retransmits
=
0
;
kfree_skb
(
skb
);
if
(
skb_queue_empty
(
&
pdata
->
retransmit_queue
))
{
if
(
skb_queue_empty
(
&
pdata
->
retransmit_queue
))
{
skb
=
skb_dequeue
(
&
pdata
->
transmit_queue
);
if
(
skb
!=
NULL
)
if
(
skb
)
spx_route_skb
(
pdata
,
skb
,
TQUEUE
);
}
return
(
0
)
;
goto
out
;
}
skb_queue_head
(
&
pdata
->
retransmit_queue
,
skb
);
return
(
-
1
);
rc
=
-
1
;
out:
return
rc
;
}
/* SPX packet receive engine */
void
spx_rcv
(
struct
sock
*
sk
,
int
bytes
)
{
struct
sk_buff
*
skb
;
struct
ipxspxhdr
*
ipxh
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sk_buff
*
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
skb
==
NULL
)
return
;
if
(
!
skb
)
goto
out
;
ipxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
/* Can't receive on a closed connection */
if
((
pdata
->
state
==
SPX_CLOSED
)
&&
(
ipxh
->
spx
.
sequence
!=
0
))
goto
toss_skb
;
if
(
ntohs
(
ipxh
->
ipx
.
ipx_pktsize
)
<
SPX_SYS_PKT_LEN
)
goto
toss_skb
;
if
(
ipxh
->
ipx
.
ipx_type
!=
IPX_TYPE_SPX
)
goto
toss_skb
;
if
(
ntohs
(
ipxh
->
spx
.
ackseq
)
>
pdata
->
sequence
)
if
((
pdata
->
state
==
SPX_CLOSED
&&
ipxh
->
spx
.
sequence
)
||
ntohs
(
ipxh
->
ipx
.
ipx_pktsize
)
<
SPX_SYS_PKT_LEN
||
ipxh
->
ipx
.
ipx_type
!=
IPX_TYPE_SPX
||
ntohs
(
ipxh
->
spx
.
ackseq
)
>
pdata
->
sequence
)
goto
toss_skb
;
/* Reset WD timer on any received packet */
...
...
@@ -640,13 +612,11 @@ void spx_rcv(struct sock *sk, int bytes)
pdata
->
watchdog
.
expires
=
jiffies
+
ABORT_TIMEOUT
;
add_timer
(
&
pdata
->
watchdog
);
switch
(
ipxh
->
spx
.
cctl
)
{
switch
(
ipxh
->
spx
.
cctl
)
{
case
(
CCTL_SYS
|
CCTL_ACK
):
if
((
ipxh
->
spx
.
sequence
==
0
)
/* ConReq */
&&
(
ipxh
->
spx
.
ackseq
==
0
)
&&
(
ipxh
->
spx
.
dconn
==
0xFFFF
))
{
if
(
!
ipxh
->
spx
.
sequence
&&
/* ConReq */
!
ipxh
->
spx
.
ackseq
&&
ipxh
->
spx
.
dconn
==
0xFFFF
)
{
pdata
->
state
=
SPX_CONNECTED
;
pdata
->
dest_addr
=
ipxh
->
ipx
.
ipx_source
;
pdata
->
source_addr
=
ipxh
->
ipx
.
ipx_dest
;
...
...
@@ -655,63 +625,57 @@ void spx_rcv(struct sock *sk, int bytes)
skb_queue_tail
(
&
sk
->
receive_queue
,
skb
);
wake_up_interruptible
(
sk
->
sleep
);
}
else
/* WD Request */
}
else
/* WD Request */
spx_transmit
(
sk
,
skb
,
WDACK
,
0
);
goto
finish
;
goto
out
;
case
CCTL_SYS
:
/* ACK */
if
((
ipxh
->
spx
.
dtype
==
0
)
/* ConReq ACK */
&&
(
ipxh
->
spx
.
sconn
!=
0xFFFF
)
&&
(
ipxh
->
spx
.
dconn
!=
0xFFFF
)
&&
(
ipxh
->
spx
.
sequence
==
0
)
&&
(
ipxh
->
spx
.
ackseq
==
0
)
&&
(
pdata
->
state
!=
SPX_CONNECTED
))
{
if
(
!
ipxh
->
spx
.
dtype
&&
/* ConReq ACK */
ipxh
->
spx
.
sconn
!=
0xFFFF
&&
ipxh
->
spx
.
dconn
!=
0xFFFF
&&
!
ipxh
->
spx
.
sequence
&&
!
ipxh
->
spx
.
ackseq
&&
pdata
->
state
!=
SPX_CONNECTED
)
{
pdata
->
state
=
SPX_CONNECTED
;
pdata
->
dest_connid
=
ipxh
->
spx
.
sconn
;
if
(
spx_retransmit_chk
(
pdata
,
0
,
CONACK
)
<
0
)
if
(
spx_retransmit_chk
(
pdata
,
0
,
CONACK
)
<
0
)
goto
toss_skb
;
skb_queue_tail
(
&
sk
->
receive_queue
,
skb
);
wake_up_interruptible
(
sk
->
sleep
);
goto
finish
;
goto
out
;
}
spx_retransmit_chk
(
pdata
,
ipxh
->
spx
.
ackseq
,
ACK
);
goto
toss_skb
;
case
(
CCTL_ACK
)
:
case
CCTL_ACK
:
/* Informed Disconnect */
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECONN
)
{
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECONN
)
{
spx_transmit
(
sk
,
skb
,
DISACK
,
0
);
spx_close_socket
(
sk
);
goto
finish
;
goto
out
;
}
/* Fall through */
default:
if
(
ntohs
(
ipxh
->
spx
.
sequence
)
==
pdata
->
rmt_seq
)
{
if
(
ntohs
(
ipxh
->
spx
.
sequence
)
==
pdata
->
rmt_seq
)
{
pdata
->
rmt_seq
=
ntohs
(
ipxh
->
spx
.
sequence
);
pdata
->
rmt_ack
=
ntohs
(
ipxh
->
spx
.
ackseq
);
pdata
->
alloc
=
pdata
->
rmt_seq
+
3
;
if
(
pdata
->
rmt_ack
>
0
||
pdata
->
rmt_ack
==
0
)
spx_retransmit_chk
(
pdata
,
pdata
->
rmt_ack
,
ACK
);
if
(
pdata
->
rmt_ack
>
0
||
!
pdata
->
rmt_ack
)
spx_retransmit_chk
(
pdata
,
pdata
->
rmt_ack
,
ACK
);
skb_queue_tail
(
&
pdata
->
rcv_queue
,
skb
);
wake_up_interruptible
(
sk
->
sleep
);
if
(
ipxh
->
spx
.
cctl
&
CCTL_ACK
)
if
(
ipxh
->
spx
.
cctl
&
CCTL_ACK
)
spx_transmit
(
sk
,
NULL
,
ACK
,
0
);
goto
finish
;
goto
out
;
}
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECACK
)
{
if
(
pdata
->
state
!=
SPX_CLOSED
)
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECACK
)
{
if
(
pdata
->
state
!=
SPX_CLOSED
)
spx_close_socket
(
sk
);
goto
toss_skb
;
}
...
...
@@ -719,51 +683,48 @@ void spx_rcv(struct sock *sk, int bytes)
toss_skb:
/* Catch All */
kfree_skb
(
skb
);
finish:
return
;
out:
;
}
/* Get message/packet data from user-land */
static
int
spx_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
len
,
struct
scm_cookie
*
scm
)
struct
scm_cookie
*
scm
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
flags
=
msg
->
msg_flags
;
struct
sk_buff
*
skb
;
int
err
,
offset
,
size
;
int
offset
,
size
,
rc
=
-
EMSGSIZE
;
if
(
len
>
534
)
return
(
-
EMSGSIZE
);
if
(
sk
->
zapped
)
return
(
-
ENOTCONN
);
/* Socket not bound */
if
(
flags
&~
MSG_DONTWAIT
)
return
(
-
EINVAL
);
if
(
len
>
534
)
goto
out
;
rc
=
-
ENOTCONN
;
/* Socket not bound */
if
(
sk
->
zapped
)
goto
out
;
rc
=
-
EINVAL
;
if
(
flags
&
~
MSG_DONTWAIT
)
goto
out
;
offset
=
ipx_if_offset
(
spx_sk
(
sk
)
->
dest_addr
.
net
);
size
=
offset
+
sizeof
(
struct
ipxspxhdr
)
+
len
;
cli
();
skb
=
sock_alloc_send_skb
(
sk
,
size
,
flags
&
MSG_DONTWAIT
,
&
err
);
skb
=
sock_alloc_send_skb
(
sk
,
size
,
flags
&
MSG_DONTWAIT
,
&
rc
);
sti
();
if
(
skb
==
NULL
)
return
(
err
);
if
(
!
skb
)
goto
out
;
skb
->
sk
=
sk
;
skb_reserve
(
skb
,
offset
);
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxspxhdr
));
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
if
(
err
)
{
rc
=
-
EFAULT
;
if
(
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
))
{
kfree_skb
(
skb
);
return
(
-
EFAULT
)
;
goto
out
;
}
err
=
spx_transmit
(
sk
,
skb
,
DATA
,
len
);
if
(
err
)
return
(
-
EAGAIN
);
return
(
len
);
rc
=
len
;
if
(
!
spx_transmit
(
sk
,
skb
,
DATA
,
len
))
rc
=
-
EAGAIN
;
out:
return
rc
;
}
/* Send message/packet data to user-land */
...
...
@@ -775,70 +736,67 @@ static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sockaddr_ipx
*
sipx
=
(
struct
sockaddr_ipx
*
)
msg
->
msg_name
;
int
copied
,
err
;
if
(
sk
->
zapped
)
return
(
-
ENOTCONN
);
/* Socket not bound */
int
copied
,
rc
=
-
ENOTCONN
;
if
(
sk
->
zapped
)
/* Socket not bound */
goto
out
;
lock_sock
(
sk
);
restart:
while
(
skb_queue_empty
(
&
pdata
->
rcv_queue
))
/* No data */
{
while
(
skb_queue_empty
(
&
pdata
->
rcv_queue
))
{
/* No data */
/* Socket errors? */
err
=
sock_error
(
sk
);
if
(
err
)
return
(
err
);
rc
=
sock_error
(
sk
);
if
(
rc
)
goto
out_release_sock
;
/* Socket shut down? */
if
(
sk
->
shutdown
&
RCV_SHUTDOWN
)
return
(
-
ESHUTDOWN
);
rc
=
-
ESHUTDOWN
;
if
(
sk
->
shutdown
&
RCV_SHUTDOWN
)
goto
out_release_sock
;
/* handle signals */
if
(
signal_pending
(
current
))
return
(
-
ERESTARTSYS
);
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
out_release_sock
;
/* User doesn't want to wait */
if
(
flags
&
MSG_DONTWAIT
)
return
(
-
EAGAIN
);
rc
=
-
EAGAIN
;
if
(
flags
&
MSG_DONTWAIT
)
goto
out_release_sock
;
release_sock
(
sk
);
save_flags
(
flags
);
cli
();
if
(
skb_peek
(
&
pdata
->
rcv_queue
)
==
NULL
)
if
(
!
skb_peek
(
&
pdata
->
rcv_queue
)
)
interruptible_sleep_on
(
sk
->
sleep
);
restore_flags
(
flags
);
lock_sock
(
sk
);
}
skb
=
skb_dequeue
(
&
pdata
->
rcv_queue
);
if
(
skb
==
NULL
)
if
(
!
skb
)
goto
restart
;
ispxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
copied
=
ntohs
(
ispxh
->
ipx
.
ipx_pktsize
)
-
SPX_SYS_PKT_LEN
;
if
(
copied
>
size
)
{
if
(
copied
>
size
)
{
copied
=
size
;
msg
->
msg_flags
|=
MSG_TRUNC
;
}
err
=
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
nh
.
raw
+
SPX_SYS_PKT_LEN
,
copied
)
;
if
(
err
)
return
(
-
EFAULT
)
;
rc
=
-
EFAULT
;
if
(
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
nh
.
raw
+
SPX_SYS_PKT_LEN
,
copied
)
)
goto
out_kfree_skb
;
msg
->
msg_namelen
=
sizeof
(
*
sipx
);
if
(
sipx
)
{
if
(
sipx
)
{
sipx
->
sipx_family
=
AF_IPX
;
sipx
->
sipx_port
=
ispxh
->
ipx
.
ipx_source
.
sock
;
memcpy
(
sipx
->
sipx_node
,
ispxh
->
ipx
.
ipx_source
.
node
,
IPX_NODE_LEN
);
sipx
->
sipx_network
=
ispxh
->
ipx
.
ipx_source
.
net
;
sipx
->
sipx_type
=
ispxh
->
ipx
.
ipx_type
;
}
rc
=
copied
;
out_kfree_skb:
kfree_skb
(
skb
);
release_sock
(
sk
);
return
(
copied
)
;
out_release_sock:
release_sock
(
sk
);
out:
return
rc
;
}
/*
...
...
@@ -847,41 +805,31 @@ static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
static
int
spx_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
int
err
;
err
=
ipx_operations
->
bind
(
sock
,
uaddr
,
addr_len
);
return
(
err
);
return
ipx_ops
->
bind
(
sock
,
uaddr
,
addr_len
);
}
static
int
spx_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
usockaddr_len
,
int
peer
)
{
int
err
;
err
=
ipx_operations
->
getname
(
sock
,
uaddr
,
usockaddr_len
,
peer
);
return
(
err
);
return
ipx_ops
->
getname
(
sock
,
uaddr
,
usockaddr_len
,
peer
);
}
static
int
spx_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
err
;
err
=
ipx_operations
->
ioctl
(
sock
,
cmd
,
arg
);
return
(
err
);
return
ipx_ops
->
ioctl
(
sock
,
cmd
,
arg
);
}
static
int
spx_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
int
err
;
err
=
ipx_operations
->
setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
return
(
err
);
return
ipx_ops
->
setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
static
int
spx_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
int
err
;
err
=
ipx_operations
->
getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
return
(
err
);
return
ipx_ops
->
getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
spx_ops
)
=
{
...
...
@@ -911,16 +859,13 @@ SOCKOPS_WRAP(spx, PF_IPX);
static
struct
net_proto_family
spx_family_ops
=
{
family:
PF_IPX
,
create:
spx_create
,
sk_size:
sizeof
(
struct
sock
)
+
sizeof
(
struct
ipx_opt
)
+
sizeof
(
struct
spx_opt
),
};
static
char
banner
[]
__initdata
=
KERN_INFO
"NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0
\n
"
;
static
char
banner
[]
__initdata
=
KERN_INFO
"NET4: Sequenced Packet eXchange (SPX) 0.03
\n
"
;
static
int
__init
spx_proto_init
(
void
)
{
int
error
;
connids
=
(
__u16
)
jiffies
;
/* initalize random */
/* allocate our sock slab cache */
...
...
@@ -933,8 +878,7 @@ static int __init spx_proto_init(void)
printk
(
KERN_CRIT
__FUNCTION__
": Cannot create spx_sock SLAB cache!
\n
"
);
error
=
ipx_register_spx
(
&
ipx_operations
,
&
spx_family_ops
);
if
(
error
)
if
(
ipx_register_spx
(
&
ipx_ops
,
&
spx_family_ops
))
printk
(
KERN_ERR
"SPX: unable to register with IPX.
\n
"
);
/* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
...
...
@@ -942,11 +886,12 @@ static int __init spx_proto_init(void)
printk
(
banner
);
return
0
;
}
module_init
(
spx_proto_init
);
static
void
__exit
spx_proto_finito
(
void
)
{
ipx_unregister_spx
();
return
;
}
module_init
(
spx_proto_init
);
module_exit
(
spx_proto_finito
);
MODULE_LICENSE
(
"GPL"
);
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