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
a914f3da
Commit
a914f3da
authored
Aug 02, 2002
by
Arnaldo Carvalho de Melo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove SPX and the last typedefs in IPX, create ipx_hdr
parent
d52a86be
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
200 additions
and
1258 deletions
+200
-1258
include/linux/ipx.h
include/linux/ipx.h
+6
-18
include/linux/skbuff.h
include/linux/skbuff.h
+0
-2
include/net/ipx.h
include/net/ipx.h
+17
-16
include/net/spx.h
include/net/spx.h
+0
-95
net/ipx/Config.help
net/ipx/Config.help
+0
-22
net/ipx/Config.in
net/ipx/Config.in
+0
-3
net/ipx/Makefile
net/ipx/Makefile
+0
-1
net/ipx/af_ipx.c
net/ipx/af_ipx.c
+151
-193
net/ipx/af_spx.c
net/ipx/af_spx.c
+0
-897
net/ipx/sysctl_net_ipx.c
net/ipx/sysctl_net_ipx.c
+26
-11
No files found.
include/linux/ipx.h
View file @
a914f3da
...
...
@@ -24,15 +24,13 @@ struct sockaddr_ipx
#define IPX_DLTITF 0
#define IPX_CRTITF 1
typedef
struct
ipx_route_definition
{
struct
ipx_route_definition
{
__u32
ipx_network
;
__u32
ipx_router_network
;
unsigned
char
ipx_router_node
[
IPX_NODE_LEN
];
}
ipx_route_definition
;
};
typedef
struct
ipx_interface_definition
{
struct
ipx_interface_definition
{
__u32
ipx_network
;
unsigned
char
ipx_device
[
16
];
unsigned
char
ipx_dlink_type
;
...
...
@@ -47,13 +45,12 @@ typedef struct ipx_interface_definition
#define IPX_PRIMARY 1
#define IPX_INTERNAL 2
unsigned
char
ipx_node
[
IPX_NODE_LEN
];
}
ipx_interface_definition
;
};
typedef
struct
ipx_config_data
{
struct
ipx_config_data
{
unsigned
char
ipxcfg_auto_select_primary
;
unsigned
char
ipxcfg_auto_create_interfaces
;
}
ipx_config_data
;
};
/*
* OLD Route Definition for backward compatibility.
...
...
@@ -77,13 +74,4 @@ struct ipx_route_def
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
#ifdef __KERNEL__
#include <linux/skbuff.h>
extern
int
ipxrtr_route_skb
(
struct
sk_buff
*
);
extern
int
ipx_if_offset
(
unsigned
long
ipx_net_number
);
extern
void
ipx_remove_socket
(
struct
sock
*
sk
);
#endif
/* def __KERNEL__ */
#endif
/* def _IPX_H_ */
include/linux/skbuff.h
View file @
a914f3da
...
...
@@ -182,7 +182,6 @@ struct sk_buff {
struct
icmphdr
*
icmph
;
struct
igmphdr
*
igmph
;
struct
iphdr
*
ipiph
;
struct
spxhdr
*
spxh
;
unsigned
char
*
raw
;
}
h
;
...
...
@@ -190,7 +189,6 @@ struct sk_buff {
struct
iphdr
*
iph
;
struct
ipv6hdr
*
ipv6h
;
struct
arphdr
*
arph
;
struct
ipxhdr
*
ipxh
;
unsigned
char
*
raw
;
}
nh
;
...
...
include/net/ipx.h
View file @
a914f3da
...
...
@@ -14,12 +14,11 @@
#include <net/datalink.h>
#include <linux/ipx.h>
typedef
struct
{
struct
ipx_address
{
__u32
net
;
__u8
node
[
IPX_NODE_LEN
];
__u16
sock
;
}
ipx_address
;
};
#define ipx_broadcast_node "\377\377\377\377\377\377"
#define ipx_this_node "\0\0\0\0\0\0"
...
...
@@ -39,11 +38,16 @@ struct ipxhdr
#define IPX_TYPE_SPX 0x05
/* SPX protocol */
#define IPX_TYPE_NCP 0x11
/* $lots for docs on this (SPIT) */
#define IPX_TYPE_PPROP 0x14
/* complicated flood fill brdcast */
ipx_address
ipx_dest
__attribute__
((
packed
));
ipx_address
ipx_source
__attribute__
((
packed
));
struct
ipx_address
ipx_dest
__attribute__
((
packed
));
struct
ipx_address
ipx_source
__attribute__
((
packed
));
};
typedef
struct
ipx_interface
{
static
__inline__
struct
ipxhdr
*
ipx_hdr
(
struct
sk_buff
*
skb
)
{
return
(
struct
ipxhdr
*
)
skb
->
h
.
raw
;
}
struct
ipx_interface
{
/* IPX address */
__u32
if_netnum
;
unsigned
char
if_node
[
IPX_NODE_LEN
];
...
...
@@ -65,16 +69,16 @@ typedef struct ipx_interface {
unsigned
char
if_primary
;
struct
ipx_interface
*
if_next
;
}
ipx_interface
;
};
typedef
struct
ipx_route
{
struct
ipx_route
{
__u32
ir_net
;
ipx_interface
*
ir_intrfc
;
struct
ipx_interface
*
ir_intrfc
;
unsigned
char
ir_routed
;
unsigned
char
ir_router_node
[
IPX_NODE_LEN
];
struct
ipx_route
*
ir_next
;
struct
ipx_route
*
ir_next
;
atomic_t
refcnt
;
}
ipx_route
;
};
#ifdef __KERNEL__
struct
ipx_cb
{
...
...
@@ -88,8 +92,8 @@ struct ipx_cb {
};
struct
ipx_opt
{
ipx_address
dest_addr
;
ipx_interface
*
intrfc
;
struct
ipx_address
dest_addr
;
struct
ipx_interface
*
intrfc
;
unsigned
short
port
;
#ifdef CONFIG_IPX_INTERN
unsigned
char
node
[
IPX_NODE_LEN
];
...
...
@@ -106,7 +110,4 @@ struct ipx_opt {
#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
extern
int
ipx_register_spx
(
struct
proto_ops
**
,
struct
net_proto_family
*
);
extern
int
ipx_unregister_spx
(
void
);
#endif
/* def _NET_INET_IPX_H_ */
include/net/spx.h
deleted
100644 → 0
View file @
d52a86be
#ifndef __NET_SPX_H
#define __NET_SPX_H
#include <net/ipx.h>
struct
spxhdr
{
__u8
cctl
;
__u8
dtype
;
#define SPX_DTYPE_ECONN 0xFE
/* Finished */
#define SPX_DTYPE_ECACK 0xFF
/* Ok */
__u16
sconn
;
/* Connection ID */
__u16
dconn
;
/* Connection ID */
__u16
sequence
;
__u16
ackseq
;
__u16
allocseq
;
};
struct
ipxspxhdr
{
struct
ipxhdr
ipx
;
struct
spxhdr
spx
;
};
#define SPX_SYS_PKT_LEN (sizeof(struct ipxspxhdr))
#ifdef __KERNEL__
struct
spx_opt
{
int
state
;
int
sndbuf
;
int
retries
;
/* Number of WD retries */
int
retransmits
;
/* Number of retransmits */
int
max_retries
;
int
wd_interval
;
void
*
owner
;
__u16
dest_connid
;
/* Net order */
__u16
source_connid
;
/* Net order */
__u16
sequence
;
/* Host order - our current pkt # */
__u16
alloc
;
/* Host order - max seq we can rcv now */
__u16
rmt_ack
;
/* Host order - last pkt ACKd by remote */
__u16
rmt_seq
;
__u16
acknowledge
;
__u16
rmt_alloc
;
/* Host order - max seq remote can handle now */
ipx_address
dest_addr
;
ipx_address
source_addr
;
struct
timer_list
watchdog
;
/* Idle watch */
struct
timer_list
retransmit
;
/* Retransmit timer */
struct
sk_buff_head
rcv_queue
;
struct
sk_buff_head
transmit_queue
;
struct
sk_buff_head
retransmit_queue
;
};
#define spx_sk(__sk) ((struct spx_opt *)(((struct sock *)(__sk)) + 1))
/* Packet connectino control defines */
#define CCTL_SPXII_XHD 0x01
/* SPX2 extended header */
#define CCTL_SPX_UNKNOWN 0x02
/* Unknown (unused ??) */
#define CCTL_SPXII_NEG 0x04
/* Negotiate size */
#define CCTL_SPXII 0x08
/* Set for SPX2 */
#define CCTL_EOM 0x10
/* End of message marker */
#define CCTL_URG 0x20
/* Urgent marker in SPP (not used in SPX?) */
#define CCTL_ACK 0x40
/* Send me an ACK */
#define CCTL_CTL 0x80
/* Control message */
#define CCTL_SYS CCTL_CTL
/* Spec uses CCTL_SYS */
/* Connection state defines */
#define SPX_CLOSED 7
#define SPX_CONNECTING 8
#define SPX_CONNECTED 9
/* Packet transmit types - Internal */
#define DATA 0
/* Data */
#define ACK 1
/* Data ACK */
#define WDACK 2
/* WD ACK */
#define CONACK 3
/* Connection Request ACK */
#define CONREQ 4
/* Connection Request */
#define WDREQ 5
/* WD Request */
#define DISCON 6
/* Informed Disconnect */
#define DISACK 7
/* Informed Disconnect ACK */
#define RETRAN 8
/* Int. Retransmit of packet */
#define TQUEUE 9
/* Int. Transmit of a queued packet */
/*
* These are good canidates for IOcontrol calls
*/
/* Watchdog defines */
#define VERIFY_TIMEOUT 3 * HZ
#define ABORT_TIMEOUT 30 * HZ
/* Packet retransmit defines */
#define RETRY_COUNT 10
#define RETRY_TIME 1 * HZ
#define MAX_RETRY_DELAY 5 * HZ
#endif
/* __KERNEL__ */
#endif
/* def __NET_SPX_H */
net/ipx/Config.help
View file @
a914f3da
...
...
@@ -23,25 +23,3 @@ CONFIG_IPX_INTERN
If you don't know what you are doing, say N.
CONFIG_SPX
* Orphaned entry retained 20 April 2001 by Petr Vandrovec *
* If you read this note from the configurator, please contact *
* the Configure.help maintainers. *
The Sequenced Packet eXchange protocol is a transport layer protocol
built on top of IPX. It is used in Novell NetWare systems for
client-server applications and is similar to TCP (which runs on top
of IP).
Note that Novell NetWare file sharing does not use SPX; it uses a
protocol called NCP, for which separate Linux support is available
("NCP file system support" below for the client side, and the user
space programs lwared or mars_nwe for the server side).
Say Y here if you have use for SPX; read the IPX-HOWTO at
<http://www.linuxdoc.org/docs.html#howto> for details.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called af_spx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
net/ipx/Config.in
View file @
a914f3da
...
...
@@ -3,6 +3,3 @@
#
bool ' IPX: Full internal IPX network' CONFIG_IPX_INTERN
#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
# dep_tristate ' IPX: SPX networking (EXPERIMENTAL)' CONFIG_SPX $CONFIG_IPX
#fi
net/ipx/Makefile
View file @
a914f3da
...
...
@@ -8,7 +8,6 @@ obj-$(CONFIG_IPX) += ipx.o
ipx-y
:=
af_ipx.o
ipx-$(CONFIG_SYSCTL)
+=
sysctl_net_ipx.o
ipx-$(CONFIG_SPX)
+=
af_spx.o
ipx-objs
:=
$
(
ipx-y
)
include
$(TOPDIR)/Rules.make
net/ipx/af_ipx.c
View file @
a914f3da
...
...
@@ -76,6 +76,7 @@
* Revision 048: Use sk->protinfo to store the pointer to IPX private
* area, remove af_ipx from sk->protinfo and move ipx_opt
* to include/net/ipx.h, use IPX_SK like DecNET, etc
* Revision 049: SPX support dropped, see comment in ipx_create
*
* Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
* pair. Also, now usage count is managed this way
...
...
@@ -144,17 +145,14 @@ static struct datalink_proto *pSNAP_datalink;
static
struct
proto_ops
ipx_dgram_ops
;
static
struct
net_proto_family
*
spx_family_ops
;
static
DECLARE_RWSEM
(
spx_family_ops_lock
);
static
ipx_route
*
ipx_routes
;
static
struct
ipx_route
*
ipx_routes
;
static
rwlock_t
ipx_routes_lock
=
RW_LOCK_UNLOCKED
;
static
ipx_interface
*
ipx_interfaces
;
static
struct
ipx_interface
*
ipx_interfaces
;
static
spinlock_t
ipx_interfaces_lock
=
SPIN_LOCK_UNLOCKED
;
static
ipx_interface
*
ipx_primary_net
;
static
ipx_interface
*
ipx_internal_net
;
static
struct
ipx_interface
*
ipx_primary_net
;
static
struct
ipx_interface
*
ipx_internal_net
;
#undef IPX_REFCNT_DEBUG
#ifdef IPX_REFCNT_DEBUG
...
...
@@ -180,9 +178,9 @@ static void ipxcfg_set_auto_select(char val)
ipx_primary_net
=
ipx_interfaces
;
}
static
int
ipxcfg_get_config_data
(
ipx_config_data
*
arg
)
static
int
ipxcfg_get_config_data
(
struct
ipx_config_data
*
arg
)
{
ipx_config_data
vals
;
struct
ipx_config_data
vals
;
vals
.
ipxcfg_auto_create_interfaces
=
ipxcfg_auto_create_interfaces
;
vals
.
ipxcfg_auto_select_primary
=
ipxcfg_auto_select_primary
;
...
...
@@ -192,22 +190,22 @@ static int ipxcfg_get_config_data(ipx_config_data *arg)
/* Handlers for the socket list. */
static
inline
void
ipxitf_hold
(
ipx_interface
*
intrfc
)
static
__inline__
void
ipxitf_hold
(
struct
ipx_interface
*
intrfc
)
{
atomic_inc
(
&
intrfc
->
refcnt
);
}
static
void
ipxitf_down
(
ipx_interface
*
intrfc
);
static
void
ipxitf_down
(
struct
ipx_interface
*
intrfc
);
static
inline
void
ipxitf_put
(
ipx_interface
*
intrfc
)
static
__inline__
void
ipxitf_put
(
struct
ipx_interface
*
intrfc
)
{
if
(
atomic_dec_and_test
(
&
intrfc
->
refcnt
))
ipxitf_down
(
intrfc
);
}
static
void
__ipxitf_down
(
ipx_interface
*
intrfc
);
static
void
__ipxitf_down
(
struct
ipx_interface
*
intrfc
);
static
inline
void
__ipxitf_put
(
ipx_interface
*
intrfc
)
static
__inline__
void
__ipxitf_put
(
struct
ipx_interface
*
intrfc
)
{
if
(
atomic_dec_and_test
(
&
intrfc
->
refcnt
))
__ipxitf_down
(
intrfc
);
...
...
@@ -218,11 +216,11 @@ static inline void __ipxitf_put(ipx_interface *intrfc)
* use this facility.
*/
void
ipx_remove_socket
(
struct
sock
*
sk
)
static
void
ipx_remove_socket
(
struct
sock
*
sk
)
{
struct
sock
*
s
;
/* Determine interface with which socket is associated */
ipx_interface
*
intrfc
=
ipx_sk
(
sk
)
->
intrfc
;
struct
ipx_interface
*
intrfc
=
ipx_sk
(
sk
)
->
intrfc
;
if
(
!
intrfc
)
goto
out
;
...
...
@@ -268,7 +266,7 @@ static void ipx_destroy_socket(struct sock *sk)
* The following code is used to support IPX Interfaces (IPXITF). An
* IPX interface is defined by a physical device and a frame type.
*/
static
ipx_route
*
ipxrtr_lookup
(
__u32
);
static
struct
ipx_route
*
ipxrtr_lookup
(
__u32
net
);
/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */
...
...
@@ -277,10 +275,10 @@ static void ipxitf_clear_primary_net(void)
ipx_primary_net
=
ipxcfg_auto_select_primary
?
ipx_interfaces
:
NULL
;
}
static
ipx_interface
*
__ipxitf_find_using_phys
(
struct
net_device
*
dev
,
unsigned
short
datalink
)
static
struct
ipx_interface
*
__ipxitf_find_using_phys
(
struct
net_device
*
dev
,
unsigned
short
datalink
)
{
ipx_interface
*
i
=
ipx_interfaces
;
struct
ipx_interface
*
i
=
ipx_interfaces
;
while
(
i
&&
(
i
->
if_dev
!=
dev
||
i
->
if_dlink_type
!=
datalink
))
i
=
i
->
if_next
;
...
...
@@ -288,10 +286,10 @@ static ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
return
i
;
}
static
ipx_interface
*
ipxitf_find_using_phys
(
struct
net_device
*
dev
,
unsigned
short
datalink
)
static
struct
ipx_interface
*
ipxitf_find_using_phys
(
struct
net_device
*
dev
,
unsigned
short
datalink
)
{
ipx_interface
*
i
;
struct
ipx_interface
*
i
;
spin_lock_bh
(
&
ipx_interfaces_lock
);
i
=
__ipxitf_find_using_phys
(
dev
,
datalink
);
...
...
@@ -301,9 +299,9 @@ static ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
return
i
;
}
static
ipx_interface
*
ipxitf_find_using_net
(
__u32
net
)
static
struct
ipx_interface
*
ipxitf_find_using_net
(
__u32
net
)
{
ipx_interface
*
i
;
struct
ipx_interface
*
i
;
spin_lock_bh
(
&
ipx_interfaces_lock
);
if
(
net
)
...
...
@@ -320,7 +318,7 @@ static ipx_interface *ipxitf_find_using_net(__u32 net)
}
/* Sockets are bound to a particular IPX interface. */
static
void
ipxitf_insert_socket
(
ipx_interface
*
intrfc
,
struct
sock
*
sk
)
static
void
ipxitf_insert_socket
(
struct
ipx_interface
*
intrfc
,
struct
sock
*
sk
)
{
ipxitf_hold
(
intrfc
);
sock_hold
(
sk
);
...
...
@@ -340,7 +338,7 @@ static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
}
/* caller must hold intrfc->if_sklist_lock */
static
struct
sock
*
__ipxitf_find_socket
(
ipx_interface
*
intrfc
,
static
struct
sock
*
__ipxitf_find_socket
(
struct
ipx_interface
*
intrfc
,
unsigned
short
port
)
{
struct
sock
*
s
=
intrfc
->
if_sklist
;
...
...
@@ -352,7 +350,7 @@ static struct sock *__ipxitf_find_socket(ipx_interface *intrfc,
}
/* caller must hold a reference to intrfc */
static
struct
sock
*
ipxitf_find_socket
(
ipx_interface
*
intrfc
,
static
struct
sock
*
ipxitf_find_socket
(
struct
ipx_interface
*
intrfc
,
unsigned
short
port
)
{
struct
sock
*
s
;
...
...
@@ -367,8 +365,9 @@ static struct sock *ipxitf_find_socket(ipx_interface *intrfc,
}
#ifdef CONFIG_IPX_INTERN
static
struct
sock
*
ipxitf_find_internal_socket
(
ipx_interface
*
intrfc
,
unsigned
char
*
node
,
unsigned
short
port
)
static
struct
sock
*
ipxitf_find_internal_socket
(
struct
ipx_interface
*
intrfc
,
unsigned
char
*
node
,
unsigned
short
port
)
{
struct
sock
*
s
;
...
...
@@ -391,9 +390,9 @@ static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
}
#endif
static
void
ipxrtr_del_routes
(
ipx_interface
*
);
static
void
ipxrtr_del_routes
(
struct
ipx_interface
*
intrfc
);
static
void
__ipxitf_down
(
ipx_interface
*
intrfc
)
static
void
__ipxitf_down
(
struct
ipx_interface
*
intrfc
)
{
struct
sock
*
s
,
*
t
;
...
...
@@ -421,7 +420,7 @@ static void __ipxitf_down(ipx_interface *intrfc)
if
(
intrfc
==
ipx_interfaces
)
ipx_interfaces
=
intrfc
->
if_next
;
else
{
ipx_interface
*
i
=
ipx_interfaces
;
struct
ipx_interface
*
i
=
ipx_interfaces
;
while
(
i
&&
i
->
if_next
!=
intrfc
)
i
=
i
->
if_next
;
if
(
i
&&
i
->
if_next
==
intrfc
)
...
...
@@ -440,7 +439,7 @@ static void __ipxitf_down(ipx_interface *intrfc)
MOD_DEC_USE_COUNT
;
}
static
void
ipxitf_down
(
ipx_interface
*
intrfc
)
static
void
ipxitf_down
(
struct
ipx_interface
*
intrfc
)
{
spin_lock_bh
(
&
ipx_interfaces_lock
);
__ipxitf_down
(
intrfc
);
...
...
@@ -451,7 +450,7 @@ static int ipxitf_device_event(struct notifier_block *notifier,
unsigned
long
event
,
void
*
ptr
)
{
struct
net_device
*
dev
=
ptr
;
ipx_interface
*
i
,
*
tmp
;
struct
ipx_interface
*
i
,
*
tmp
;
if
(
event
!=
NETDEV_DOWN
&&
event
!=
NETDEV_UP
)
goto
out
;
...
...
@@ -484,10 +483,10 @@ static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
/* caller must hold a reference to intrfc */
#ifdef CONFIG_IPX_INTERN
static
int
ipxitf_demux_socket
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
int
copy
)
static
int
ipxitf_demux_socket
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
int
copy
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
int
is_broadcast
=
!
memcmp
(
ipx
->
ipx_dest
.
node
,
ipx_broadcast_node
,
IPX_NODE_LEN
);
struct
sock
*
s
;
...
...
@@ -532,7 +531,7 @@ out: spin_unlock_bh(&intrfc->if_sklist_lock);
return
ret
;
}
#else
static
struct
sock
*
ncp_connection_hack
(
ipx_interface
*
intrfc
,
static
struct
sock
*
ncp_connection_hack
(
struct
ipx_interface
*
intrfc
,
struct
ipxhdr
*
ipx
)
{
/* The packet's target is a NCP connection handler. We want to hand it
...
...
@@ -566,10 +565,10 @@ static struct sock *ncp_connection_hack(ipx_interface *intrfc,
return
sk
;
}
static
int
ipxitf_demux_socket
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
int
copy
)
static
int
ipxitf_demux_socket
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
int
copy
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
struct
sock
*
sock1
=
NULL
,
*
sock2
=
NULL
;
struct
sk_buff
*
skb1
=
NULL
,
*
skb2
=
NULL
;
int
ret
;
...
...
@@ -651,11 +650,11 @@ out: if (sock1)
}
#endif
/* CONFIG_IPX_INTERN */
static
struct
sk_buff
*
ipxitf_adjust_skbuff
(
ipx_interface
*
intrfc
,
static
struct
sk_buff
*
ipxitf_adjust_skbuff
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
{
struct
sk_buff
*
skb2
;
int
in_offset
=
skb
->
h
.
raw
-
skb
->
head
;
int
in_offset
=
(
unsigned
char
*
)
ipx_hdr
(
skb
)
-
skb
->
head
;
int
out_offset
=
intrfc
->
if_ipx_offset
;
int
len
;
...
...
@@ -669,7 +668,7 @@ static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc,
if
(
skb2
)
{
skb_reserve
(
skb2
,
out_offset
);
skb2
->
nh
.
raw
=
skb2
->
h
.
raw
=
skb_put
(
skb2
,
skb
->
len
);
memcpy
(
skb2
->
h
.
raw
,
skb
->
h
.
raw
,
skb
->
len
);
memcpy
(
ipx_hdr
(
skb2
),
ipx_hdr
(
skb
)
,
skb
->
len
);
memcpy
(
skb2
->
cb
,
skb
->
cb
,
sizeof
(
skb
->
cb
));
}
kfree_skb
(
skb
);
...
...
@@ -678,9 +677,10 @@ static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc,
/* caller must hold a reference to intrfc and the skb has to be unshared */
static
int
ipxitf_send
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
char
*
node
)
static
int
ipxitf_send
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
,
char
*
node
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
struct
net_device
*
dev
=
intrfc
->
if_dev
;
struct
datalink_proto
*
dl
=
intrfc
->
if_dlink
;
char
dest_node
[
IPX_NODE_LEN
];
...
...
@@ -784,21 +784,24 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
out:
return
0
;
}
static
int
ipxrtr_add_route
(
__u32
,
ipx_interface
*
,
unsigned
char
*
);
static
int
ipxrtr_add_route
(
__u32
network
,
struct
ipx_interface
*
intrfc
,
unsigned
char
*
);
static
int
ipxitf_add_local_route
(
ipx_interface
*
intrfc
)
static
int
ipxitf_add_local_route
(
struct
ipx_interface
*
intrfc
)
{
return
ipxrtr_add_route
(
intrfc
->
if_netnum
,
intrfc
,
NULL
);
}
static
const
char
*
ipx_frame_name
(
unsigned
short
);
static
const
char
*
ipx_device_name
(
ipx_interface
*
);
static
void
ipxitf_discover_netnum
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
);
static
int
ipxitf_pprop
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
);
static
const
char
*
ipx_frame_name
(
unsigned
short
);
static
const
char
*
ipx_device_name
(
struct
ipx_interface
*
);
static
void
ipxitf_discover_netnum
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
);
static
int
ipxitf_pprop
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
);
static
int
ipxrtr_route_skb
(
struct
sk_buff
*
skb
);
static
int
ipxitf_rcv
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
static
int
ipxitf_rcv
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
int
ret
=
0
;
ipxitf_hold
(
intrfc
);
...
...
@@ -850,13 +853,15 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
return
ret
;
}
static
void
ipxitf_discover_netnum
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
static
void
ipxitf_discover_netnum
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
{
const
struct
ipx_cb
*
cb
=
IPX_SKB_CB
(
skb
);
/* see if this is an intra packet: source_net == dest_net */
if
(
cb
->
ipx_source_net
==
cb
->
ipx_dest_net
&&
cb
->
ipx_source_net
)
{
ipx_interface
*
i
=
ipxitf_find_using_net
(
cb
->
ipx_source_net
);
struct
ipx_interface
*
i
=
ipxitf_find_using_net
(
cb
->
ipx_source_net
);
/* NB: NetWare servers lie about their hop count so we
* dropped the test based on it. This is the best way
* to determine this is a 0 hop count packet. */
...
...
@@ -900,11 +905,11 @@ static void ipxitf_discover_netnum(ipx_interface *intrfc, struct sk_buff *skb)
* Returns -EINVAL for invalid packets, so that the calling function drops
* the packet without local processing. 0 if packet is to be locally processed.
*/
static
int
ipxitf_pprop
(
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
static
int
ipxitf_pprop
(
struct
ipx_interface
*
intrfc
,
struct
sk_buff
*
skb
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
int
i
,
ret
=
-
EINVAL
;
ipx_interface
*
ifcs
;
struct
ipx_interface
*
ifcs
;
char
*
c
;
u32
*
l
;
...
...
@@ -968,14 +973,14 @@ static int ipxitf_pprop(ipx_interface *intrfc, struct sk_buff *skb)
out:
return
ret
;
}
static
void
ipxitf_insert
(
ipx_interface
*
intrfc
)
static
void
ipxitf_insert
(
struct
ipx_interface
*
intrfc
)
{
intrfc
->
if_next
=
NULL
;
spin_lock_bh
(
&
ipx_interfaces_lock
);
if
(
!
ipx_interfaces
)
ipx_interfaces
=
intrfc
;
else
{
ipx_interface
*
i
=
ipx_interfaces
;
struct
ipx_interface
*
i
=
ipx_interfaces
;
while
(
i
->
if_next
)
i
=
i
->
if_next
;
i
->
if_next
=
intrfc
;
...
...
@@ -986,12 +991,13 @@ static void ipxitf_insert(ipx_interface *intrfc)
ipx_primary_net
=
intrfc
;
}
static
ipx_interface
*
ipxitf_alloc
(
struct
net_device
*
dev
,
__u32
netnum
,
unsigned
short
dlink_type
,
struct
datalink_proto
*
dlink
,
unsigned
char
internal
,
int
ipx_offset
)
static
struct
ipx_interface
*
ipxitf_alloc
(
struct
net_device
*
dev
,
__u32
netnum
,
unsigned
short
dlink_type
,
struct
datalink_proto
*
dlink
,
unsigned
char
internal
,
int
ipx_offset
)
{
ipx_interface
*
intrfc
=
kmalloc
(
sizeof
(
*
intrfc
),
GFP_ATOMIC
);
struct
ipx_interface
*
intrfc
=
kmalloc
(
sizeof
(
*
intrfc
),
GFP_ATOMIC
);
if
(
intrfc
)
{
intrfc
->
if_dev
=
dev
;
...
...
@@ -1010,9 +1016,9 @@ static ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum,
return
intrfc
;
}
static
int
ipxitf_create_internal
(
ipx_interface_definition
*
idef
)
static
int
ipxitf_create_internal
(
struct
ipx_interface_definition
*
idef
)
{
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
int
ret
=
-
EEXIST
;
/* Only one primary network allowed */
...
...
@@ -1061,12 +1067,12 @@ static int ipx_map_frame_type(unsigned char type)
return
ret
;
}
static
int
ipxitf_create
(
ipx_interface_definition
*
idef
)
static
int
ipxitf_create
(
struct
ipx_interface_definition
*
idef
)
{
struct
net_device
*
dev
;
unsigned
short
dlink_type
=
0
;
struct
datalink_proto
*
datalink
=
NULL
;
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
int
err
;
if
(
idef
->
ipx_special
==
IPX_INTERNAL
)
{
...
...
@@ -1173,11 +1179,11 @@ static int ipxitf_create(ipx_interface_definition *idef)
out:
return
err
;
}
static
int
ipxitf_delete
(
ipx_interface_definition
*
idef
)
static
int
ipxitf_delete
(
struct
ipx_interface_definition
*
idef
)
{
struct
net_device
*
dev
=
NULL
;
unsigned
short
dlink_type
=
0
;
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
int
ret
=
0
;
spin_lock_bh
(
&
ipx_interfaces_lock
);
...
...
@@ -1211,10 +1217,10 @@ out: spin_unlock_bh(&ipx_interfaces_lock);
return
ret
;
}
static
ipx_interface
*
ipxitf_auto_create
(
struct
net_device
*
dev
,
unsigned
short
dlink_type
)
static
struct
ipx_interface
*
ipxitf_auto_create
(
struct
net_device
*
dev
,
unsigned
short
dlink_type
)
{
ipx_interface
*
intrfc
=
NULL
;
struct
ipx_interface
*
intrfc
=
NULL
;
struct
datalink_proto
*
datalink
;
if
(
!
dev
)
...
...
@@ -1269,7 +1275,7 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg)
switch
(
cmd
)
{
case
SIOCSIFADDR
:
{
struct
sockaddr_ipx
*
sipx
;
ipx_interface_definition
f
;
struct
ipx_interface_definition
f
;
if
(
copy_from_user
(
&
ifr
,
arg
,
sizeof
(
ifr
)))
return
-
EFAULT
;
...
...
@@ -1294,7 +1300,7 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg)
case
SIOCGIFADDR
:
{
int
err
=
0
;
struct
sockaddr_ipx
*
sipx
;
ipx_interface
*
ipxif
;
struct
ipx_interface
*
ipxif
;
struct
net_device
*
dev
;
if
(
copy_from_user
(
&
ifr
,
arg
,
sizeof
(
ifr
)))
...
...
@@ -1341,20 +1347,20 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg)
/* Routing tables for the IPX socket layer. */
static
inline
void
ipxrtr_hold
(
ipx_route
*
rt
)
static
__inline__
void
ipxrtr_hold
(
struct
ipx_route
*
rt
)
{
atomic_inc
(
&
rt
->
refcnt
);
}
static
inline
void
ipxrtr_put
(
ipx_route
*
rt
)
static
__inline__
void
ipxrtr_put
(
struct
ipx_route
*
rt
)
{
if
(
atomic_dec_and_test
(
&
rt
->
refcnt
))
kfree
(
rt
);
}
static
ipx_route
*
ipxrtr_lookup
(
__u32
net
)
static
struct
ipx_route
*
ipxrtr_lookup
(
__u32
net
)
{
ipx_route
*
r
;
struct
ipx_route
*
r
;
read_lock_bh
(
&
ipx_routes_lock
);
for
(
r
=
ipx_routes
;
r
&&
r
->
ir_net
!=
net
;
r
=
r
->
ir_next
)
...
...
@@ -1368,16 +1374,16 @@ static ipx_route *ipxrtr_lookup(__u32 net)
/* caller must hold a reference to intrfc */
static
int
ipxrtr_add_route
(
__u32
network
,
ipx_interface
*
intrfc
,
unsigned
char
*
node
)
static
int
ipxrtr_add_route
(
__u32
network
,
struct
ipx_interface
*
intrfc
,
unsigned
char
*
node
)
{
ipx_route
*
rt
;
struct
ipx_route
*
rt
;
int
ret
;
/* Get a route structure; either existing or create */
rt
=
ipxrtr_lookup
(
network
);
if
(
!
rt
)
{
rt
=
kmalloc
(
sizeof
(
ipx_route
),
GFP_ATOMIC
);
rt
=
kmalloc
(
sizeof
(
*
rt
),
GFP_ATOMIC
);
ret
=
-
EAGAIN
;
if
(
!
rt
)
goto
out
;
...
...
@@ -1410,9 +1416,9 @@ static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc,
out:
return
ret
;
}
static
void
ipxrtr_del_routes
(
ipx_interface
*
intrfc
)
static
void
ipxrtr_del_routes
(
struct
ipx_interface
*
intrfc
)
{
ipx_route
**
r
,
*
tmp
;
struct
ipx_route
**
r
,
*
tmp
;
write_lock_bh
(
&
ipx_routes_lock
);
for
(
r
=
&
ipx_routes
;
(
tmp
=
*
r
)
!=
NULL
;)
{
...
...
@@ -1425,9 +1431,9 @@ static void ipxrtr_del_routes(ipx_interface *intrfc)
write_unlock_bh
(
&
ipx_routes_lock
);
}
static
int
ipxrtr_create
(
ipx_route_definition
*
rd
)
static
int
ipxrtr_create
(
struct
ipx_route_definition
*
rd
)
{
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
int
ret
=
-
ENETUNREACH
;
/* Find the appropriate interface */
...
...
@@ -1441,8 +1447,8 @@ out: return ret;
static
int
ipxrtr_delete
(
long
net
)
{
ipx_route
**
r
;
ipx_route
*
tmp
;
struct
ipx_route
**
r
;
struct
ipx_route
*
tmp
;
int
err
;
write_lock_bh
(
&
ipx_routes_lock
);
...
...
@@ -1513,11 +1519,11 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
{
struct
sk_buff
*
skb
;
struct
ipx_opt
*
ipxs
=
ipx_sk
(
sk
);
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
struct
ipxhdr
*
ipx
;
int
size
;
int
ipx_offset
;
ipx_route
*
rt
=
NULL
;
struct
ipx_route
*
rt
=
NULL
;
int
err
;
/* Find the appropriate interface on which to send packet */
...
...
@@ -1544,11 +1550,11 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
skb
->
sk
=
sk
;
/* Fill in IPX header */
ipx
=
(
struct
ipxhdr
*
)
skb_put
(
skb
,
sizeof
(
struct
ipxhdr
));
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxhdr
));
ipx
=
ipx_hdr
(
skb
);
ipx
->
ipx_pktsize
=
htons
(
len
+
sizeof
(
struct
ipxhdr
));
IPX_SKB_CB
(
skb
)
->
ipx_tctrl
=
0
;
ipx
->
ipx_type
=
usipx
->
sipx_type
;
skb
->
h
.
raw
=
(
void
*
)
skb
->
nh
.
ipxh
=
ipx
;
IPX_SKB_CB
(
skb
)
->
last_hop
.
index
=
-
1
;
#ifdef CONFIG_IPX_INTERN
...
...
@@ -1596,8 +1602,8 @@ out: return err;
* modify the packet */
int
ipxrtr_route_skb
(
struct
sk_buff
*
skb
)
{
struct
ipxhdr
*
ipx
=
skb
->
nh
.
ipxh
;
ipx_route
*
r
=
ipxrtr_lookup
(
IPX_SKB_CB
(
skb
)
->
ipx_dest_net
);
struct
ipxhdr
*
ipx
=
ipx_hdr
(
skb
)
;
struct
ipx_route
*
r
=
ipxrtr_lookup
(
IPX_SKB_CB
(
skb
)
->
ipx_dest_net
);
if
(
!
r
)
{
/* no known route */
kfree_skb
(
skb
);
...
...
@@ -1666,7 +1672,7 @@ static const char *ipx_frame_name(unsigned short frame)
return
ret
;
}
static
const
char
*
ipx_device_name
(
ipx_interface
*
intrfc
)
static
const
char
*
ipx_device_name
(
struct
ipx_interface
*
intrfc
)
{
return
intrfc
->
if_internal
?
"Internal"
:
intrfc
->
if_dev
?
intrfc
->
if_dev
->
name
:
"Unknown"
;
...
...
@@ -1676,7 +1682,7 @@ static const char *ipx_device_name(ipx_interface *intrfc)
static
int
ipx_interface_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
ipx_interface
*
i
;
struct
ipx_interface
*
i
;
off_t
begin
=
0
,
pos
=
0
;
int
len
=
0
;
...
...
@@ -1728,7 +1734,7 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
static
int
ipx_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
struct
sock
*
s
;
ipx_interface
*
i
;
struct
ipx_interface
*
i
;
off_t
begin
=
0
,
pos
=
0
;
int
len
=
0
;
...
...
@@ -1808,7 +1814,7 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length)
static
int
ipx_rt_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
ipx_route
*
rt
;
struct
ipx_route
*
rt
;
off_t
begin
=
0
,
pos
=
0
;
int
len
=
0
;
...
...
@@ -1927,17 +1933,11 @@ static int ipx_create(struct socket *sock, int protocol)
case
SOCK_SEQPACKET
:
/*
* From this point on SPX sockets are handled
* by af_spx.c and the methods replaced.
* SPX support is not anymore in the kernel sources. If
* you want to ressurrect it, completing it and making
* it understand shared skbs, be fully multithreaded,
* etc, grab the sources in an early 2.5 kernel tree.
*/
down_read
(
&
spx_family_ops_lock
);
if
(
spx_family_ops
)
{
ret
=
spx_family_ops
->
create
(
sock
,
protocol
);
up_read
(
&
spx_family_ops_lock
);
goto
decmod
;
}
up_read
(
&
spx_family_ops_lock
);
/* Fall through if SPX is not loaded */
case
SOCK_STREAM
:
/* Allow higher levels to piggyback */
default:
goto
decmod
;
...
...
@@ -1978,7 +1978,7 @@ out: return 0;
/* caller must hold a reference to intrfc */
static
unsigned
short
ipx_first_free_socketnum
(
ipx_interface
*
intrfc
)
static
unsigned
short
ipx_first_free_socketnum
(
struct
ipx_interface
*
intrfc
)
{
unsigned
short
socketNum
=
intrfc
->
if_sknum
;
...
...
@@ -2003,7 +2003,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
ipx_opt
*
ipxs
=
ipx_sk
(
sk
);
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
struct
sockaddr_ipx
*
addr
=
(
struct
sockaddr_ipx
*
)
uaddr
;
int
ret
=
-
EINVAL
;
...
...
@@ -2101,7 +2101,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
struct
ipx_opt
*
ipxs
=
ipx_sk
(
sk
);
struct
sockaddr_ipx
*
addr
;
int
ret
=
-
EINVAL
;
ipx_route
*
rt
;
struct
ipx_route
*
rt
;
sk
->
state
=
TCP_CLOSE
;
sock
->
state
=
SS_UNCONNECTED
;
...
...
@@ -2158,7 +2158,7 @@ out: return ret;
static
int
ipx_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
uaddr_len
,
int
peer
)
{
ipx_address
*
addr
;
struct
ipx_address
*
addr
;
struct
sockaddr_ipx
sipx
;
struct
sock
*
sk
=
sock
->
sk
;
struct
ipx_opt
*
ipxs
=
ipx_sk
(
sk
);
...
...
@@ -2204,7 +2204,7 @@ out: return ret;
int
ipx_rcv
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
pt
)
{
/* NULL here for pt means the packet was looped back */
ipx_interface
*
intrfc
;
struct
ipx_interface
*
intrfc
;
struct
ipxhdr
*
ipx
;
u16
ipx_pktsize
;
int
ret
=
0
;
...
...
@@ -2216,7 +2216,7 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
if
((
skb
=
skb_share_check
(
skb
,
GFP_ATOMIC
))
==
NULL
)
goto
out
;
ipx
=
skb
->
nh
.
ipxh
;
ipx
=
ipx_hdr
(
skb
)
;
ipx_pktsize
=
ntohs
(
ipx
->
ipx_pktsize
);
/* Too small or invalid header? */
...
...
@@ -2352,7 +2352,7 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
if
(
!
skb
)
goto
out
;
ipx
=
skb
->
nh
.
ipxh
;
ipx
=
ipx_hdr
(
skb
)
;
copied
=
ntohs
(
ipx
->
ipx_pktsize
)
-
sizeof
(
struct
ipxhdr
);
if
(
copied
>
size
)
{
copied
=
size
;
...
...
@@ -2461,64 +2461,33 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return
0
;
}
/*
* SPX interface support
*/
int
ipx_register_spx
(
struct
proto_ops
**
p
,
struct
net_proto_family
*
spx
)
{
int
err
;
err
=
-
EBUSY
;
down_write
(
&
spx_family_ops_lock
);
if
(
!
spx_family_ops
)
{
MOD_INC_USE_COUNT
;
*
p
=
&
ipx_dgram_ops
;
spx_family_ops
=
spx
;
}
up_write
(
&
spx_family_ops_lock
);
return
0
;
}
int
ipx_unregister_spx
(
void
)
{
down_write
(
&
spx_family_ops_lock
);
if
(
spx_family_ops
)
{
spx_family_ops
=
NULL
;
MOD_DEC_USE_COUNT
;
}
up_write
(
&
spx_family_ops_lock
);
return
0
;
}
/*
* Socket family declarations
*/
static
struct
net_proto_family
ipx_family_ops
=
{
.
family
=
PF_IPX
,
.
create
=
ipx_create
,
.
family
=
PF_IPX
,
.
create
=
ipx_create
,
};
static
struct
proto_ops
SOCKOPS_WRAPPED
(
ipx_dgram_ops
)
=
{
.
family
=
PF_IPX
,
.
release
=
ipx_release
,
.
bind
=
ipx_bind
,
.
connect
=
ipx_connect
,
.
socketpair
=
sock_no_socketpair
,
.
accept
=
sock_no_accept
,
.
getname
=
ipx_getname
,
.
poll
=
datagram_poll
,
.
ioctl
=
ipx_ioctl
,
.
listen
=
sock_no_listen
,
.
shutdown
=
sock_no_shutdown
,
/* FIXME: have to support shutdown */
.
setsockopt
=
ipx_setsockopt
,
.
getsockopt
=
ipx_getsockopt
,
.
sendmsg
=
ipx_sendmsg
,
.
recvmsg
=
ipx_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
.
family
=
PF_IPX
,
.
release
=
ipx_release
,
.
bind
=
ipx_bind
,
.
connect
=
ipx_connect
,
.
socketpair
=
sock_no_socketpair
,
.
accept
=
sock_no_accept
,
.
getname
=
ipx_getname
,
.
poll
=
datagram_poll
,
.
ioctl
=
ipx_ioctl
,
.
listen
=
sock_no_listen
,
.
shutdown
=
sock_no_shutdown
,
/* FIXME: support shutdown */
.
setsockopt
=
ipx_setsockopt
,
.
getsockopt
=
ipx_getsockopt
,
.
sendmsg
=
ipx_sendmsg
,
.
recvmsg
=
ipx_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
};
#include <linux/smp_lock.h>
...
...
@@ -2540,7 +2509,6 @@ static struct notifier_block ipx_dev_notifier = {
.
notifier_call
=
ipxitf_device_event
,
};
extern
struct
datalink_proto
*
make_EII_client
(
void
);
extern
struct
datalink_proto
*
make_8023_client
(
void
);
extern
void
destroy_EII_client
(
struct
datalink_proto
*
);
...
...
@@ -2549,9 +2517,13 @@ extern void destroy_8023_client(struct datalink_proto *);
static
unsigned
char
ipx_8022_type
=
0xE0
;
static
unsigned
char
ipx_snap_id
[
5
]
=
{
0x0
,
0x0
,
0x0
,
0x81
,
0x37
};
static
char
ipx_banner
[]
__initdata
=
KERN_INFO
"NET4: Linux IPX 0.4
8
for NET4.0
\n
"
KERN_INFO
"NET4: Linux IPX 0.4
9
for NET4.0
\n
"
KERN_INFO
"IPX Portions Copyright (c) 1995 Caldera, Inc.
\n
"
\
KERN_INFO
"IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.
\n
"
;
static
char
ipx_EII_err_msg
[]
__initdata
=
KERN_CRIT
"IPX: Unable to register with Ethernet II
\n
"
;
static
char
ipx_8023_err_msg
[]
__initdata
=
KERN_CRIT
"IPX: Unable to register with 802.3
\n
"
;
static
char
ipx_llc_err_msg
[]
__initdata
=
KERN_CRIT
"IPX: Unable to register with 802.2
\n
"
;
static
char
ipx_snap_err_msg
[]
__initdata
=
...
...
@@ -2562,10 +2534,16 @@ static int __init ipx_init(void)
sock_register
(
&
ipx_family_ops
);
pEII_datalink
=
make_EII_client
();
dev_add_pack
(
&
ipx_dix_packet_type
);
if
(
pEII_datalink
)
dev_add_pack
(
&
ipx_dix_packet_type
);
else
printk
(
ipx_EII_err_msg
);
p8023_datalink
=
make_8023_client
();
dev_add_pack
(
&
ipx_8023_packet_type
);
if
(
p8023_datalink
)
dev_add_pack
(
&
ipx_8023_packet_type
);
else
printk
(
ipx_8023_err_msg
);
p8022_datalink
=
register_8022_client
(
ipx_8022_type
,
ipx_rcv
);
if
(
!
p8022_datalink
)
...
...
@@ -2588,26 +2566,6 @@ static int __init ipx_init(void)
module_init
(
ipx_init
);
/* Higher layers need this info to prep tx pkts */
int
ipx_if_offset
(
unsigned
long
ipx_net_number
)
{
ipx_route
*
rt
=
ipxrtr_lookup
(
ipx_net_number
);
int
ret
=
-
ENETUNREACH
;
if
(
!
rt
)
goto
out
;
ret
=
rt
->
ir_intrfc
->
if_ipx_offset
;
ipxrtr_put
(
rt
);
out:
return
ret
;
}
/* Export symbols for higher layers */
EXPORT_SYMBOL
(
ipxrtr_route_skb
);
EXPORT_SYMBOL
(
ipx_if_offset
);
EXPORT_SYMBOL
(
ipx_remove_socket
);
EXPORT_SYMBOL
(
ipx_register_spx
);
EXPORT_SYMBOL
(
ipx_unregister_spx
);
/* Note on MOD_{INC,DEC}_USE_COUNT:
*
* Use counts are incremented/decremented when
...
...
net/ipx/af_spx.c
deleted
100644 → 0
View file @
d52a86be
/*
* This module implements the (SPP-derived) Sequenced Packet eXchange
* (SPX) protocol for Linux 2.1.X as specified in
* NetWare SPX Services Specification, Semantics and API
* Revision: 1.00
* Revision Date: February 9, 1993
*
* 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
* that crashed it under load. Renamed and
* made static the ipx ops. Removed the hack
* ipx methods interface. Dropped AF_SPX - its
* the wrong abstraction.
* Eduardo Trapani : Added a check for the return value of
* ipx_if_offset that crashed sock_alloc_send_skb.
* Added spx_datagram_poll() so that select()
* works now on SPX sockets. Added updating
* 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
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* None of the authors or maintainers or their employers admit
* liability nor provide warranty for any of this software.
* This material is provided "as is" and at no charge.
*/
#include <linux/module.h>
#include <net/ipx.h>
#include <net/spx.h>
#include <net/tcp.h>
#include <net/sock.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <linux/uio.h>
#include <linux/unistd.h>
#include <linux/poll.h>
static
struct
proto_ops
*
ipx_ops
;
static
struct
proto_ops
spx_ops
;
static
__u16
connids
;
/* Functions needed for SPX connection start up */
static
int
spx_transmit
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
type
,
int
len
);
static
void
spx_retransmit
(
unsigned
long
data
);
static
void
spx_watchdog
(
unsigned
long
data
);
void
spx_rcv
(
struct
sock
*
sk
,
int
bytes
);
extern
void
ipx_remove_socket
(
struct
sock
*
sk
);
/* Datagram poll: the same code as datagram_poll() in net/core
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
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
unsigned
int
mask
;
poll_wait
(
file
,
sk
->
sleep
,
wait
);
mask
=
0
;
/* exceptional events? */
if
(
sk
->
err
||
!
skb_queue_empty
(
&
sk
->
error_queue
))
mask
|=
POLLERR
;
if
(
sk
->
shutdown
&
RCV_SHUTDOWN
)
mask
|=
POLLHUP
;
/* readable? */
if
(
!
skb_queue_empty
(
&
pdata
->
rcv_queue
))
mask
|=
POLLIN
|
POLLRDNORM
;
/* Need to check for termination and startup */
if
(
sk
->
state
==
TCP_CLOSE
)
mask
|=
POLLHUP
;
/* connection hasn't started yet? */
if
(
sk
->
state
==
TCP_SYN_SENT
)
goto
out
;
/* writable? */
if
(
sock_writeable
(
sk
))
mask
|=
POLLOUT
|
POLLWRNORM
|
POLLWRBAND
;
else
set_bit
(
SOCK_ASYNC_NOSPACE
,
&
sk
->
socket
->
flags
);
out:
return
mask
;
}
/* Create the SPX specific data */
static
int
spx_sock_init
(
struct
sock
*
sk
)
{
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
pdata
->
state
=
SPX_CLOSED
;
pdata
->
sequence
=
0
;
pdata
->
acknowledge
=
0
;
pdata
->
source_connid
=
htons
(
connids
);
pdata
->
rmt_seq
=
0
;
connids
++
;
pdata
->
owner
=
(
void
*
)
sk
;
pdata
->
sndbuf
=
sk
->
sndbuf
;
pdata
->
watchdog
.
function
=
spx_watchdog
;
pdata
->
watchdog
.
data
=
(
unsigned
long
)
sk
;
pdata
->
wd_interval
=
VERIFY_TIMEOUT
;
pdata
->
retransmit
.
function
=
spx_retransmit
;
pdata
->
retransmit
.
data
=
(
unsigned
long
)
sk
;
pdata
->
retransmits
=
0
;
pdata
->
retries
=
0
;
pdata
->
max_retries
=
RETRY_COUNT
;
skb_queue_head_init
(
&
pdata
->
rcv_queue
);
skb_queue_head_init
(
&
pdata
->
transmit_queue
);
skb_queue_head_init
(
&
pdata
->
retransmit_queue
);
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 */
sk
=
sk_alloc
(
PF_IPX
,
GFP_ATOMIC
,
1
);
if
(
!
sk
)
goto
decmod
;
rc
=
-
ESOCKTNOSUPPORT
;
switch
(
sock
->
type
)
{
case
SOCK_SEQPACKET
:
sock
->
ops
=
&
spx_ops
;
break
;
default:
sk_free
(
sk
);
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
;
out:
return
rc
;
decmod:
MOD_DEC_USE_COUNT
;
goto
out
;
}
void
spx_close_socket
(
struct
sock
*
sk
)
{
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
pdata
->
state
=
SPX_CLOSED
;
sk
->
state
=
TCP_CLOSE
;
del_timer
(
&
pdata
->
retransmit
);
del_timer
(
&
pdata
->
watchdog
);
}
void
spx_destroy_socket
(
struct
sock
*
sk
)
{
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
ipx_remove_socket
(
sk
);
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
;
}
/* Release an SPX socket */
static
int
spx_release
(
struct
socket
*
sock
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
if
(
!
sk
)
goto
out
;
if
(
!
sk
->
dead
)
sk
->
state_change
(
sk
);
sk
->
dead
=
1
;
if
(
pdata
->
state
!=
SPX_CLOSED
)
{
spx_transmit
(
sk
,
NULL
,
DISCON
,
0
);
spx_close_socket
(
sk
);
}
sock
->
sk
=
NULL
;
sk
->
socket
=
NULL
;
spx_destroy_socket
(
sk
);
out:
return
0
;
}
/* Move a socket into listening state. */
static
int
spx_listen
(
struct
socket
*
sock
,
int
backlog
)
{
struct
sock
*
sk
=
sock
->
sk
;
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
)
{
sk
->
ack_backlog
=
0
;
sk
->
state
=
TCP_LISTEN
;
}
sk
->
socket
->
flags
|=
__SO_ACCEPTCON
;
out:
return
rc
;
}
/* Accept a pending SPX connection */
static
int
spx_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
newsk
;
struct
sk_buff
*
skb
;
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
)
{
rc
=
-
EWOULDBLOCK
;
if
(
flags
&
O_NONBLOCK
)
goto
out_unlock
;
interruptible_sleep_on
(
sk
->
sleep
);
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
out_unlock
;
}
}
while
(
!
skb
);
newsk
=
skb
->
sk
;
newsk
->
pair
=
NULL
;
sti
();
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
;
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
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sockaddr_ipx
src
;
struct
sk_buff
*
skb
;
int
size
=
sizeof
(
src
);
int
rc
=
ipx_ops
->
getname
(
sock
,
(
struct
sockaddr
*
)
&
src
,
&
size
,
0
);
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
;
rc
=
ipx_ops
->
connect
(
sock
,
uaddr
,
addr_len
,
flags
);
if
(
rc
)
goto
out
;
pdata
->
dest_addr
=
ipx_sk
(
sk
)
->
dest_addr
;
pdata
->
state
=
SPX_CONNECTING
;
sock
->
state
=
SS_CONNECTING
;
sk
->
state
=
TCP_SYN_SENT
;
/* Send Connection request */
rc
=
spx_transmit
(
sk
,
NULL
,
CONREQ
,
0
);
if
(
rc
)
goto
out
;
cli
();
do
{
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
!
skb
)
{
rc
=
-
EWOULDBLOCK
;
if
(
flags
&
O_NONBLOCK
)
goto
unlock
;
interruptible_sleep_on
(
sk
->
sleep
);
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
unlock
;
}
}
while
(
!
skb
);
rc
=
-
ETIMEDOUT
;
if
(
pdata
->
state
==
SPX_CLOSED
)
{
del_timer
(
&
pdata
->
watchdog
);
goto
unlock
;
}
rc
=
0
;
sock
->
state
=
SS_CONNECTED
;
sk
->
state
=
TCP_ESTABLISHED
;
kfree_skb
(
skb
);
unlock:
sti
();
out:
return
rc
;
}
/*
* Calculate the timeout for a packet. Thankfully SPX has a large
* fudge factor (3/4 secs) and does not pay much attention to RTT.
* As we simply have a default retry time of 1*HZ and a max retry
* time of 5*HZ. Between those values we increase the timeout based
* on the number of retransmit tries.
*
* FixMe: This is quite fake, but will work for now. (JS)
*/
static
inline
unsigned
long
spx_calc_rtt
(
int
tries
)
{
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
)
{
int
rc
=
-
ENOBUFS
;
skb
=
skb_unshare
(
skb
,
GFP_ATOMIC
);
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
);
goto
out
;
}
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
)
{
rc
=
-
ENOBUFS
;
goto
out
;
}
skb_queue_tail
(
&
pdata
->
retransmit_queue
,
skb2
);
/* 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
);
}
out:
return
rc
;
}
/* SPX packet transmit engine */
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
rc
;
if
(
!
skb
)
{
int
offset
=
ipx_if_offset
(
pdata
->
dest_addr
.
net
);
int
size
=
offset
+
sizeof
(
struct
ipxspxhdr
);
rc
=
-
ENETUNREACH
;
if
(
offset
<
0
)
goto
out
;
save_flags
(
flags
);
cli
();
skb
=
sock_alloc_send_skb
(
sk
,
size
,
0
,
&
err
);
rc
=
-
ENOMEM
;
if
(
!
skb
)
{
restore_flags
(
flags
);
goto
out
;
}
skb_reserve
(
skb
,
offset
);
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxspxhdr
));
restore_flags
(
flags
);
}
/* IPX header */
ipxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
ipxh
->
ipx
.
ipx_checksum
=
0xFFFF
;
ipxh
->
ipx
.
ipx_pktsize
=
htons
(
SPX_SYS_PKT_LEN
);
ipxh
->
ipx
.
ipx_tctrl
=
0
;
ipxh
->
ipx
.
ipx_type
=
IPX_TYPE_SPX
;
ipxh
->
ipx
.
ipx_dest
=
pdata
->
dest_addr
;
ipxh
->
ipx
.
ipx_source
=
pdata
->
source_addr
;
/* SPX header */
ipxh
->
spx
.
dtype
=
0
;
ipxh
->
spx
.
sequence
=
htons
(
pdata
->
sequence
);
ipxh
->
spx
.
ackseq
=
htons
(
pdata
->
rmt_seq
);
ipxh
->
spx
.
sconn
=
pdata
->
source_connid
;
ipxh
->
spx
.
dconn
=
pdata
->
dest_connid
;
ipxh
->
spx
.
allocseq
=
htons
(
pdata
->
alloc
);
/* Reset/Set WD timer */
mod_timer
(
&
pdata
->
watchdog
,
jiffies
+
VERIFY_TIMEOUT
);
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 */
pdata
->
rmt_seq
++
;
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 */
del_timer
(
&
pdata
->
watchdog
);
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
.
sconn
=
pdata
->
source_connid
;
ipxh
->
spx
.
dconn
=
pdata
->
dest_connid
;
ipxh
->
spx
.
allocseq
=
htons
(
pdata
->
alloc
);
break
;
case
DISCON
:
/* Informed Disconnect */
ipxh
->
spx
.
cctl
=
CCTL_ACK
;
ipxh
->
spx
.
dtype
=
SPX_DTYPE_ECONN
;
break
;
case
DISACK
:
/* Informed Disconnect ACK */
ipxh
->
spx
.
cctl
=
0
;
ipxh
->
spx
.
dtype
=
SPX_DTYPE_ECACK
;
ipxh
->
spx
.
sequence
=
0
;
ipxh
->
spx
.
ackseq
=
htons
(
pdata
->
rmt_seq
++
);
break
;
default:
rc
=
-
EOPNOTSUPP
;
goto
out
;
}
/* Send data */
rc
=
spx_route_skb
(
pdata
,
skb
,
type
);
out:
return
rc
;
}
/* Check the state of the connection and send a WD request if needed. */
static
void
spx_watchdog
(
unsigned
long
data
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
data
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
del_timer
(
&
pdata
->
watchdog
);
if
(
pdata
->
state
==
SPX_CLOSED
)
goto
out
;
if
(
pdata
->
retries
>
pdata
->
max_retries
)
{
spx_close_socket
(
sk
);
/* Unilateral Abort */
goto
out
;
}
/* Send WD request */
spx_transmit
(
sk
,
NULL
,
WDREQ
,
0
);
pdata
->
retries
++
;
out:
;
}
static
void
spx_retransmit
(
unsigned
long
data
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
data
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sk_buff
*
skb
;
unsigned
long
flags
;
del_timer
(
&
pdata
->
retransmit
);
if
(
pdata
->
state
==
SPX_CLOSED
)
goto
out
;
if
(
pdata
->
retransmits
>
RETRY_COUNT
)
{
spx_close_socket
(
sk
);
/* Unilateral Abort */
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
))
skb
=
skb_copy
(
skb
,
GFP_ATOMIC
);
else
skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
restore_flags
(
flags
);
pdata
->
retransmit
.
expires
=
jiffies
+
spx_calc_rtt
(
pdata
->
retransmits
);
add_timer
(
&
pdata
->
retransmit
);
spx_route_skb
(
pdata
,
skb
,
RETRAN
);
pdata
->
retransmits
++
;
out:
;
}
/* Check packet for retransmission, ConReqAck aware */
static
int
spx_retransmit_chk
(
struct
spx_opt
*
pdata
,
int
ackseq
,
int
type
)
{
struct
ipxspxhdr
*
ipxh
;
int
rc
=
-
ENOENT
;
struct
sk_buff
*
skb
=
skb_dequeue
(
&
pdata
->
retransmit_queue
);
if
(
!
skb
)
goto
out
;
rc
=
0
;
/* Check Data/ACK seq */
switch
(
type
)
{
case
ACK
:
/* Check Sequence, Should == 1 */
ipxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
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
))
{
skb
=
skb_dequeue
(
&
pdata
->
transmit_queue
);
if
(
skb
)
spx_route_skb
(
pdata
,
skb
,
TQUEUE
);
}
goto
out
;
}
skb_queue_head
(
&
pdata
->
retransmit_queue
,
skb
);
rc
=
-
1
;
out:
return
rc
;
}
/* SPX packet receive engine */
void
spx_rcv
(
struct
sock
*
sk
,
int
bytes
)
{
struct
ipxspxhdr
*
ipxh
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sk_buff
*
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
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
)
||
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 */
del_timer
(
&
pdata
->
watchdog
);
pdata
->
retries
=
0
;
pdata
->
watchdog
.
expires
=
jiffies
+
ABORT_TIMEOUT
;
add_timer
(
&
pdata
->
watchdog
);
switch
(
ipxh
->
spx
.
cctl
)
{
case
(
CCTL_SYS
|
CCTL_ACK
):
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
;
pdata
->
dest_connid
=
ipxh
->
spx
.
sconn
;
pdata
->
alloc
=
3
+
ntohs
(
ipxh
->
spx
.
sequence
);
skb_queue_tail
(
&
sk
->
receive_queue
,
skb
);
wake_up_interruptible
(
sk
->
sleep
);
}
else
/* WD Request */
spx_transmit
(
sk
,
skb
,
WDACK
,
0
);
goto
out
;
case
CCTL_SYS
:
/* ACK */
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
)
goto
toss_skb
;
skb_queue_tail
(
&
sk
->
receive_queue
,
skb
);
wake_up_interruptible
(
sk
->
sleep
);
goto
out
;
}
spx_retransmit_chk
(
pdata
,
ipxh
->
spx
.
ackseq
,
ACK
);
goto
toss_skb
;
case
CCTL_ACK
:
/* Informed Disconnect */
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECONN
)
{
spx_transmit
(
sk
,
skb
,
DISACK
,
0
);
spx_close_socket
(
sk
);
goto
out
;
}
/* Fall through */
default:
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
)
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
)
spx_transmit
(
sk
,
NULL
,
ACK
,
0
);
goto
out
;
}
if
(
ipxh
->
spx
.
dtype
==
SPX_DTYPE_ECACK
)
{
if
(
pdata
->
state
!=
SPX_CLOSED
)
spx_close_socket
(
sk
);
goto
toss_skb
;
}
}
toss_skb:
/* Catch All */
kfree_skb
(
skb
);
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
sock
*
sk
=
sock
->
sk
;
int
flags
=
msg
->
msg_flags
;
struct
sk_buff
*
skb
;
int
offset
,
size
,
rc
=
-
EMSGSIZE
;
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
,
&
rc
);
sti
();
if
(
!
skb
)
goto
out
;
skb
->
sk
=
sk
;
skb_reserve
(
skb
,
offset
);
skb
->
h
.
raw
=
skb
->
nh
.
raw
=
skb_put
(
skb
,
sizeof
(
struct
ipxspxhdr
));
rc
=
-
EFAULT
;
if
(
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
))
{
kfree_skb
(
skb
);
goto
out
;
}
rc
=
len
;
if
(
!
spx_transmit
(
sk
,
skb
,
DATA
,
len
))
rc
=
-
EAGAIN
;
out:
return
rc
;
}
/* Send message/packet data to user-land */
static
int
spx_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
,
struct
scm_cookie
*
scm
)
{
struct
sk_buff
*
skb
;
struct
ipxspxhdr
*
ispxh
;
struct
sock
*
sk
=
sock
->
sk
;
struct
spx_opt
*
pdata
=
spx_sk
(
sk
);
struct
sockaddr_ipx
*
sipx
=
(
struct
sockaddr_ipx
*
)
msg
->
msg_name
;
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 */
/* Socket errors? */
rc
=
sock_error
(
sk
);
if
(
rc
)
goto
out_release_sock
;
/* Socket shut down? */
rc
=
-
ESHUTDOWN
;
if
(
sk
->
shutdown
&
RCV_SHUTDOWN
)
goto
out_release_sock
;
/* handle signals */
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
goto
out_release_sock
;
/* User doesn't want to wait */
rc
=
-
EAGAIN
;
if
(
flags
&
MSG_DONTWAIT
)
goto
out_release_sock
;
release_sock
(
sk
);
save_flags
(
flags
);
cli
();
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
)
goto
restart
;
ispxh
=
(
struct
ipxspxhdr
*
)
skb
->
nh
.
raw
;
copied
=
ntohs
(
ispxh
->
ipx
.
ipx_pktsize
)
-
SPX_SYS_PKT_LEN
;
if
(
copied
>
size
)
{
copied
=
size
;
msg
->
msg_flags
|=
MSG_TRUNC
;
}
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
)
{
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
);
out_release_sock:
release_sock
(
sk
);
out:
return
rc
;
}
/*
* Functions which just wrap their IPX cousins
*/
static
int
spx_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
return
ipx_ops
->
bind
(
sock
,
uaddr
,
addr_len
);
}
static
int
spx_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
usockaddr_len
,
int
peer
)
{
return
ipx_ops
->
getname
(
sock
,
uaddr
,
usockaddr_len
,
peer
);
}
static
int
spx_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
ipx_ops
->
ioctl
(
sock
,
cmd
,
arg
);
}
static
int
spx_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
return
ipx_ops
->
setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
static
int
spx_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
return
ipx_ops
->
getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
spx_ops
)
=
{
.
family
=
PF_IPX
,
.
release
=
spx_release
,
.
bind
=
spx_bind
,
.
connect
=
spx_connect
,
.
socketpair
=
sock_no_socketpair
,
.
accept
=
spx_accept
,
.
getname
=
spx_getname
,
.
poll
=
spx_datagram_poll
,
.
ioctl
=
spx_ioctl
,
.
listen
=
spx_listen
,
.
shutdown
=
sock_no_shutdown
,
.
setsockopt
=
spx_setsockopt
,
.
getsockopt
=
spx_getsockopt
,
.
sendmsg
=
spx_sendmsg
,
.
recvmsg
=
spx_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
};
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
spx
,
PF_IPX
);
static
struct
net_proto_family
spx_family_ops
=
{
.
family
=
PF_IPX
,
.
create
=
spx_create
,
};
static
char
banner
[]
__initdata
=
KERN_INFO
"NET4: Sequenced Packet eXchange (SPX) 0.03
\n
"
;
static
int
__init
spx_proto_init
(
void
)
{
connids
=
(
__u16
)
jiffies
;
/* initalize random */
/* allocate our sock slab cache */
spx_family_ops
.
sk_cachep
=
kmem_cache_create
(
"spx_sock"
,
spx_family_ops
.
sk_size
,
0
,
SLAB_HWCACHE_ALIGN
,
0
,
0
);
if
(
!
spx_family_ops
.
sk_cachep
)
printk
(
KERN_CRIT
__FUNCTION__
": Cannot create spx_sock SLAB cache!
\n
"
);
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() */
printk
(
banner
);
return
0
;
}
static
void
__exit
spx_proto_finito
(
void
)
{
ipx_unregister_spx
();
}
module_init
(
spx_proto_init
);
module_exit
(
spx_proto_finito
);
MODULE_LICENSE
(
"GPL"
);
net/ipx/sysctl_net_ipx.c
View file @
a914f3da
...
...
@@ -17,21 +17,36 @@
/* From af_ipx.c */
extern
int
sysctl_ipx_pprop_broadcasting
;
ctl_table
ipx_table
[]
=
{
{
NET_IPX_PPROP_BROADCASTING
,
"ipx_pprop_broadcasting"
,
&
sysctl_ipx_pprop_broadcasting
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec
},
{
0
}
static
struct
ctl_table
ipx_table
[]
=
{
{
.
ctl_name
=
NET_IPX_PPROP_BROADCASTING
,
.
procname
=
"ipx_pprop_broadcasting"
,
.
data
=
&
sysctl_ipx_pprop_broadcasting
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
,
},
{
0
},
};
static
ctl_table
ipx_dir_table
[]
=
{
{
NET_IPX
,
"ipx"
,
NULL
,
0
,
0555
,
ipx_table
},
{
0
}
static
struct
ctl_table
ipx_dir_table
[]
=
{
{
.
ctl_name
=
NET_IPX
,
.
procname
=
"ipx"
,
.
mode
=
0555
,
.
child
=
ipx_table
,
},
{
0
},
};
static
ctl_table
ipx_root_table
[]
=
{
{
CTL_NET
,
"net"
,
NULL
,
0
,
0555
,
ipx_dir_table
},
{
0
}
static
struct
ctl_table
ipx_root_table
[]
=
{
{
.
ctl_name
=
CTL_NET
,
.
procname
=
"net"
,
.
mode
=
0555
,
.
child
=
ipx_dir_table
,
},
{
0
},
};
static
struct
ctl_table_header
*
ipx_table_header
;
...
...
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