Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds 2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

101
net/ipx/ChangeLog Normal file
View file

@ -0,0 +1,101 @@
Revision 0.21: Uses the new generic socket option code.
Revision 0.22: Gcc clean ups and drop out device registration. Use the
new multi-protocol edition of hard_header
Revision 0.23: IPX /proc by Mark Evans. Adding a route will
will overwrite any existing route to the same network.
Revision 0.24: Supports new /proc with no 4K limit
Revision 0.25: Add ephemeral sockets, passive local network
identification, support for local net 0 and
multiple datalinks <Greg Page>
Revision 0.26: Device drop kills IPX routes via it. (needed for module)
Revision 0.27: Autobind <Mark Evans>
Revision 0.28: Small fix for multiple local networks <Thomas Winder>
Revision 0.29: Assorted major errors removed <Mark Evans>
Small correction to promisc mode error fix <Alan Cox>
Asynchronous I/O support. Changed to use notifiers
and the newer packet_type stuff. Assorted major
fixes <Alejandro Liu>
Revision 0.30: Moved to net/ipx/... <Alan Cox>
Don't set address length on recvfrom that errors.
Incorrect verify_area.
Revision 0.31: New sk_buffs. This still needs a lot of
testing. <Alan Cox>
Revision 0.32: Using sock_alloc_send_skb, firewall hooks. <Alan Cox>
Supports sendmsg/recvmsg
Revision 0.33: Internal network support, routing changes, uses a
protocol private area for ipx data.
Revision 0.34: Module support. <Jim Freeman>
Revision 0.35: Checksum support. <Neil Turton>, hooked in by <Alan Cox>
Handles WIN95 discovery packets <Volker Lendecke>
Revision 0.36: Internal bump up for 2.1
Revision 0.37: Began adding POSIXisms.
Revision 0.38: Asynchronous socket stuff made current.
Revision 0.39: SPX interfaces
Revision 0.40: Tiny SIOCGSTAMP fix ([email protected])
Revision 0.41: 802.2TR removed ([email protected])
Fixed connecting to primary net,
Automatic binding on send & receive,
Martijn van Oosterhout <[email protected]>
Revision 042: Multithreading - use spinlocks and refcounting to
protect some structures: ipx_interface sock list, list
of ipx interfaces, etc.
Bugfixes - do refcounting on net_devices, check function
results, etc. Thanks to davem and freitag for
suggestions and guidance.
Arnaldo Carvalho de Melo <[email protected]>,
November, 2000
Revision 043: Shared SKBs, don't mangle packets, some cleanups
Arnaldo Carvalho de Melo <[email protected]>,
December, 2000
Revision 044: Call ipxitf_hold on NETDEV_UP - acme
Revision 045: fix PPROP routing bug - acme
Revision 046: Further fixes to PPROP, ipxitf_create_internal was
doing an unneeded MOD_INC_USE_COUNT, implement
sysctl for ipx_pprop_broacasting, fix the ipx sysctl
handling, making it dynamic, some cleanups, thanks to
Petr Vandrovec for review and good suggestions. (acme)
Revision 047: Cleanups, CodingStyle changes, move the ncp connection
hack out of line - acme
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 - acme
Revision 049: SPX support dropped, see comment in ipx_create - acme
Revision 050: Use seq_file for proc stuff, moving it to ipx_proc.c - acme
Other fixes:
Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pair. Also, now
usage count is managed this way:
-Count one if the auto_interface mode is on
-Count one per configured interface
Jacques Gelinas ([email protected])

31
net/ipx/Kconfig Normal file
View file

@ -0,0 +1,31 @@
#
# IPX configuration
#
config IPX_INTERN
bool "IPX: Full internal IPX network"
depends on IPX
---help---
Every IPX network has an address that identifies it. Sometimes it is
useful to give an IPX "network" address to your Linux box as well
(for example if your box is acting as a file server for different
IPX networks: it will then be accessible from everywhere using the
same address). The way this is done is to create a virtual internal
"network" inside your box and to assign an IPX address to this
network. Say Y here if you want to do this; read the IPX-HOWTO at
<http://www.tldp.org/docs.html#howto> for details.
The full internal IPX network enables you to allocate sockets on
different virtual nodes of the internal network. This is done by
evaluating the field sipx_node of the socket address given to the
bind call. So applications should always initialize the node field
to 0 when binding a socket on the primary network. In this case the
socket is assigned the default node that has been given to the
kernel when the internal network was created. By enabling the full
internal IPX network the cross-forwarding of packets targeted at
'special' sockets to sockets listening on the primary network is
disabled. This might break existing applications, especially RIP/SAP
daemons. A RIP/SAP daemon that works well with the full internal net
can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
If you don't know what you are doing, say N.

8
net/ipx/Makefile Normal file
View file

@ -0,0 +1,8 @@
#
# Makefile for the Linux IPX layer.
#
obj-$(CONFIG_IPX) += ipx.o
ipx-y := af_ipx.o ipx_route.o ipx_proc.o
ipx-$(CONFIG_SYSCTL) += sysctl_net_ipx.o

2024
net/ipx/af_ipx.c Normal file

File diff suppressed because it is too large Load diff

408
net/ipx/ipx_proc.c Normal file
View file

@ -0,0 +1,408 @@
/*
* IPX proc routines
*
* Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002
*/
#include <linux/config.h>
#include <linux/init.h>
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>
#include <linux/tcp.h>
#include <net/ipx.h>
static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
{
struct ipx_interface *i;
list_for_each_entry(i, &ipx_interfaces, node)
if (!pos--)
goto out;
i = NULL;
out:
return i;
}
static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i)
{
struct ipx_interface *rc = NULL;
if (i->node.next != &ipx_interfaces)
rc = list_entry(i->node.next, struct ipx_interface, node);
return rc;
}
static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
{
loff_t l = *pos;
spin_lock_bh(&ipx_interfaces_lock);
return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN;
}
static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ipx_interface *i;
++*pos;
if (v == SEQ_START_TOKEN)
i = ipx_interfaces_head();
else
i = ipx_interfaces_next(v);
return i;
}
static void ipx_seq_interface_stop(struct seq_file *seq, void *v)
{
spin_unlock_bh(&ipx_interfaces_lock);
}
static int ipx_seq_interface_show(struct seq_file *seq, void *v)
{
struct ipx_interface *i;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Network Node_Address Primary Device "
"Frame_Type");
#ifdef IPX_REFCNT_DEBUG
seq_puts(seq, " refcnt");
#endif
seq_puts(seq, "\n");
goto out;
}
i = v;
seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum));
seq_printf(seq, "%02X%02X%02X%02X%02X%02X ",
i->if_node[0], i->if_node[1], i->if_node[2],
i->if_node[3], i->if_node[4], i->if_node[5]);
seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No");
seq_printf(seq, "%-11s", ipx_device_name(i));
seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
#ifdef IPX_REFCNT_DEBUG
seq_printf(seq, "%6d", atomic_read(&i->refcnt));
#endif
seq_puts(seq, "\n");
out:
return 0;
}
static struct ipx_route *ipx_routes_head(void)
{
struct ipx_route *rc = NULL;
if (!list_empty(&ipx_routes))
rc = list_entry(ipx_routes.next, struct ipx_route, node);
return rc;
}
static struct ipx_route *ipx_routes_next(struct ipx_route *r)
{
struct ipx_route *rc = NULL;
if (r->node.next != &ipx_routes)
rc = list_entry(r->node.next, struct ipx_route, node);
return rc;
}
static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos)
{
struct ipx_route *r;
list_for_each_entry(r, &ipx_routes, node)
if (!pos--)
goto out;
r = NULL;
out:
return r;
}
static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos)
{
loff_t l = *pos;
read_lock_bh(&ipx_routes_lock);
return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN;
}
static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ipx_route *r;
++*pos;
if (v == SEQ_START_TOKEN)
r = ipx_routes_head();
else
r = ipx_routes_next(v);
return r;
}
static void ipx_seq_route_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&ipx_routes_lock);
}
static int ipx_seq_route_show(struct seq_file *seq, void *v)
{
struct ipx_route *rt;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Network Router_Net Router_Node\n");
goto out;
}
rt = v;
seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net));
if (rt->ir_routed)
seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n",
(long unsigned int)ntohl(rt->ir_intrfc->if_netnum),
rt->ir_router_node[0], rt->ir_router_node[1],
rt->ir_router_node[2], rt->ir_router_node[3],
rt->ir_router_node[4], rt->ir_router_node[5]);
else
seq_puts(seq, "Directly Connected\n");
out:
return 0;
}
static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
{
struct sock *s = NULL;
struct hlist_node *node;
struct ipx_interface *i;
list_for_each_entry(i, &ipx_interfaces, node) {
spin_lock_bh(&i->if_sklist_lock);
sk_for_each(s, node, &i->if_sklist) {
if (!pos)
break;
--pos;
}
spin_unlock_bh(&i->if_sklist_lock);
if (!pos) {
if (node)
goto found;
break;
}
}
s = NULL;
found:
return s;
}
static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
{
loff_t l = *pos;
spin_lock_bh(&ipx_interfaces_lock);
return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
}
static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct sock* sk, *next;
struct ipx_interface *i;
struct ipx_sock *ipxs;
++*pos;
if (v == SEQ_START_TOKEN) {
sk = NULL;
i = ipx_interfaces_head();
if (!i)
goto out;
sk = sk_head(&i->if_sklist);
if (sk)
spin_lock_bh(&i->if_sklist_lock);
goto out;
}
sk = v;
next = sk_next(sk);
if (next) {
sk = next;
goto out;
}
ipxs = ipx_sk(sk);
i = ipxs->intrfc;
spin_unlock_bh(&i->if_sklist_lock);
sk = NULL;
for (;;) {
i = ipx_interfaces_next(i);
if (!i)
break;
spin_lock_bh(&i->if_sklist_lock);
if (!hlist_empty(&i->if_sklist)) {
sk = sk_head(&i->if_sklist);
break;
}
spin_unlock_bh(&i->if_sklist_lock);
}
out:
return sk;
}
static int ipx_seq_socket_show(struct seq_file *seq, void *v)
{
struct sock *s;
struct ipx_sock *ipxs;
if (v == SEQ_START_TOKEN) {
#ifdef CONFIG_IPX_INTERN
seq_puts(seq, "Local_Address "
"Remote_Address Tx_Queue "
"Rx_Queue State Uid\n");
#else
seq_puts(seq, "Local_Address Remote_Address "
"Tx_Queue Rx_Queue State Uid\n");
#endif
goto out;
}
s = v;
ipxs = ipx_sk(s);
#ifdef CONFIG_IPX_INTERN
seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
(unsigned long)htonl(ipxs->intrfc->if_netnum),
ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
ipxs->node[4], ipxs->node[5], htons(ipxs->port));
#else
seq_printf(seq, "%08lX:%04X ", (unsigned long) htonl(ipxs->intrfc->if_netnum),
htons(ipxs->port));
#endif /* CONFIG_IPX_INTERN */
if (s->sk_state != TCP_ESTABLISHED)
seq_printf(seq, "%-28s", "Not_Connected");
else {
seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
(unsigned long)htonl(ipxs->dest_addr.net),
ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
htons(ipxs->dest_addr.sock));
}
seq_printf(seq, "%08X %08X %02X %03d\n",
atomic_read(&s->sk_wmem_alloc),
atomic_read(&s->sk_rmem_alloc),
s->sk_state, SOCK_INODE(s->sk_socket)->i_uid);
out:
return 0;
}
static struct seq_operations ipx_seq_interface_ops = {
.start = ipx_seq_interface_start,
.next = ipx_seq_interface_next,
.stop = ipx_seq_interface_stop,
.show = ipx_seq_interface_show,
};
static struct seq_operations ipx_seq_route_ops = {
.start = ipx_seq_route_start,
.next = ipx_seq_route_next,
.stop = ipx_seq_route_stop,
.show = ipx_seq_route_show,
};
static struct seq_operations ipx_seq_socket_ops = {
.start = ipx_seq_socket_start,
.next = ipx_seq_socket_next,
.stop = ipx_seq_interface_stop,
.show = ipx_seq_socket_show,
};
static int ipx_seq_route_open(struct inode *inode, struct file *file)
{
return seq_open(file, &ipx_seq_route_ops);
}
static int ipx_seq_interface_open(struct inode *inode, struct file *file)
{
return seq_open(file, &ipx_seq_interface_ops);
}
static int ipx_seq_socket_open(struct inode *inode, struct file *file)
{
return seq_open(file, &ipx_seq_socket_ops);
}
static struct file_operations ipx_seq_interface_fops = {
.owner = THIS_MODULE,
.open = ipx_seq_interface_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static struct file_operations ipx_seq_route_fops = {
.owner = THIS_MODULE,
.open = ipx_seq_route_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static struct file_operations ipx_seq_socket_fops = {
.owner = THIS_MODULE,
.open = ipx_seq_socket_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static struct proc_dir_entry *ipx_proc_dir;
int __init ipx_proc_init(void)
{
struct proc_dir_entry *p;
int rc = -ENOMEM;
ipx_proc_dir = proc_mkdir("ipx", proc_net);
if (!ipx_proc_dir)
goto out;
p = create_proc_entry("interface", S_IRUGO, ipx_proc_dir);
if (!p)
goto out_interface;
p->proc_fops = &ipx_seq_interface_fops;
p = create_proc_entry("route", S_IRUGO, ipx_proc_dir);
if (!p)
goto out_route;
p->proc_fops = &ipx_seq_route_fops;
p = create_proc_entry("socket", S_IRUGO, ipx_proc_dir);
if (!p)
goto out_socket;
p->proc_fops = &ipx_seq_socket_fops;
rc = 0;
out:
return rc;
out_socket:
remove_proc_entry("route", ipx_proc_dir);
out_route:
remove_proc_entry("interface", ipx_proc_dir);
out_interface:
remove_proc_entry("ipx", proc_net);
goto out;
}
void __exit ipx_proc_exit(void)
{
remove_proc_entry("interface", ipx_proc_dir);
remove_proc_entry("route", ipx_proc_dir);
remove_proc_entry("socket", ipx_proc_dir);
remove_proc_entry("ipx", proc_net);
}
#else /* CONFIG_PROC_FS */
int __init ipx_proc_init(void)
{
return 0;
}
void __exit ipx_proc_exit(void)
{
}
#endif /* CONFIG_PROC_FS */

293
net/ipx/ipx_route.c Normal file
View file

@ -0,0 +1,293 @@
/*
* Implements the IPX routing routines.
* Code moved from af_ipx.c.
*
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2003
*
* See net/ipx/ChangeLog.
*/
#include <linux/config.h>
#include <linux/list.h>
#include <linux/route.h>
#include <linux/spinlock.h>
#include <net/ipx.h>
#include <net/sock.h>
LIST_HEAD(ipx_routes);
DEFINE_RWLOCK(ipx_routes_lock);
extern struct ipx_interface *ipx_internal_net;
extern __u16 ipx_cksum(struct ipxhdr *packet, int length);
extern struct ipx_interface *ipxitf_find_using_net(__u32 net);
extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
struct sk_buff *skb, int copy);
extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
struct sk_buff *skb, int copy);
extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb,
char *node);
extern struct ipx_interface *ipxitf_find_using_net(__u32 net);
struct ipx_route *ipxrtr_lookup(__u32 net)
{
struct ipx_route *r;
read_lock_bh(&ipx_routes_lock);
list_for_each_entry(r, &ipx_routes, node)
if (r->ir_net == net) {
ipxrtr_hold(r);
goto unlock;
}
r = NULL;
unlock:
read_unlock_bh(&ipx_routes_lock);
return r;
}
/*
* Caller must hold a reference to intrfc
*/
int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
unsigned char *node)
{
struct ipx_route *rt;
int rc;
/* Get a route structure; either existing or create */
rt = ipxrtr_lookup(network);
if (!rt) {
rt = kmalloc(sizeof(*rt), GFP_ATOMIC);
rc = -EAGAIN;
if (!rt)
goto out;
atomic_set(&rt->refcnt, 1);
ipxrtr_hold(rt);
write_lock_bh(&ipx_routes_lock);
list_add(&rt->node, &ipx_routes);
write_unlock_bh(&ipx_routes_lock);
} else {
rc = -EEXIST;
if (intrfc == ipx_internal_net)
goto out_put;
}
rt->ir_net = network;
rt->ir_intrfc = intrfc;
if (!node) {
memset(rt->ir_router_node, '\0', IPX_NODE_LEN);
rt->ir_routed = 0;
} else {
memcpy(rt->ir_router_node, node, IPX_NODE_LEN);
rt->ir_routed = 1;
}
rc = 0;
out_put:
ipxrtr_put(rt);
out:
return rc;
}
void ipxrtr_del_routes(struct ipx_interface *intrfc)
{
struct ipx_route *r, *tmp;
write_lock_bh(&ipx_routes_lock);
list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (r->ir_intrfc == intrfc) {
list_del(&r->node);
ipxrtr_put(r);
}
write_unlock_bh(&ipx_routes_lock);
}
static int ipxrtr_create(struct ipx_route_definition *rd)
{
struct ipx_interface *intrfc;
int rc = -ENETUNREACH;
/* Find the appropriate interface */
intrfc = ipxitf_find_using_net(rd->ipx_router_network);
if (!intrfc)
goto out;
rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
ipxitf_put(intrfc);
out:
return rc;
}
static int ipxrtr_delete(long net)
{
struct ipx_route *r, *tmp;
int rc;
write_lock_bh(&ipx_routes_lock);
list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (r->ir_net == net) {
/* Directly connected; can't lose route */
rc = -EPERM;
if (!r->ir_routed)
goto out;
list_del(&r->node);
ipxrtr_put(r);
rc = 0;
goto out;
}
rc = -ENOENT;
out:
write_unlock_bh(&ipx_routes_lock);
return rc;
}
/*
* The skb has to be unshared, we'll end up calling ipxitf_send, that'll
* modify the packet
*/
int ipxrtr_route_skb(struct sk_buff *skb)
{
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);
return 0;
}
ipxitf_hold(r->ir_intrfc);
ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?
r->ir_router_node : ipx->ipx_dest.node);
ipxitf_put(r->ir_intrfc);
ipxrtr_put(r);
return 0;
}
/*
* Route an outgoing frame from a socket.
*/
int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
struct iovec *iov, size_t len, int noblock)
{
struct sk_buff *skb;
struct ipx_sock *ipxs = ipx_sk(sk);
struct ipx_interface *intrfc;
struct ipxhdr *ipx;
size_t size;
int ipx_offset;
struct ipx_route *rt = NULL;
int rc;
/* Find the appropriate interface on which to send packet */
if (!usipx->sipx_network && ipx_primary_net) {
usipx->sipx_network = ipx_primary_net->if_netnum;
intrfc = ipx_primary_net;
} else {
rt = ipxrtr_lookup(usipx->sipx_network);
rc = -ENETUNREACH;
if (!rt)
goto out;
intrfc = rt->ir_intrfc;
}
ipxitf_hold(intrfc);
ipx_offset = intrfc->if_ipx_offset;
size = sizeof(struct ipxhdr) + len + ipx_offset;
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
if (!skb)
goto out_put;
skb_reserve(skb, ipx_offset);
skb->sk = sk;
/* Fill in IPX header */
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;
IPX_SKB_CB(skb)->last_hop.index = -1;
#ifdef CONFIG_IPX_INTERN
IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN);
#else
rc = ntohs(ipxs->port);
if (rc == 0x453 || rc == 0x452) {
/* RIP/SAP special handling for mars_nwe */
IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
} else {
IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node,
IPX_NODE_LEN);
}
#endif /* CONFIG_IPX_INTERN */
ipx->ipx_source.sock = ipxs->port;
IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network;
memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
ipx->ipx_dest.sock = usipx->sipx_port;
rc = memcpy_fromiovec(skb_put(skb, len), iov, len);
if (rc) {
kfree_skb(skb);
goto out_put;
}
/* Apply checksum. Not allowed on 802.3 links. */
if (sk->sk_no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
ipx->ipx_checksum = 0xFFFF;
else
ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
rt->ir_router_node : ipx->ipx_dest.node);
out_put:
ipxitf_put(intrfc);
if (rt)
ipxrtr_put(rt);
out:
return rc;
}
/*
* We use a normal struct rtentry for route handling
*/
int ipxrtr_ioctl(unsigned int cmd, void __user *arg)
{
struct rtentry rt; /* Use these to behave like 'other' stacks */
struct sockaddr_ipx *sg, *st;
int rc = -EFAULT;
if (copy_from_user(&rt, arg, sizeof(rt)))
goto out;
sg = (struct sockaddr_ipx *)&rt.rt_gateway;
st = (struct sockaddr_ipx *)&rt.rt_dst;
rc = -EINVAL;
if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */
sg->sipx_family != AF_IPX ||
st->sipx_family != AF_IPX)
goto out;
switch (cmd) {
case SIOCDELRT:
rc = ipxrtr_delete(st->sipx_network);
break;
case SIOCADDRT: {
struct ipx_route_definition f;
f.ipx_network = st->sipx_network;
f.ipx_router_network = sg->sipx_network;
memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
rc = ipxrtr_create(&f);
break;
}
}
out:
return rc;
}

62
net/ipx/sysctl_net_ipx.c Normal file
View file

@ -0,0 +1,62 @@
/* -*- linux-c -*-
* sysctl_net_ipx.c: sysctl interface to net IPX subsystem.
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/ipx directory entry (empty =) ). [MS]
* Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#ifndef CONFIG_SYSCTL
#error This file should not be compiled without CONFIG_SYSCTL defined
#endif
/* From af_ipx.c */
extern int sysctl_ipx_pprop_broadcasting;
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 struct ctl_table ipx_dir_table[] = {
{
.ctl_name = NET_IPX,
.procname = "ipx",
.mode = 0555,
.child = ipx_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;
void ipx_register_sysctl(void)
{
ipx_table_header = register_sysctl_table(ipx_root_table, 1);
}
void ipx_unregister_sysctl(void)
{
unregister_sysctl_table(ipx_table_header);
}