diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /net/ipx/af_ipx.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/ipx/af_ipx.c')
-rw-r--r-- | net/ipx/af_ipx.c | 1167 |
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; } |