summaryrefslogtreecommitdiffstats
path: root/net/ipx/af_ipx.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /net/ipx/af_ipx.c
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/ipx/af_ipx.c')
-rw-r--r--net/ipx/af_ipx.c1167
1 files changed, 605 insertions, 562 deletions
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 82a85f685..5b131e4a9 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -12,17 +12,17 @@
*
* All the material in this file is subject to the Gnu license version 2.
* Neither Alan Cox nor the Swansea University Computer Society admit liability
- * nor provide warranty for any of this software. This material is provided
- * as is and at no charge.
+ * nor provide warranty for any of this software. This material is provided
+ * as is and at no charge.
*
* 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
+ * new multi-protocol edition of hard_header
* Revision 0.23: IPX /proc by Mark Evans.
* Adding a route 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
+ * 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 modules)
@@ -46,6 +46,7 @@
* 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.
*
* Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
* pair. Also, now usage count is managed this way
@@ -56,14 +57,13 @@
*
*
* Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
- * Neither Greg Page nor Caldera, Inc. admit liability nor provide
- * warranty for any of this software. This material is provided
- * "AS-IS" and at no charge.
+ * Neither Greg Page nor Caldera, Inc. 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 <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -108,27 +108,31 @@ static struct datalink_proto *pEII_datalink = NULL;
static struct datalink_proto *p8023_datalink = NULL;
static struct datalink_proto *pSNAP_datalink = NULL;
+static struct proto_ops ipx_dgram_ops;
+
static ipx_route *ipx_routes = NULL;
static ipx_interface *ipx_interfaces = NULL;
static ipx_interface *ipx_primary_net = NULL;
static ipx_interface *ipx_internal_net = NULL;
-static int
-ipxcfg_set_auto_create(char val)
+static int ipxcfg_set_auto_create(char val)
{
- if (ipxcfg_auto_create_interfaces != val){
- if (val){
+ if (ipxcfg_auto_create_interfaces != val)
+ {
+ if (val)
+ {
MOD_INC_USE_COUNT;
- }else{
+ }
+ else
+ {
MOD_DEC_USE_COUNT;
}
ipxcfg_auto_create_interfaces = val;
}
return 0;
}
-
-static int
-ipxcfg_set_auto_select(char val)
+
+static int ipxcfg_set_auto_select(char val)
{
ipxcfg_auto_select_primary = val;
if (val && (ipx_primary_net == NULL))
@@ -136,11 +140,10 @@ ipxcfg_set_auto_select(char val)
return 0;
}
-static int
-ipxcfg_get_config_data(ipx_config_data *arg)
+static int ipxcfg_get_config_data(ipx_config_data *arg)
{
ipx_config_data vals;
-
+
vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
@@ -158,17 +161,16 @@ ipxcfg_get_config_data(ipx_config_data *arg)
* handler using this technique. They can be added although we do not
* use this facility.
*/
-
-static void
-ipx_remove_socket(ipx_socket *sk)
+
+static void ipx_remove_socket(struct sock *sk)
{
- ipx_socket *s;
+ struct sock *s;
ipx_interface *intrfc;
unsigned long flags;
save_flags(flags);
cli();
-
+
/* Determine interface with which socket is associated */
intrfc = sk->protinfo.af_ipx.intrfc;
if (intrfc == NULL) {
@@ -181,7 +183,7 @@ ipx_remove_socket(ipx_socket *sk)
intrfc->if_sklist=s->next;
restore_flags(flags);
return;
- }
+ }
while(s && s->next) {
if(s->next==sk) {
@@ -200,9 +202,8 @@ ipx_remove_socket(ipx_socket *sk)
* Once it is removed from the queue no interrupt or bottom half will
* touch it and we are (fairly 8-) ) safe.
*/
-
-static void
-ipx_destroy_socket(ipx_socket *sk)
+
+static void ipx_destroy_socket(struct sock *sk)
{
struct sk_buff *skb;
@@ -210,19 +211,18 @@ ipx_destroy_socket(ipx_socket *sk)
while((skb=skb_dequeue(&sk->receive_queue))!=NULL) {
kfree_skb(skb,FREE_READ);
}
-
+
sk_free(sk);
MOD_DEC_USE_COUNT;
}
-
+
/* 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(unsigned long);
-static void
-ipxitf_clear_primary_net(void)
+static void ipxitf_clear_primary_net(void)
{
if (ipxcfg_auto_select_primary && (ipx_interfaces != NULL))
ipx_primary_net = ipx_interfaces;
@@ -230,20 +230,18 @@ ipxitf_clear_primary_net(void)
ipx_primary_net = NULL;
}
-static ipx_interface *
-ipxitf_find_using_phys(struct device *dev, unsigned short datalink)
+static ipx_interface *ipxitf_find_using_phys(struct device *dev, unsigned short datalink)
{
ipx_interface *i;
- for (i=ipx_interfaces;
- i && ((i->if_dev!=dev) || (i->if_dlink_type!=datalink));
+ for (i=ipx_interfaces;
+ i && ((i->if_dev!=dev) || (i->if_dlink_type!=datalink));
i=i->if_next)
;
return i;
}
-static ipx_interface *
-ipxitf_find_using_net(unsigned long net)
+static ipx_interface *ipxitf_find_using_net(unsigned long net)
{
ipx_interface *i;
@@ -257,10 +255,9 @@ ipxitf_find_using_net(unsigned long net)
}
/* Sockets are bound to a particular IPX interface. */
-static void
-ipxitf_insert_socket(ipx_interface *intrfc, ipx_socket *sk)
+static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
{
- ipx_socket *s;
+ struct sock *s;
sk->protinfo.af_ipx.intrfc = intrfc;
sk->next = NULL;
@@ -273,13 +270,12 @@ ipxitf_insert_socket(ipx_interface *intrfc, ipx_socket *sk)
}
}
-static ipx_socket *
-ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
+static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
{
- ipx_socket *s;
+ struct sock *s;
- for (s=intrfc->if_sklist;
- (s != NULL) && (s->protinfo.af_ipx.port != port);
+ for (s=intrfc->if_sklist;
+ (s != NULL) && (s->protinfo.af_ipx.port != port);
s=s->next)
;
@@ -288,11 +284,10 @@ ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
#ifdef CONFIG_IPX_INTERN
-static ipx_socket *
-ipxitf_find_internal_socket(ipx_interface *intrfc,
+static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
unsigned char *node, unsigned short port)
{
- ipx_socket *s = intrfc->if_sklist;
+ struct sock *s = intrfc->if_sklist;
while (s != NULL)
{
@@ -304,16 +299,15 @@ ipxitf_find_internal_socket(ipx_interface *intrfc,
s = s->next;
}
return s;
-}
+}
#endif
static void ipxrtr_del_routes(ipx_interface *);
-static void
-ipxitf_down(ipx_interface *intrfc)
+static void ipxitf_down(ipx_interface *intrfc)
{
ipx_interface *i;
- ipx_socket *s, *t;
+ struct sock *s, *t;
/* Delete all routes associated with this interface */
ipxrtr_del_routes(intrfc);
@@ -335,11 +329,11 @@ ipxitf_down(ipx_interface *intrfc)
if (intrfc == ipx_interfaces) {
ipx_interfaces = intrfc->if_next;
} else {
- for (i = ipx_interfaces;
+ for (i = ipx_interfaces;
(i != NULL) && (i->if_next != intrfc);
i = i->if_next)
;
- if ((i != NULL) && (i->if_next == intrfc))
+ if ((i != NULL) && (i->if_next == intrfc))
i->if_next = intrfc->if_next;
}
@@ -357,8 +351,7 @@ ipxitf_down(ipx_interface *intrfc)
return;
}
-static int
-ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
+static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
{
struct device *dev = ptr;
ipx_interface *i, *tmp;
@@ -367,9 +360,9 @@ ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *
return NOTIFY_DONE;
for (i = ipx_interfaces; i != NULL; ) {
-
+
tmp = i->if_next;
- if (i->if_dev == dev)
+ if (i->if_dev == dev)
ipxitf_down(i);
i = tmp;
@@ -382,7 +375,7 @@ static int ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
{
int retval;
- if((retval = sock_queue_rcv_skb(sock, skb))<0)
+ if((retval = sock_queue_rcv_skb(sock, skb))<0)
{
/*
* skb->sk is NULL here, so FREE_WRITE does not hurt
@@ -398,11 +391,10 @@ static int ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
*/
#ifdef CONFIG_IPX_INTERN
-static int
-ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
{
- ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
- ipx_socket *s;
+ struct ipxhdr *ipx = skb->nh.ipxh;
+ struct sock *s;
int is_broadcast = (memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
IPX_NODE_LEN) == 0);
@@ -424,7 +416,7 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1 != NULL)
{
- skb1->arp = skb1->free = 1;
+ skb1->arp = 1;
}
else
{
@@ -462,11 +454,10 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
#else
-static int
-ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
{
- ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
- ipx_socket *sock1 = NULL, *sock2 = NULL;
+ struct ipxhdr *ipx = skb->nh.ipxh;
+ struct sock *sock1 = NULL, *sock2 = NULL;
struct sk_buff *skb1 = NULL, *skb2 = NULL;
sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
@@ -478,10 +469,10 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
* The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and
* 0x456(Diagnostic).
*/
-
- if (ipx_primary_net && (intrfc != ipx_primary_net))
+
+ if (ipx_primary_net && (intrfc != ipx_primary_net))
{
- switch (ntohs(ipx->ipx_dest.sock))
+ switch (ntohs(ipx->ipx_dest.sock))
{
case 0x452:
case 0x453:
@@ -492,7 +483,7 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
* interface via ipxitf_send; however, we'll cheat
* and just demux it here.
*/
- sock2 = ipxitf_find_socket(ipx_primary_net,
+ sock2 = ipxitf_find_socket(ipx_primary_net,
ipx->ipx_dest.sock);
break;
default:
@@ -500,57 +491,57 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
}
}
- /*
+ /*
* if there is nothing to do, return. The kfree will
* cancel any charging.
*/
-
- if (sock1 == NULL && sock2 == NULL)
+
+ if (sock1 == NULL && sock2 == NULL)
{
- if (!copy)
+ if (!copy)
kfree_skb(skb,FREE_WRITE);
return 0;
}
/*
* This next segment of code is a little awkward, but it sets it up
- * so that the appropriate number of copies of the SKB are made and
- * that skb1 and skb2 point to it (them) so that it (they) can be
+ * so that the appropriate number of copies of the SKB are made and
+ * that skb1 and skb2 point to it (them) so that it (they) can be
* demuxed to sock1 and/or sock2. If we are unable to make enough
* copies, we do as much as is possible.
*/
-
- if (copy)
+
+ if (copy)
{
skb1 = skb_clone(skb, GFP_ATOMIC);
- if (skb1 != NULL)
- skb1->arp = skb1->free = 1;
- }
- else
+ if (skb1)
+ skb1->arp=1;
+ }
+ else
{
skb1 = skb;
}
-
- if (skb1 == NULL)
- return -ENOMEM;
+
+ if (skb1 == NULL)
+ return -ENOMEM;
/*
- * Do we need 2 SKBs?
+ * Do we need 2 SKBs?
*/
-
- if (sock1 && sock2)
+
+ if (sock1 && sock2)
{
skb2 = skb_clone(skb1, GFP_ATOMIC);
- if (skb2 != NULL)
- skb2->arp = skb2->free = 1;
+ if (skb2 != NULL)
+ skb2->arp = 1;
}
- else
+ else
skb2 = skb1;
-
+
if (sock1)
(void) ipxitf_def_skb_handler(sock1, skb1);
- if (skb2 == NULL)
+ if (skb2 == NULL)
return -ENOMEM;
if (sock2)
@@ -560,8 +551,7 @@ ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
}
#endif
-static struct sk_buff *
-ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
+static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
{
struct sk_buff *skb2;
int in_offset = skb->h.raw - skb->head;
@@ -570,7 +560,7 @@ ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
/* Hopefully, most cases */
if (in_offset >= out_offset) {
- skb->arp = skb->free = 1;
+ skb->arp = 1;
return skb;
}
@@ -579,8 +569,8 @@ ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
skb2 = alloc_skb(len, GFP_ATOMIC);
if (skb2 != NULL) {
skb_reserve(skb2,out_offset);
+ skb2->nh.raw=
skb2->h.raw=skb_put(skb2,skb->len);
- skb2->free=1;
skb2->arp=1;
memcpy(skb2->h.raw, skb->h.raw, skb->len);
}
@@ -590,7 +580,7 @@ ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
{
- ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
+ struct ipxhdr *ipx = skb->nh.ipxh;
struct device *dev = intrfc->if_dev;
struct datalink_proto *dl = intrfc->if_dlink;
char dest_node[IPX_NODE_LEN];
@@ -616,17 +606,15 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
{
/*
* To our own node, loop and free the original.
+ * The internal net will receive on all node address.
*/
- if (memcmp(intrfc->if_node, node, IPX_NODE_LEN) == 0)
+ if ((intrfc == ipx_internal_net)
+ || memcmp(intrfc->if_node, node, IPX_NODE_LEN) == 0)
{
/*
* Don't charge sender
*/
- if(skb->sk)
- {
- atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
- skb->sk=NULL;
- }
+ skb_orphan(skb);
/*
* Will charge receiver
*/
@@ -635,38 +623,35 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
/*
* Broadcast, loop and possibly keep to send on.
*/
- if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
+ if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
{
- if (!send_to_wire && skb->sk)
- {
- atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
- skb->sk=NULL;
- }
+ if (!send_to_wire)
+ skb_orphan(skb);
ipxitf_demux_socket(intrfc, skb, send_to_wire);
- if (!send_to_wire)
+ if (!send_to_wire)
return 0;
}
}
/*
- * If the originating net is not equal to our net; this is routed
+ * If the originating net is not equal to our net; this is routed
* We are still charging the sender. Which is right - the driver
* free will handle this fairly.
*/
-
- if (ipx->ipx_source.net != intrfc->if_netnum)
+
+ if (ipx->ipx_source.net != intrfc->if_netnum)
{
- if (++(ipx->ipx_tctrl) > ipxcfg_max_hops)
+ if (++(ipx->ipx_tctrl) > ipxcfg_max_hops)
send_to_wire = 0;
}
- if (!send_to_wire)
+ if (!send_to_wire)
{
/*
* We do a FREE_WRITE here because this indicates how
- * to treat the socket with which the packet is
+ * to treat the socket with which the packet is
* associated. If this packet is associated with a
- * socket at all, it must be the originator of the
+ * socket at all, it must be the originator of the
* packet. Routed packets will have no socket associated
* with them.
*/
@@ -675,21 +660,21 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
}
/*
- * Determine the appropriate hardware address
+ * Determine the appropriate hardware address
*/
-
+
addr_len = dev->addr_len;
- if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
+ if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
memcpy(dest_node, dev->broadcast, addr_len);
else
memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
/*
- * Make any compensation for differing physical/data link size
+ * Make any compensation for differing physical/data link size
*/
-
+
skb = ipxitf_adjust_skbuff(intrfc, skb);
- if (skb == NULL)
+ if (skb == NULL)
return 0;
/* set up data link and physical headers */
@@ -701,15 +686,15 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
* Now log the packet just before transmission
*/
- dump_pkt("IPX snd:", (ipx_packet *)skb->h.raw);
- dump_data("ETH hdr:", skb->data, skb->h.raw - skb->data);
+ dump_pkt("IPX snd:", skb->nh.ipxh);
+ dump_data("ETH hdr:", skb->mac.raw, skb->nh.raw - skb->mac.raw);
#endif
/*
* Send it out
*/
-
- dev_queue_xmit(skb, dev, SOPRI_NORMAL);
+ skb->priority = SOPRI_NORMAL;
+ dev_queue_xmit(skb);
return 0;
}
@@ -726,40 +711,37 @@ static int ipxrtr_route_skb(struct sk_buff *);
static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
- ipx_packet *ipx = (ipx_packet *) (skb->h.raw);
+ struct ipxhdr *ipx = skb->nh.ipxh;
ipx_interface *i;
-#ifdef CONFIG_FIREWALL
/*
* We firewall first, ask questions later.
*/
-
- if (call_in_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
+
+ if (call_in_firewall(PF_IPX, skb->dev, ipx, NULL, &skb)!=FW_ACCEPT)
{
kfree_skb(skb, FREE_READ);
return 0;
}
-
-#endif
/* See if we should update our network number */
- if ((intrfc->if_netnum == 0L) &&
+ if ((intrfc->if_netnum == 0L) &&
(ipx->ipx_source.net == ipx->ipx_dest.net) &&
- (ipx->ipx_source.net != 0L))
+ (ipx->ipx_source.net != 0L))
{
/* 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.
*/
- if ((i=ipxitf_find_using_net(ipx->ipx_source.net))==NULL)
+ if ((i=ipxitf_find_using_net(ipx->ipx_source.net))==NULL)
{
intrfc->if_netnum = ipx->ipx_source.net;
(void) ipxitf_add_local_route(intrfc);
- }
- else
+ }
+ else
{
printk(KERN_WARNING "IPX: Network number collision %lx\n %s %s and %s %s\n",
- htonl(ipx->ipx_source.net),
+ htonl(ipx->ipx_source.net),
ipx_device_name(i),
ipx_frame_name(i->if_dlink_type),
ipx_device_name(intrfc),
@@ -767,26 +749,115 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
}
}
+#ifdef CONFIG_IPX_PPROP_ROUTING
+ if( ipx->ipx_type == IPX_TYPE_PPROP && ipx->ipx_tctrl < 8 )
+ {
+ int i;
+ ipx_interface *ifcs;
+ struct sk_buff *skb2;
+ long *l;
+ char *c;
+
+ if(skb->pkt_type!=PACKET_HOST)
+ {
+ kfree_skb(skb, FREE_READ);
+ return 0;
+ }
+
+#ifdef DEBUG_IPX_PPROP_ROUTING
+ printk(KERN_INFO "IPX: PPROP packet received\n"
+ " Src: %8x:%02x:%02x:%02x:%02x:%02x:%02x:%d/%d\n",
+ htonl(ipx->ipx_source.net),
+ ipx->ipx_source.node[0], ipx->ipx_source.node[1],
+ ipx->ipx_source.node[2], ipx->ipx_source.node[3],
+ ipx->ipx_source.node[4], ipx->ipx_source.node[5],
+ htons(ipx->ipx_source.sock),
+ htons(ipx->ipx_dest.sock)
+ );
+#endif
+
+ c = (char *) skb->data;
+ c += sizeof( struct ipxhdr );
+
+ l = (long *) c;
+
+#ifdef DEBUG_IPX_PPROP_ROUTING
+ printk( "IPX: Routing PPROP from net num %08x\n", (unsigned int) htonl(intrfc->if_netnum) );
+ for( i = 0 ; i < ipx->ipx_tctrl ; i++ )
+ printk( "IPX: Routing PPROP seen net num %08x\n", (unsigned int) htonl(*l++) );
+ l = (long *) c;
+#endif
+ i = 0;
+ /*
+ * Dump packet if too many hops or already seen this net
+ */
+ if( ipx->ipx_tctrl < 8 )
+ for( ; i < ipx->ipx_tctrl ; i++ )
+ if( *l++ == intrfc->if_netnum )
+ break;
+
+ if( i == ipx->ipx_tctrl )
+ {
+ /* < 8 hops && input itfc not in list */
+ *l = intrfc->if_netnum; /* insert recvd netnum into list */
+ /* xmit on all other interfaces... */
+ for ( ifcs = ipx_interfaces; ifcs != NULL ; ifcs = ifcs->if_next)
+ {
+ /* That aren't in the list */
+ l = (long *) c;
+ for( i = 0 ; i <= ipx->ipx_tctrl ; i++ )
+ if( ifcs->if_netnum == *l++ )
+ break;
+ if( i - 1 == ipx->ipx_tctrl )
+ {
+ ipx->ipx_dest.net = ifcs->if_netnum;
+#ifdef DEBUG_IPX_PPROP_ROUTING
+ printk( "IPX: Forward PPROP onto net num %08x\n", (unsigned int) htonl(ifcs->if_netnum) );
+#endif
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+
+ /*
+ * See if we are allowed to firewall forward
+ */
+ if (call_fw_firewall(PF_IPX, skb2->dev, ipx, NULL, &skb)!=FW_ACCEPT)
+ {
+ kfree_skb(skb, FREE_READ);
+ return 0;
+ }
+ ipxrtr_route_skb(skb2);
+ }
+#ifdef DEBUG_IPX_PPROP_ROUTING
+ else
+ printk( "IPX: Ignoring PPROP for net num %08x\n", (unsigned int) htonl(ifcs->if_netnum) );
+#endif
+ }
+ /*
+ * Reset network number in packet
+ */
+ ipx->ipx_dest.net = intrfc->if_netnum;
+ }
+
+ }
+#endif
+
if (ipx->ipx_dest.net == 0L)
ipx->ipx_dest.net = intrfc->if_netnum;
if (ipx->ipx_source.net == 0L)
ipx->ipx_source.net = intrfc->if_netnum;
- if (intrfc->if_netnum != ipx->ipx_dest.net)
+ if (intrfc->if_netnum != ipx->ipx_dest.net)
{
-#ifdef CONFIG_FIREWALL
/*
* See if we are allowed to firewall forward
*/
- if (call_fw_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
+ if (call_fw_firewall(PF_IPX, skb->dev, ipx, NULL, &skb)!=FW_ACCEPT)
{
kfree_skb(skb, FREE_READ);
return 0;
}
-#endif
+
/* We only route point-to-point packets. */
- if ((skb->pkt_type != PACKET_BROADCAST) &&
- (skb->pkt_type != PACKET_MULTICAST))
+ if (skb->pkt_type == PACKET_HOST)
{
skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
if(skb)
@@ -799,8 +870,8 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
}
/* see if we should keep it */
- if ((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
- || (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
+ if ((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
+ || (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
{
return ipxitf_demux_socket(intrfc, skb, 0);
}
@@ -810,8 +881,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
return 0;
}
-static void
-ipxitf_insert(ipx_interface *intrfc)
+static void ipxitf_insert(ipx_interface *intrfc)
{
ipx_interface *i;
@@ -830,16 +900,17 @@ ipxitf_insert(ipx_interface *intrfc)
return;
}
-static int
-ipxitf_create_internal(ipx_interface_definition *idef)
+static int ipxitf_create_internal(ipx_interface_definition *idef)
{
ipx_interface *intrfc;
/* Only one primary network allowed */
- if (ipx_primary_net != NULL) return -EEXIST;
+ if (ipx_primary_net != NULL)
+ return -EEXIST;
/* Must have a valid network number */
- if (idef->ipx_network == 0L) return -EADDRNOTAVAIL;
+ if (idef->ipx_network == 0L)
+ return -EADDRNOTAVAIL;
if (ipxitf_find_using_net(idef->ipx_network) != NULL)
return -EADDRINUSE;
@@ -861,28 +932,32 @@ ipxitf_create_internal(ipx_interface_definition *idef)
return ipxitf_add_local_route(intrfc);
}
-static int
-ipx_map_frame_type(unsigned char type)
+static int ipx_map_frame_type(unsigned char type)
{
- switch (type) {
- case IPX_FRAME_ETHERII: return htons(ETH_P_IPX);
- case IPX_FRAME_8022: return htons(ETH_P_802_2);
- case IPX_FRAME_TR_8022: return htons(ETH_P_TR_802_2);
- case IPX_FRAME_SNAP: return htons(ETH_P_SNAP);
- case IPX_FRAME_8023: return htons(ETH_P_802_3);
+ switch (type)
+ {
+ case IPX_FRAME_ETHERII:
+ return htons(ETH_P_IPX);
+ case IPX_FRAME_8022:
+ return htons(ETH_P_802_2);
+ case IPX_FRAME_TR_8022:
+ return htons(ETH_P_TR_802_2);
+ case IPX_FRAME_SNAP:
+ return htons(ETH_P_SNAP);
+ case IPX_FRAME_8023:
+ return htons(ETH_P_802_3);
}
return 0;
}
-static int
-ipxitf_create(ipx_interface_definition *idef)
+static int ipxitf_create(ipx_interface_definition *idef)
{
struct device *dev;
unsigned short dlink_type = 0;
struct datalink_proto *datalink = NULL;
ipx_interface *intrfc;
- if (idef->ipx_special == IPX_INTERNAL)
+ if (idef->ipx_special == IPX_INTERNAL)
return ipxitf_create_internal(idef);
if ((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL))
@@ -892,37 +967,38 @@ ipxitf_create(ipx_interface_definition *idef)
(ipxitf_find_using_net(idef->ipx_network) != NULL))
return -EADDRINUSE;
- switch (idef->ipx_dlink_type) {
- case IPX_FRAME_ETHERII:
- dlink_type = htons(ETH_P_IPX);
- datalink = pEII_datalink;
- break;
- case IPX_FRAME_TR_8022:
- dlink_type = htons(ETH_P_TR_802_2);
- datalink = p8022tr_datalink;
- break;
- case IPX_FRAME_8022:
- dlink_type = htons(ETH_P_802_2);
- datalink = p8022_datalink;
- break;
- case IPX_FRAME_SNAP:
- dlink_type = htons(ETH_P_SNAP);
- datalink = pSNAP_datalink;
- break;
- case IPX_FRAME_8023:
- dlink_type = htons(ETH_P_802_3);
- datalink = p8023_datalink;
- break;
- case IPX_FRAME_NONE:
- default:
- break;
- }
-
- if (datalink == NULL)
+ switch (idef->ipx_dlink_type)
+ {
+ case IPX_FRAME_ETHERII:
+ dlink_type = htons(ETH_P_IPX);
+ datalink = pEII_datalink;
+ break;
+ case IPX_FRAME_TR_8022:
+ dlink_type = htons(ETH_P_TR_802_2);
+ datalink = p8022tr_datalink;
+ break;
+ case IPX_FRAME_8022:
+ dlink_type = htons(ETH_P_802_2);
+ datalink = p8022_datalink;
+ break;
+ case IPX_FRAME_SNAP:
+ dlink_type = htons(ETH_P_SNAP);
+ datalink = pSNAP_datalink;
+ break;
+ case IPX_FRAME_8023:
+ dlink_type = htons(ETH_P_802_3);
+ datalink = p8023_datalink;
+ break;
+ case IPX_FRAME_NONE:
+ default:
+ break;
+ }
+
+ if (datalink == NULL)
return -EPROTONOSUPPORT;
dev=dev_get(idef->ipx_device);
- if (dev==NULL)
+ if (dev==NULL)
return -ENODEV;
if (!(dev->flags & IFF_UP))
@@ -932,7 +1008,7 @@ ipxitf_create(ipx_interface_definition *idef)
if(dev->addr_len>IPX_NODE_LEN)
return -EINVAL;
- if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL)
+ if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL)
{
/* Ok now create */
intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
@@ -945,14 +1021,14 @@ ipxitf_create(ipx_interface_definition *idef)
intrfc->if_sklist = NULL;
intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
/* Setup primary if necessary */
- if ((idef->ipx_special == IPX_PRIMARY))
+ if ((idef->ipx_special == IPX_PRIMARY))
ipx_primary_net = intrfc;
intrfc->if_internal = 0;
intrfc->if_ipx_offset = dev->hard_header_len + datalink->header_length;
if(memcmp(idef->ipx_node, "\000\000\000\000\000\000", IPX_NODE_LEN)==0)
{
memset(intrfc->if_node, 0, IPX_NODE_LEN);
- memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
+ memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
dev->dev_addr, dev->addr_len);
}
else
@@ -961,21 +1037,22 @@ ipxitf_create(ipx_interface_definition *idef)
}
/* If the network number is known, add a route */
- if (intrfc->if_netnum == 0L)
+ if (intrfc->if_netnum == 0L)
return 0;
return ipxitf_add_local_route(intrfc);
}
-static int
-ipxitf_delete(ipx_interface_definition *idef)
+static int ipxitf_delete(ipx_interface_definition *idef)
{
struct device *dev = NULL;
unsigned short dlink_type = 0;
ipx_interface *intrfc;
- if (idef->ipx_special == IPX_INTERNAL) {
- if (ipx_internal_net != NULL) {
+ if (idef->ipx_special == IPX_INTERNAL)
+ {
+ if (ipx_internal_net != NULL)
+ {
ipxitf_down(ipx_internal_net);
return 0;
}
@@ -997,21 +1074,33 @@ ipxitf_delete(ipx_interface_definition *idef)
return -EINVAL;
}
-static ipx_interface *
-ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
+static ipx_interface *ipxitf_auto_create(struct device *dev,
+ unsigned short dlink_type)
{
struct datalink_proto *datalink = NULL;
ipx_interface *intrfc;
- switch (htons(dlink_type)) {
- case ETH_P_IPX: datalink = pEII_datalink; break;
- case ETH_P_802_2: datalink = p8022_datalink; break;
- case ETH_P_TR_802_2: datalink = p8022tr_datalink; break;
- case ETH_P_SNAP: datalink = pSNAP_datalink; break;
- case ETH_P_802_3: datalink = p8023_datalink; break;
- default: return NULL;
+ switch (htons(dlink_type))
+ {
+ case ETH_P_IPX:
+ datalink = pEII_datalink;
+ break;
+ case ETH_P_802_2:
+ datalink = p8022_datalink;
+ break;
+ case ETH_P_TR_802_2:
+ datalink = p8022tr_datalink;
+ break;
+ case ETH_P_SNAP:
+ datalink = pSNAP_datalink;
+ break;
+ case ETH_P_802_3:
+ datalink = p8023_datalink;
+ break;
+ default:
+ return NULL;
}
-
+
if (dev == NULL)
return NULL;
@@ -1019,7 +1108,8 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
if(dev->addr_len>IPX_NODE_LEN) return NULL;
intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
- if (intrfc!=NULL) {
+ if (intrfc!=NULL)
+ {
intrfc->if_dev=dev;
intrfc->if_netnum=0L;
intrfc->if_dlink_type = dlink_type;
@@ -1027,10 +1117,10 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
intrfc->if_sklist = NULL;
intrfc->if_internal = 0;
intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
- intrfc->if_ipx_offset = dev->hard_header_len +
+ intrfc->if_ipx_offset = dev->hard_header_len +
datalink->header_length;
memset(intrfc->if_node, 0, IPX_NODE_LEN);
- memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
+ memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
dev->dev_addr, dev->addr_len);
ipxitf_insert(intrfc);
}
@@ -1038,12 +1128,12 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
return intrfc;
}
-static int
-ipxitf_ioctl_real(unsigned int cmd, void *arg)
+static int ipxitf_ioctl_real(unsigned int cmd, void *arg)
{
switch(cmd)
{
- case SIOCSIFADDR: {
+ case SIOCSIFADDR:
+ {
struct ifreq ifr;
struct sockaddr_ipx *sipx;
ipx_interface_definition f;
@@ -1063,13 +1153,14 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
else
return ipxitf_create(&f);
}
- case SIOCGIFADDR: {
+ case SIOCGIFADDR:
+ {
struct ifreq ifr;
struct sockaddr_ipx *sipx;
ipx_interface *ipxif;
struct device *dev;
int err;
-
+
if (copy_from_user(&ifr,arg,sizeof(ifr)))
return -EFAULT;
sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
@@ -1087,14 +1178,16 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
return -EFAULT;
return err;
}
- case SIOCAIPXITFCRT: {
+ case SIOCAIPXITFCRT:
+ {
int err, val;
err = get_user(val, (unsigned char *) arg);
if (err)
return err;
return ipxcfg_set_auto_create(val);
}
- case SIOCAIPXPRISLT: {
+ case SIOCAIPXPRISLT:
+ {
int err, val;
err = get_user(val, (unsigned char *) arg);
if (err)
@@ -1106,8 +1199,7 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
}
}
-static int
-ipxitf_ioctl(unsigned int cmd, void *arg)
+static int ipxitf_ioctl(unsigned int cmd, void *arg)
{
int ret;
MOD_INC_USE_COUNT;
@@ -1115,14 +1207,14 @@ ipxitf_ioctl(unsigned int cmd, void *arg)
MOD_DEC_USE_COUNT;
return ret;
}
+
/*******************************************************************************************************************\
* *
* Routing tables for the IPX socket layer *
* *
\*******************************************************************************************************************/
-static ipx_route *
-ipxrtr_lookup(unsigned long net)
+static ipx_route *ipxrtr_lookup(unsigned long net)
{
ipx_route *r;
@@ -1132,14 +1224,14 @@ ipxrtr_lookup(unsigned long net)
return r;
}
-static int
-ipxrtr_add_route(unsigned long network, ipx_interface *intrfc, unsigned char *node)
+static int ipxrtr_add_route(unsigned long network, ipx_interface *intrfc, unsigned char *node)
{
ipx_route *rt;
/* Get a route structure; either existing or create */
rt = ipxrtr_lookup(network);
- if (rt==NULL) {
+ if (rt==NULL)
+ {
rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);
if(rt==NULL)
return -EAGAIN;
@@ -1161,8 +1253,7 @@ ipxrtr_add_route(unsigned long network, ipx_interface *intrfc, unsigned char *no
return 0;
}
-static void
-ipxrtr_del_routes(ipx_interface *intrfc)
+static void ipxrtr_del_routes(ipx_interface *intrfc)
{
ipx_route **r, *tmp;
@@ -1176,8 +1267,7 @@ ipxrtr_del_routes(ipx_interface *intrfc)
}
}
-static int
-ipxrtr_create(ipx_route_definition *rd)
+static int ipxrtr_create(ipx_route_definition *rd)
{
ipx_interface *intrfc;
@@ -1190,22 +1280,22 @@ ipxrtr_create(ipx_route_definition *rd)
}
-static int
-ipxrtr_delete(long net)
+static int ipxrtr_delete(long net)
{
ipx_route **r;
ipx_route *tmp;
- for (r = &ipx_routes; (tmp = *r) != NULL; ) {
- if (tmp->ir_net == net) {
- if (!(tmp->ir_routed)) {
+ for (r = &ipx_routes; (tmp = *r) != NULL; )
+ {
+ if (tmp->ir_net == net)
+ {
+ if (!(tmp->ir_routed))
/* Directly connected; can't lose route */
return -EPERM;
- }
*r = tmp->ir_next;
kfree_s(tmp, sizeof(ipx_route));
return 0;
- }
+ }
r = &(tmp->ir_next);
}
@@ -1218,7 +1308,7 @@ ipxrtr_delete(long net)
/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
-static __u16 ipx_set_checksum(ipx_packet *packet,int length)
+static __u16 ipx_set_checksum(struct ipxhdr *packet,int length)
{
/*
* NOTE: sum is a net byte order quantity, which optimizes the
@@ -1235,73 +1325,73 @@ static __u16 ipx_set_checksum(ipx_packet *packet,int length)
__u16 *p=(__u16 *)&packet->ipx_pktsize;
/*
- * Number of complete words
+ * Number of complete words
*/
__u32 i=length>>1;
/*
- * Loop through all complete words except the checksum field
+ * Loop through all complete words except the checksum field
*/
while(--i)
sum+=*p++;
/*
- * Add on the last part word if it exists
+ * Add on the last part word if it exists
*/
if(packet->ipx_pktsize&htons(1))
sum+=ntohs(0xff00)&*p;
/*
- * Do final fixup
+ * Do final fixup
*/
-
+
sum=(sum&0xffff)+(sum>>16);
/*
- * It's a pity there's no concept of carry in C
+ * It's a pity there's no concept of carry in C
*/
if(sum>=0x10000)
sum++;
-
+
return ~sum;
};
-
+
/*
* Route an outgoing frame from a socket.
*/
-static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len, int noblock)
+static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len, int noblock)
{
struct sk_buff *skb;
ipx_interface *intrfc;
- ipx_packet *ipx;
+ struct ipxhdr *ipx;
int size;
int ipx_offset;
ipx_route *rt = NULL;
int err;
-
+
/* Find the appropriate interface on which to send packet */
- if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL))
+ if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL))
{
usipx->sipx_network = ipx_primary_net->if_netnum;
intrfc = ipx_primary_net;
- }
- else
+ }
+ else
{
rt = ipxrtr_lookup(usipx->sipx_network);
- if (rt==NULL) {
+ if (rt==NULL)
return -ENETUNREACH;
- }
+
intrfc = rt->ir_intrfc;
}
-
+
ipx_offset = intrfc->if_ipx_offset;
- size=sizeof(ipx_packet)+len;
+ size=sizeof(struct ipxhdr)+len;
size += ipx_offset;
skb=sock_alloc_send_skb(sk, size, 0, noblock, &err);
@@ -1309,22 +1399,21 @@ static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struc
return err;
skb_reserve(skb,ipx_offset);
- skb->free=1;
skb->arp=1;
skb->sk=sk;
/* Fill in IPX header */
- ipx=(ipx_packet *)skb_put(skb,sizeof(ipx_packet));
- ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
+ ipx=(struct ipxhdr *)skb_put(skb,sizeof(struct ipxhdr));
+ ipx->ipx_pktsize=htons(len+sizeof(struct ipxhdr));
ipx->ipx_tctrl=0;
ipx->ipx_type=usipx->sipx_type;
- skb->h.raw = (unsigned char *)ipx;
+ skb->h.raw = (void *)skb->nh.ipxh = ipx;
ipx->ipx_source.net = sk->protinfo.af_ipx.intrfc->if_netnum;
#ifdef CONFIG_IPX_INTERN
memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
#else
- if ((err = ntohs(sk->protinfo.af_ipx.port)) == 0x453 || err == 0x452)
+ if ((err = ntohs(sk->protinfo.af_ipx.port)) == 0x453 || err == 0x452)
{
/* RIP/SAP special handling for mars_nwe */
ipx->ipx_source.net = intrfc->if_netnum;
@@ -1355,35 +1444,33 @@ static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struc
if(sk->no_check || intrfc->if_dlink_type==IPX_FRAME_8023)
ipx->ipx_checksum=0xFFFF;
else
- ipx->ipx_checksum=ipx_set_checksum(ipx, len+sizeof(ipx_packet));
+ ipx->ipx_checksum=ipx_set_checksum(ipx, len+sizeof(struct ipxhdr));
-#ifdef CONFIG_FIREWALL
- if(call_out_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
+ if(call_out_firewall(PF_IPX, skb->dev, ipx, NULL, &skb)!=FW_ACCEPT)
{
kfree_skb(skb, FREE_WRITE);
return -EPERM;
}
-#endif
return ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
rt->ir_router_node : ipx->ipx_dest.node);
}
-static int
-ipxrtr_route_skb(struct sk_buff *skb)
+static int ipxrtr_route_skb(struct sk_buff *skb)
{
- ipx_packet *ipx = (ipx_packet *) (skb->h.raw);
+ struct ipxhdr *ipx = skb->nh.ipxh;
ipx_route *r;
ipx_interface *i;
r = ipxrtr_lookup(ipx->ipx_dest.net);
- if (r == NULL) {
+ if (r == NULL)
+ {
/* no known route */
kfree_skb(skb,FREE_READ);
return 0;
}
i = r->ir_intrfc;
- (void)ipxitf_send(i, skb, (r->ir_routed) ?
+ (void)ipxitf_send(i, skb, (r->ir_routed) ?
r->ir_router_node : ipx->ipx_dest.node);
return 0;
}
@@ -1397,21 +1484,21 @@ static int ipxrtr_ioctl(unsigned int cmd, void *arg)
int err;
struct rtentry rt; /* Use these to behave like 'other' stacks */
struct sockaddr_ipx *sg,*st;
-
+
err = copy_from_user(&rt,arg,sizeof(rt));
if (err)
- return -EFAULT;
+ return -EFAULT;
sg=(struct sockaddr_ipx *)&rt.rt_gateway;
st=(struct sockaddr_ipx *)&rt.rt_dst;
-
+
if(!(rt.rt_flags&RTF_GATEWAY))
return -EINVAL; /* Direct routes are fixed */
if(sg->sipx_family!=AF_IPX)
return -EINVAL;
if(st->sipx_family!=AF_IPX)
return -EINVAL;
-
+
switch(cmd)
{
case SIOCDELRT:
@@ -1429,21 +1516,26 @@ static int ipxrtr_ioctl(unsigned int cmd, void *arg)
}
}
-static const char *
-ipx_frame_name(unsigned short frame)
+static const char *ipx_frame_name(unsigned short frame)
{
- switch (ntohs(frame)) {
- case ETH_P_IPX: return "EtherII";
- case ETH_P_802_2: return "802.2";
- case ETH_P_SNAP: return "SNAP";
- case ETH_P_802_3: return "802.3";
- case ETH_P_TR_802_2: return "802.2TR";
- default: return "None";
+ switch (ntohs(frame))
+ {
+ case ETH_P_IPX:
+ return "EtherII";
+ case ETH_P_802_2:
+ return "802.2";
+ case ETH_P_SNAP:
+ return "SNAP";
+ case ETH_P_802_3:
+ return "802.3";
+ case ETH_P_TR_802_2:
+ return "802.2TR";
+ default:
+ return "None";
}
}
-static const char *
-ipx_device_name(ipx_interface *intrfc)
+static const char *ipx_device_name(ipx_interface *intrfc)
{
return (intrfc->if_internal ? "Internal" :
(intrfc->if_dev ? intrfc->if_dev->name : "Unknown"));
@@ -1460,22 +1552,22 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
/* Theory.. Keep printing in the same place until we pass offset */
- len += sprintf (buffer,"%-11s%-15s%-9s%-11s%s\n", "Network",
+ len += sprintf (buffer,"%-11s%-15s%-9s%-11s%s\n", "Network",
"Node_Address", "Primary", "Device", "Frame_Type");
for (i = ipx_interfaces; i != NULL; i = i->if_next) {
len += sprintf(buffer+len, "%08lX ", ntohl(i->if_netnum));
- len += sprintf (buffer+len,"%02X%02X%02X%02X%02X%02X ",
+ len += sprintf (buffer+len,"%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]);
len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ?
"Yes" : "No");
len += sprintf (buffer+len, "%-11s", ipx_device_name(i));
- len += sprintf (buffer+len, "%s\n",
+ len += sprintf (buffer+len, "%s\n",
ipx_frame_name(i->if_dlink_type));
/* Are we still dumping unwanted data then discard the record */
pos=begin+len;
-
+
if(pos<offset) {
len=0; /* Keep dumping into the buffer start */
begin=pos;
@@ -1483,20 +1575,20 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
if(pos>offset+length) /* We have dumped enough */
break;
}
-
+
/* The data in question runs from begin to begin+len */
*start=buffer+(offset-begin); /* Start of wanted data */
len-=(offset-begin); /* Remove unwanted header data from length */
if(len>length)
len=length; /* Remove unwanted tail data from length */
-
+
return len;
}
static int ipx_get_info(char *buffer, char **start, off_t offset,
int length, int dummy)
{
- ipx_socket *s;
+ struct sock *s;
ipx_interface *i;
int len=0;
off_t pos=0;
@@ -1504,28 +1596,28 @@ static int ipx_get_info(char *buffer, char **start, off_t offset,
/* Theory.. Keep printing in the same place until we pass offset */
-#ifdef CONFIG_IPX_INTERN
- len += sprintf (buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+#ifdef CONFIG_IPX_INTERN
+ len += sprintf (buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
#else
- len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+ len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
#endif
- "Remote_Address", "Tx_Queue", "Rx_Queue",
+ "Remote_Address", "Tx_Queue", "Rx_Queue",
"State", "Uid");
for (i = ipx_interfaces; i != NULL; i = i->if_next) {
for (s = i->if_sklist; s != NULL; s = s->next) {
#ifdef CONFIG_IPX_INTERN
len += sprintf(buffer+len,
- "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
+ "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
htonl(s->protinfo.af_ipx.intrfc->if_netnum),
s->protinfo.af_ipx.node[0],
- s->protinfo.af_ipx.node[1],
- s->protinfo.af_ipx.node[2],
- s->protinfo.af_ipx.node[3],
- s->protinfo.af_ipx.node[4],
+ s->protinfo.af_ipx.node[1],
+ s->protinfo.af_ipx.node[2],
+ s->protinfo.af_ipx.node[3],
+ s->protinfo.af_ipx.node[4],
s->protinfo.af_ipx.node[5],
htons(s->protinfo.af_ipx.port));
#else
- len += sprintf(buffer+len,"%08lX:%04X ",
+ len += sprintf(buffer+len,"%08lX:%04X ",
htonl(i->if_netnum),
htons(s->protinfo.af_ipx.port));
#endif
@@ -1533,24 +1625,25 @@ static int ipx_get_info(char *buffer, char **start, off_t offset,
len += sprintf(buffer+len, "%-28s", "Not_Connected");
} else {
len += sprintf (buffer+len,
- "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
+ "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
htonl(s->protinfo.af_ipx.dest_addr.net),
s->protinfo.af_ipx.dest_addr.node[0],
- s->protinfo.af_ipx.dest_addr.node[1],
+ s->protinfo.af_ipx.dest_addr.node[1],
s->protinfo.af_ipx.dest_addr.node[2],
- s->protinfo.af_ipx.dest_addr.node[3],
+ s->protinfo.af_ipx.dest_addr.node[3],
s->protinfo.af_ipx.dest_addr.node[4],
s->protinfo.af_ipx.dest_addr.node[5],
htons(s->protinfo.af_ipx.dest_addr.sock));
}
- len += sprintf (buffer+len,"%08X %08X ",
- s->wmem_alloc, s->rmem_alloc);
- len += sprintf (buffer+len,"%02X %03d\n",
+ len += sprintf (buffer+len,"%08X %08X ",
+ atomic_read(&s->wmem_alloc),
+ atomic_read(&s->rmem_alloc));
+ len += sprintf (buffer+len,"%02X %03d\n",
s->state, SOCK_INODE(s->socket)->i_uid);
-
+
/* Are we still dumping unwanted data then discard the record */
pos=begin+len;
-
+
if(pos<offset)
{
len=0; /* Keep dumping into the buffer start */
@@ -1560,13 +1653,13 @@ static int ipx_get_info(char *buffer, char **start, off_t offset,
break;
}
}
-
+
/* The data in question runs from begin to begin+len */
*start=buffer+(offset-begin); /* Start of wanted data */
len-=(offset-begin); /* Remove unwanted header data from length */
if(len>length)
len=length; /* Remove unwanted tail data from length */
-
+
return len;
}
@@ -1578,16 +1671,16 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset,
off_t pos=0;
off_t begin=0;
- len += sprintf (buffer,"%-11s%-13s%s\n",
+ len += sprintf (buffer,"%-11s%-13s%s\n",
"Network", "Router_Net", "Router_Node");
for (rt = ipx_routes; rt != NULL; rt = rt->ir_next)
{
len += sprintf (buffer+len,"%08lX ", ntohl(rt->ir_net));
if (rt->ir_routed) {
- len += sprintf (buffer+len,"%08lX %02X%02X%02X%02X%02X%02X\n",
- 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],
+ len += sprintf (buffer+len,"%08lX %02X%02X%02X%02X%02X%02X\n",
+ 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 {
len += sprintf (buffer+len, "%-13s%s\n",
@@ -1615,29 +1708,20 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset,
* *
\*******************************************************************************************************************/
-static int ipx_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- switch(cmd)
- {
- default:
- return(-EINVAL);
- }
-}
-
static int ipx_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{
- ipx_socket *sk;
+ struct sock *sk;
int err,opt;
-
- sk=(ipx_socket *)sock->data;
-
- if (optval==NULL)
+
+ sk=sock->sk;
+
+ if (optlen!=sizeof(int))
return(-EINVAL);
err = get_user(opt, (unsigned int *)optval);
if (err)
return err;
-
+
switch(level)
{
case SOL_IPX:
@@ -1647,26 +1731,23 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, char *opt
sk->protinfo.af_ipx.type=opt;
return 0;
default:
- return -EOPNOTSUPP;
+ return -ENOPROTOOPT;
}
break;
-
- case SOL_SOCKET:
- return sock_setsockopt(sk,level,optname,optval,optlen);
default:
- return -EOPNOTSUPP;
+ return -ENOPROTOOPT;
}
}
static int ipx_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen)
{
- ipx_socket *sk;
+ struct sock *sk;
int val=0;
- int err;
-
- sk=(ipx_socket *)sock->data;
+ int len;
+
+ sk=sock->sk;
switch(level)
{
@@ -1681,90 +1762,51 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
return -ENOPROTOOPT;
}
break;
-
- case SOL_SOCKET:
- return sock_getsockopt(sk,level,optname,optval,optlen);
-
- default:
- return -EOPNOTSUPP;
- }
- err = put_user(sizeof(int), optlen);
- if (!err)
- err = put_user(val, (int *)optval);
- return err;
-}
-static int ipx_listen(struct socket *sock, int backlog)
-{
- return -EOPNOTSUPP;
-}
-
-static void def_callback1(struct sock *sk)
-{
- if(!sk->dead)
- wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk, int len)
-{
- if(!sk->dead)
- {
- wake_up_interruptible(sk->sleep);
- sock_wake_async(sk->socket, 1);
- }
+ default:
+ return -ENOPROTOOPT;
+ }
+ if(get_user(len,optlen))
+ return -EFAULT;
+ len=min(len,sizeof(int));
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval,&val,len))
+ return -EFAULT;
+ return 0;
}
static int ipx_create(struct socket *sock, int protocol)
{
- ipx_socket *sk;
- sk=(ipx_socket *)sk_alloc(GFP_KERNEL);
+ struct sock *sk;
+ sk=sk_alloc(GFP_KERNEL);
if(sk==NULL)
return(-ENOMEM);
switch(sock->type)
{
case SOCK_DGRAM:
+ sock->ops = &ipx_dgram_ops;
break;
default:
- kfree_s((void *)sk,sizeof(*sk));
+ sk_free(sk);
return(-ESOCKTNOSUPPORT);
}
- sk->rcvbuf=SK_RMEM_MAX;
- sk->sndbuf=SK_WMEM_MAX;
- sk->prot=NULL; /* So we use default free mechanisms */
- skb_queue_head_init(&sk->receive_queue);
- skb_queue_head_init(&sk->write_queue);
- sk->send_head=NULL;
- skb_queue_head_init(&sk->back_log);
- sk->state=TCP_CLOSE;
- sk->socket=sock;
- sk->type=sock->type;
+ sock_init_data(sock,sk);
sk->mtu=IPX_MTU;
- sk->no_check = 1; /* Checksum off by default */
- if(sock!=NULL)
- {
- sock->data=(void *)sk;
- sk->sleep=sock->wait;
- }
-
- sk->state_change=def_callback1;
- sk->data_ready=def_callback2;
- sk->write_space=def_callback1;
- sk->error_report=def_callback1;
-
- sk->zapped=1;
+ sk->no_check = 1; /* Checksum off by default */
MOD_INC_USE_COUNT;
return 0;
}
static int ipx_release(struct socket *sock, struct socket *peer)
{
- ipx_socket *sk=(ipx_socket *)sock->data;
+ struct sock *sk=sock->sk;
if(sk==NULL)
return(0);
if(!sk->dead)
sk->state_change(sk);
sk->dead=1;
- sock->data=NULL;
+ sock->sk=NULL;
ipx_destroy_socket(sk);
return(0);
}
@@ -1774,8 +1816,7 @@ static int ipx_dup(struct socket *newsock,struct socket *oldsock)
return(ipx_create(newsock,SOCK_DGRAM));
}
-static unsigned short
-ipx_first_free_socketnum(ipx_interface *intrfc)
+static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc)
{
unsigned short socketNum = intrfc->if_sknum;
@@ -1791,21 +1832,21 @@ ipx_first_free_socketnum(ipx_interface *intrfc)
intrfc->if_sknum = socketNum;
return ntohs(socketNum);
}
-
+
static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
- ipx_socket *sk;
+ struct sock *sk;
ipx_interface *intrfc;
struct sockaddr_ipx *addr=(struct sockaddr_ipx *)uaddr;
-
- sk=(ipx_socket *)sock->data;
-
+
+ sk=sock->sk;
+
if(sk->zapped==0)
return -EINVAL;
-
+
if(addr_len!=sizeof(struct sockaddr_ipx))
return -EINVAL;
-
+
intrfc = ipxitf_find_using_net(addr->sipx_network);
if (intrfc == NULL)
return -EADDRNOTAVAIL;
@@ -1843,13 +1884,11 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, IPX_NODE_LEN);
}
- if (ipxitf_find_internal_socket(intrfc,
- sk->protinfo.af_ipx.node,
+ if (ipxitf_find_internal_socket(intrfc,
+ sk->protinfo.af_ipx.node,
sk->protinfo.af_ipx.port) != NULL)
{
- if(sk->debug)
- printk("IPX: bind failed because port %X in"
- " use.\n", (int)addr->sipx_port);
+ SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", (int)addr->sipx_port);
return -EADDRINUSE;
}
}
@@ -1860,14 +1899,12 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
* with the ipx routing ioctl()
*/
- memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
+ memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
IPX_NODE_LEN);
-
+
if(ipxitf_find_socket(intrfc, addr->sipx_port)!=NULL) {
- if(sk->debug)
- printk("IPX: bind failed because port %X in"
- " use.\n", (int)addr->sipx_port);
- return -EADDRINUSE;
+ SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", (int)addr->sipx_port);
+ return -EADDRINUSE;
}
}
@@ -1877,40 +1914,37 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
an interface routed to IPX with the ipx routing ioctl() */
if(ipxitf_find_socket(intrfc, addr->sipx_port)!=NULL) {
- if(sk->debug)
- printk("IPX: bind failed because port %X in use.\n",
- (int)addr->sipx_port);
- return -EADDRINUSE;
+ SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", (int)addr->sipx_port);
+ return -EADDRINUSE;
}
#endif
ipxitf_insert_socket(intrfc, sk);
sk->zapped=0;
- if(sk->debug)
- printk("IPX: socket is bound.\n");
+ SOCK_DEBUG(sk, "IPX: socket is bound.\n");
return 0;
}
static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
- ipx_socket *sk=(ipx_socket *)sock->data;
+ struct sock *sk=sock->sk;
struct sockaddr_ipx *addr;
-
- sk->state = TCP_CLOSE;
+
+ sk->state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
if(addr_len!=sizeof(*addr))
return(-EINVAL);
addr=(struct sockaddr_ipx *)uaddr;
-
+
if(sk->protinfo.af_ipx.port==0)
/* put the autobinding in */
{
struct sockaddr_ipx uaddr;
int ret;
-
+
uaddr.sipx_port = 0;
uaddr.sipx_network = 0L;
#ifdef CONFIG_IPX_INTERN
@@ -1921,7 +1955,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
sizeof(struct sockaddr_ipx));
if (ret != 0) return (ret);
}
-
+
if(ipxrtr_lookup(addr->sipx_network)==NULL)
return -ENETUNREACH;
sk->protinfo.af_ipx.dest_addr.net=addr->sipx_network;
@@ -1941,8 +1975,8 @@ static int ipx_socketpair(struct socket *sock1, struct socket *sock2)
static int ipx_accept(struct socket *sock, struct socket *newsock, int flags)
{
- if(newsock->data) {
- kfree_s(newsock->data,sizeof(ipx_socket));
+ if(newsock->sk) {
+ sk_free(newsock->sk);
MOD_DEC_USE_COUNT;
}
return -EOPNOTSUPP;
@@ -1953,12 +1987,12 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
{
ipx_address *addr;
struct sockaddr_ipx sipx;
- ipx_socket *sk;
-
- sk=(ipx_socket *)sock->data;
-
+ struct sock *sk;
+
+ sk=sock->sk;
+
*uaddr_len = sizeof(struct sockaddr_ipx);
-
+
if(peer) {
if(sk->state!=TCP_ESTABLISHED)
return -ENOTCONN;
@@ -1972,7 +2006,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
#ifdef CONFIG_IPX_INTERN
memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
#else
- memcpy(sipx.sipx_node,
+ memcpy(sipx.sipx_node,
sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
#endif
@@ -1982,7 +2016,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
}
sipx.sipx_port = sk->protinfo.af_ipx.port;
}
-
+
sipx.sipx_family = AF_IPX;
sipx.sipx_type = sk->protinfo.af_ipx.type;
memcpy(uaddr,&sipx,sizeof(sipx));
@@ -1993,56 +2027,66 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
/*
* User to dump IPX packets (debugging)
*/
-void dump_data(char *str,unsigned char *d, int len) {
- static char h2c[] = "0123456789ABCDEF";
- int l,i;
- char *p, b[64];
- for (l=0;len > 0 && l<16;l++) {
- p = b;
- for (i=0; i < 8 ; i++, --len) {
- if (len > 0) {
- *(p++) = h2c[(d[i] >> 4) & 0x0f];
- *(p++) = h2c[d[i] & 0x0f];
- }
- else {
- *(p++) = ' ';
- *(p++) = ' ';
- }
- *(p++) = ' ';
- }
- *(p++) = '-';
- *(p++) = ' ';
- len += 8;
- for (i=0; i < 8 ; i++, --len)
- if (len > 0)
- *(p++) = ' '<= d[i] && d[i]<'\177' ? d[i] : '.';
- else
+void dump_data(char *str,unsigned char *d, int len)
+{
+ static char h2c[] = "0123456789ABCDEF";
+ int l,i;
+ char *p, b[64];
+ for (l=0;len > 0 && l<16;l++)
+ {
+ p = b;
+ for (i=0; i < 8 ; i++, --len)
+ {
+ if (len > 0)
+ {
+ *(p++) = h2c[(d[i] >> 4) & 0x0f];
+ *(p++) = h2c[d[i] & 0x0f];
+ }
+ else
+ {
+ *(p++) = ' ';
+ *(p++) = ' ';
+ }
*(p++) = ' ';
- *p = '\000';
- d += i;
- printk("%s-%04X: %s\n",str,l*8,b);
- }
+ }
+ *(p++) = '-';
+ *(p++) = ' ';
+ len += 8;
+ for (i=0; i < 8 ; i++, --len)
+ {
+ if (len > 0)
+ *(p++) = ' '<= d[i] && d[i]<'\177' ? d[i] : '.';
+ else
+ *(p++) = ' ';
+ }
+ *p = '\000';
+ d += i;
+ printk(KERN_DEBUG"%s-%04X: %s\n",str,l*8,b);
+ }
}
-void dump_addr(char *str,ipx_address *p) {
- printk("%s: %08X:%02X%02X%02X%02X%02X%02X:%04X\n",
- str,ntohl(p->net),p->node[0],p->node[1],p->node[2],
- p->node[3],p->node[4],p->node[5],ntohs(p->sock));
+void dump_addr(char *str,ipx_address *p)
+{
+ printk(KERN_DEBUG"%s: %08X:%02X%02X%02X%02X%02X%02X:%04X\n",
+ str,ntohl(p->net),p->node[0],p->node[1],p->node[2],
+ p->node[3],p->node[4],p->node[5],ntohs(p->sock));
}
-void dump_hdr(char *str,ipx_packet *p) {
- printk("%s: CHKSUM=%04X SIZE=%d (%04X) HOPS=%d (%02X) TYPE=%02X\n",
- str,p->ipx_checksum,ntohs(p->ipx_pktsize),ntohs(p->ipx_pktsize),
- p->ipx_tctrl,p->ipx_tctrl,p->ipx_type);
- dump_addr(" IPX-DST",&p->ipx_dest);
- dump_addr(" IPX-SRC",&p->ipx_source);
+void dump_hdr(char *str,struct ipxhdr *p)
+{
+ printk(KERN_DEBUG"%s: CHKSUM=%04X SIZE=%d (%04X) HOPS=%d (%02X) TYPE=%02X\n",
+ str,p->ipx_checksum,ntohs(p->ipx_pktsize),ntohs(p->ipx_pktsize),
+ p->ipx_tctrl,p->ipx_tctrl,p->ipx_type);
+ dump_addr(" IPX-DST",&p->ipx_dest);
+ dump_addr(" IPX-SRC",&p->ipx_source);
}
-void dump_pkt(char *str,ipx_packet *p) {
- int len = ntohs(p->ipx_pktsize);
- dump_hdr(str,p);
- if (len > 30)
- dump_data(str,(unsigned char *)p + 30, len - 30);
+void dump_pkt(char *str,struct ipxhdr *p)
+{
+ int len = ntohs(p->ipx_pktsize);
+ dump_hdr(str,p);
+ if (len > 30)
+ dump_data(str,(unsigned char *)p + 30, len - 30);
}
#endif
@@ -2050,14 +2094,12 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
{
/* NULL here for pt means the packet was looped back */
ipx_interface *intrfc;
- ipx_packet *ipx;
-
-
- ipx=(ipx_packet *)skb->h.raw;
-
- /* Too small */
+ struct ipxhdr *ipx;
+
+ ipx = skb->nh.ipxh;
- if(ntohs(ipx->ipx_pktsize)<sizeof(ipx_packet)) {
+ /* Too small? */
+ if(ntohs(ipx->ipx_pktsize)<sizeof(struct ipxhdr)) {
kfree_skb(skb,FREE_READ);
return 0;
}
@@ -2070,13 +2112,13 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
return 0;
}
}
-
+
/* Determine what local ipx endpoint this is */
intrfc = ipxitf_find_using_phys(dev, pt->type);
- if (intrfc == NULL)
+ if (intrfc == NULL)
{
if (ipxcfg_auto_create_interfaces &&
- ntohl(ipx->ipx_dest.net)!=0L)
+ ntohl(ipx->ipx_dest.net)!=0L)
{
intrfc = ipxitf_auto_create(dev, pt->type);
}
@@ -2091,28 +2133,29 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
return ipxitf_rcv(intrfc, skb);
}
-static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock,
- int flags)
+static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+ struct scm_cookie *scm)
{
- ipx_socket *sk=(ipx_socket *)sock->data;
+ struct sock *sk=sock->sk;
struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)msg->msg_name;
struct sockaddr_ipx local_sipx;
int retval;
+ int flags = msg->msg_flags;
- if (sk->zapped)
+ if (sk->zapped)
return -EIO; /* Socket not bound */
- if(flags)
+ if (flags&~MSG_DONTWAIT)
return -EINVAL;
-
- if(usipx)
+
+ if(usipx)
{
- if(sk->protinfo.af_ipx.port == 0)
+ if(sk->protinfo.af_ipx.port == 0)
{
struct sockaddr_ipx uaddr;
int ret;
uaddr.sipx_port = 0;
- uaddr.sipx_network = 0L;
+ uaddr.sipx_network = 0L;
#ifdef CONFIG_IPX_INTERN
memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc
->if_node, IPX_NODE_LEN);
@@ -2127,7 +2170,7 @@ static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nob
if(usipx->sipx_family != AF_IPX)
return -EINVAL;
}
- else
+ else
{
if(sk->state!=TCP_ESTABLISHED)
return -ENOTCONN;
@@ -2138,39 +2181,35 @@ static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nob
usipx->sipx_network=sk->protinfo.af_ipx.dest_addr.net;
memcpy(usipx->sipx_node,sk->protinfo.af_ipx.dest_addr.node,IPX_NODE_LEN);
}
-
- retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, noblock);
- if (retval < 0)
+
+ retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, flags&MSG_DONTWAIT);
+ if (retval < 0)
return retval;
return len;
}
-static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock,
- int flags, int *addr_len)
+static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ int flags, struct scm_cookie *scm)
{
- ipx_socket *sk=(ipx_socket *)sock->data;
+ struct sock *sk=sock->sk;
struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)msg->msg_name;
- struct ipx_packet *ipx = NULL;
+ struct ipxhdr *ipx = NULL;
int copied = 0;
int truesize;
struct sk_buff *skb;
int err;
-
+
if (sk->zapped)
return -ENOTCONN;
-
- skb=skb_recv_datagram(sk,flags,noblock,&err);
+ skb=skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
if(skb==NULL)
return err;
-
- if(addr_len)
- *addr_len=sizeof(*sipx);
- ipx = (ipx_packet *)(skb->h.raw);
- truesize=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
+ ipx = skb->nh.ipxh;
+ truesize=ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
copied = truesize;
if(copied > size)
@@ -2178,12 +2217,14 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int no
copied=size;
msg->msg_flags|=MSG_TRUNC;
}
-
- err = skb_copy_datagram_iovec(skb,sizeof(struct ipx_packet),msg->msg_iov,copied);
+
+ err = skb_copy_datagram_iovec(skb,sizeof(struct ipxhdr),msg->msg_iov,copied);
if (err)
return err;
+ msg->msg_namelen = sizeof(*sipx);
+
if(sipx)
{
sipx->sipx_family=AF_IPX;
@@ -2193,30 +2234,28 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int no
sipx->sipx_type = ipx->ipx_type;
}
skb_free_datagram(sk, skb);
+
return(copied);
-}
+}
+/*
+ * FIXME: We have to support shutdown really.
+ */
+
static int ipx_shutdown(struct socket *sk,int how)
{
return -EOPNOTSUPP;
}
-static int ipx_select(struct socket *sock , int sel_type, select_table *wait)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
-
- return datagram_select(sk,sel_type,wait);
-}
-
static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
{
long amount=0;
- ipx_socket *sk=(ipx_socket *)sock->data;
-
+ struct sock *sk=sock->sk;
+
switch(cmd)
{
case TIOCOUTQ:
- amount=sk->sndbuf-sk->wmem_alloc;
+ amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if(amount<0)
amount=0;
return put_user(amount, (int *)arg);
@@ -2225,7 +2264,7 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
struct sk_buff *skb;
/* These two are safe on a single CPU system as only user tasks fiddle here */
if((skb=skb_peek(&sk->receive_queue))!=NULL)
- amount=skb->len-sizeof(struct ipx_packet);
+ amount=skb->len-sizeof(struct ipxhdr);
return put_user(amount, (int *)arg);
}
case SIOCADDRT:
@@ -2240,7 +2279,7 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
return -EPERM;
case SIOCGIFADDR:
return(ipxitf_ioctl(cmd,(void *)arg));
- case SIOCIPXCFGDATA:
+ case SIOCIPXCFGDATA:
{
return(ipxcfg_get_config_data((void *)arg));
}
@@ -2271,10 +2310,14 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
return(0);
}
-static struct proto_ops ipx_proto_ops = {
+static struct net_proto_family ipx_family_ops = {
AF_IPX,
-
- ipx_create,
+ ipx_create
+};
+
+static struct proto_ops ipx_dgram_ops = {
+ AF_IPX,
+
ipx_dup,
ipx_release,
ipx_bind,
@@ -2282,20 +2325,20 @@ static struct proto_ops ipx_proto_ops = {
ipx_socketpair,
ipx_accept,
ipx_getname,
- ipx_select,
+ datagram_poll,
ipx_ioctl,
- ipx_listen,
+ sock_no_listen,
ipx_shutdown,
ipx_setsockopt,
ipx_getsockopt,
- ipx_fcntl,
+ sock_no_fcntl,
ipx_sendmsg,
ipx_recvmsg
};
/* Called by protocol.c on kernel start up */
-static struct packet_type ipx_8023_packet_type =
+static struct packet_type ipx_8023_packet_type =
{
0, /* MUTTER ntohs(ETH_P_8023),*/
@@ -2305,7 +2348,7 @@ static struct packet_type ipx_8023_packet_type =
NULL,
};
-static struct packet_type ipx_dix_packet_type =
+static struct packet_type ipx_dix_packet_type =
{
0, /* MUTTER ntohs(ETH_P_IPX),*/
NULL, /* All devices */
@@ -2347,7 +2390,7 @@ static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
void
ipx_proto_init(struct net_proto *pro)
{
- (void) sock_register(ipx_proto_ops.family, &ipx_proto_ops);
+ (void) sock_register(&ipx_family_ops);
pEII_datalink = make_EII_client();
ipx_dix_packet_type.type=htons(ETH_P_IPX);
@@ -2356,24 +2399,24 @@ ipx_proto_init(struct net_proto *pro)
p8023_datalink = make_8023_client();
ipx_8023_packet_type.type=htons(ETH_P_802_3);
dev_add_pack(&ipx_8023_packet_type);
-
+
if ((p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv)) == NULL)
printk(KERN_CRIT "IPX: Unable to register with 802.2\n");
if ((p8022tr_datalink = register_8022tr_client(ipx_8022_type, ipx_rcv)) == NULL)
printk(KERN_CRIT "IPX: Unable to register with 802.2TR\n");
-
+
if ((pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv)) == NULL)
printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
-
+
register_netdevice_notifier(&ipx_dev_notifier);
#ifdef CONFIG_PROC_FS
proc_net_register(&ipx_procinfo);
proc_net_register(&ipx_if_procinfo);
proc_net_register(&ipx_rt_procinfo);
-#endif
-
- printk(KERN_INFO "Swansea University Computer Society IPX 0.35 for NET3.037\n");
+#endif
+
+ printk(KERN_INFO "Swansea University Computer Society IPX 0.38 for NET3.037\n");
printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
}
@@ -2382,17 +2425,16 @@ ipx_proto_init(struct net_proto *pro)
*
* Use counts are incremented/decremented when
* sockets are created/deleted.
- *
+ *
* Routes are always associated with an interface, and
* allocs/frees will remain properly accounted for by
* their associated interfaces.
- *
+ *
* Ergo, before the ipx module can be removed, all IPX
- * sockets be closed from user space.
+ * sockets be closed from user space.
*/
-static void
-ipx_proto_finito(void)
+static void ipx_proto_finito(void)
{ ipx_interface *ifc;
while (ipx_interfaces) {
@@ -2406,7 +2448,7 @@ ipx_proto_finito(void)
proc_net_unregister(PROC_NET_IPX_ROUTE);
proc_net_unregister(PROC_NET_IPX_INTERFACE);
proc_net_unregister(PROC_NET_IPX);
-#endif
+#endif
unregister_netdevice_notifier(&ipx_dev_notifier);
@@ -2427,15 +2469,16 @@ ipx_proto_finito(void)
destroy_EII_client(pEII_datalink);
pEII_datalink = NULL;
- (void) sock_unregister(ipx_proto_ops.family);
+ (void) sock_unregister(ipx_family_ops.family);
return;
}
+EXPORT_NO_SYMBOLS;
+
int init_module(void)
{
ipx_proto_init(NULL);
- register_symtab(0);
return 0;
}