patch-1.3.82 linux/net/ipx/af_ipx.c
Next file: linux/net/ipx/sysctl_net_ipx.c
Previous file: linux/net/ipx/Makefile
Back to the patch index
Back to the overall index
- Lines: 255
- Date:
Tue Apr 2 08:43:07 1996
- Orig file:
v1.3.81/linux/net/ipx/af_ipx.c
- Orig date:
Sun Mar 31 00:13:19 1996
diff -u --recursive --new-file v1.3.81/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
@@ -42,6 +42,7 @@
* Revision 0.33: Internal network support, routing changes, uses a
* protocol private area for ipx data.
* Revision 0.34: Module support. <Jim Freeman>
+ * Revision 0.35: Checksum support. <Neil Turton>, hooked in by <Alan Cox>
*
* Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
* Neither Greg Page nor Caldera, Inc. admit liability nor provide
@@ -193,7 +194,7 @@
kfree_skb(skb,FREE_READ);
}
- kfree_s(sk,sizeof(*sk));
+ sk_free(sk);
MOD_DEC_USE_COUNT;
}
@@ -907,8 +908,8 @@
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);
if (intrfc==NULL)
@@ -924,9 +925,14 @@
ipx_primary_net = intrfc;
intrfc->if_internal = 0;
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]), dev->dev_addr, dev->addr_len);
-
+ 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]),
+ dev->dev_addr, dev->addr_len);
+ }
+ else
+ memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
ipxitf_insert(intrfc);
}
@@ -1172,6 +1178,65 @@
}
/*
+ * Checksum routine for IPX
+ */
+
+/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
+
+static __u16 ipx_set_checksum(ipx_packet *packet,int length)
+{
+ /*
+ * NOTE: sum is a net byte order quantity, which optimizes the
+ * loop. This only works on big and little endian machines. (I
+ * don't know of a machine that isn't.)
+ */
+
+ __u32 sum=0;
+
+ /*
+ * Pointer to second word - We skip the checksum field
+ */
+
+ __u16 *p=(__u16 *)&packet->ipx_pktsize;
+
+ /*
+ * Number of complete words
+ */
+
+ __u32 i=length>>1;
+
+ /*
+ * Loop through all complete words except the checksum field
+ */
+
+ while(--i)
+ sum+=*p++;
+
+ /*
+ * Add on the last part word if it exists
+ */
+
+ if(packet->ipx_pktsize&htons(1))
+ sum+=ntohs(0xff00)&*p;
+
+ /*
+ * Do final fixup
+ */
+
+ sum=(sum&0xffff)+(sum>>16);
+
+ /*
+ * It's a pitty there's no concept of carry in C
+ */
+
+ if(sum>=0x10000)
+ sum++;
+
+ return ~sum;
+};
+
+
+/*
* Route an outgoing frame from a socket.
*/
@@ -1215,7 +1280,6 @@
/* Fill in IPX header */
ipx=(ipx_packet *)skb_put(skb,sizeof(ipx_packet));
- ipx->ipx_checksum=0xFFFF;
ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
ipx->ipx_tctrl=0;
ipx->ipx_type=usipx->sipx_type;
@@ -1244,6 +1308,15 @@
memcpy_fromiovec(skb_put(skb,len),iov,len);
+ /*
+ * Apply checksum. Not allowed on 802.3 links.
+ */
+
+ 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));
+
#ifdef CONFIG_FIREWALL
if(call_out_firewall(PF_IPX, skb, ipx)!=FW_ACCEPT)
{
@@ -1608,11 +1681,10 @@
}
}
-static int
-ipx_create(struct socket *sock, int protocol)
+static int ipx_create(struct socket *sock, int protocol)
{
ipx_socket *sk;
- sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
+ sk=(ipx_socket *)sk_alloc(GFP_KERNEL);
if(sk==NULL)
return(-ENOMEM);
switch(sock->type)
@@ -1623,17 +1695,9 @@
kfree_s((void *)sk,sizeof(*sk));
return(-ESOCKTNOSUPPORT);
}
- sk->dead=0;
- sk->next=NULL;
- sk->broadcast=0;
sk->rcvbuf=SK_RMEM_MAX;
sk->sndbuf=SK_WMEM_MAX;
- sk->wmem_alloc=0;
- sk->rmem_alloc=0;
- sk->users=0;
- sk->shutdown=0;
sk->prot=NULL; /* So we use default free mechanisms */
- sk->err=0;
skb_queue_head_init(&sk->receive_queue);
skb_queue_head_init(&sk->write_queue);
sk->send_head=NULL;
@@ -1641,15 +1705,8 @@
sk->state=TCP_CLOSE;
sk->socket=sock;
sk->type=sock->type;
- sk->protinfo.af_ipx.type=0; /* General user level IPX */
- sk->debug=0;
- sk->protinfo.af_ipx.intrfc = NULL;
- memset(&sk->protinfo.af_ipx.dest_addr,'\0',
- sizeof(sk->protinfo.af_ipx.dest_addr));
- sk->protinfo.af_ipx.port = 0;
- sk->protinfo.af_ipx.ncp_server = 0;
sk->mtu=IPX_MTU;
-
+ sk->no_check = 1; /* Checksum off by default */
if(sock!=NULL)
{
sock->data=(void *)sk;
@@ -1965,23 +2022,26 @@
ipx=(ipx_packet *)skb->h.raw;
- if(ipx->ipx_checksum!=IPX_NO_CHECKSUM) {
- /* We don't do checksum options. We can't really. Novell don't seem to have documented them.
- If you need them try the XNS checksum since IPX is basically XNS in disguise. It might be
- the same... */
+ /* Too small */
+
+ if(ntohs(ipx->ipx_pktsize)<sizeof(ipx_packet)) {
kfree_skb(skb,FREE_READ);
return 0;
}
- /* Too small */
- if(htons(ipx->ipx_pktsize)<sizeof(ipx_packet)) {
- kfree_skb(skb,FREE_READ);
- return 0;
+ if(ipx->ipx_checksum!=IPX_NO_CHECKSUM)
+ {
+ if(ipx_set_checksum(ipx, ntohs(ipx->ipx_pktsize))!=ipx->ipx_checksum)
+ {
+ kfree_skb(skb,FREE_READ);
+ 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) {
intrfc = ipxitf_auto_create(dev, pt->type);
}
@@ -2004,8 +2064,10 @@
struct sockaddr_ipx local_sipx;
int retval;
- if (sk->zapped) return -EIO; /* Socket not bound */
- if(flags) return -EINVAL;
+ if (sk->zapped)
+ return -EIO; /* Socket not bound */
+ if(flags)
+ return -EINVAL;
if(usipx)
{
@@ -2043,7 +2105,8 @@
}
retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len);
- if (retval < 0) return retval;
+ if (retval < 0)
+ return retval;
return len;
}
@@ -2278,8 +2341,8 @@
proc_net_register(&ipx_if_procinfo);
proc_net_register(&ipx_rt_procinfo);
- printk("Swansea University Computer Society IPX 0.34 for NET3.034\n");
- printk("IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
+ printk(KERN_INFO "Swansea University Computer Society IPX 0.34 for NET3.034\n");
+ printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
}
#ifdef MODULE
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this