patch-1.3.60 linux/net/ipx/af_ipx.c
Next file: linux/net/netlink.c
Previous file: linux/net/ipv4/udp.c
Back to the patch index
Back to the overall index
- Lines: 363
- Date:
Wed Feb 7 08:55:56 1996
- Orig file:
v1.3.59/linux/net/ipx/af_ipx.c
- Orig date:
Thu Jan 4 21:54:59 1996
diff -u --recursive --new-file v1.3.59/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
@@ -258,6 +258,27 @@
return s;
}
+#ifdef CONFIG_IPX_INTERN
+
+static ipx_socket *
+ipxitf_find_internal_socket(ipx_interface *intrfc,
+ unsigned char *node, unsigned short port)
+{
+ ipx_socket *s = intrfc->if_sklist;
+
+ while (s != NULL)
+ {
+ if ( (s->ipx_port == port)
+ && (memcmp(node, s->ipx_node, IPX_NODE_LEN) == 0))
+ {
+ break;
+ }
+ s = s->next;
+ }
+ return s;
+}
+#endif
+
static void ipxrtr_del_routes(ipx_interface *);
static void
@@ -331,12 +352,8 @@
if((retval = sock_queue_rcv_skb(sock, skb))<0)
{
/*
- * We do a FREE_WRITE here because this indicates how
- * 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
- * packet. Incoming packets will have no socket
- * associated with them at this point.
+ * skb->sk is NULL here, so FREE_WRITE does not hurt
+ * the sending socket.
*/
kfree_skb(skb,FREE_WRITE);
}
@@ -344,12 +361,76 @@
}
/*
- * On input if skb->sk is set the buffer is a socket sending. We need to ensure the
- * accounting is kept right in these cases. At the moment the socket write queue is
- * charged for the memory.
+ * On input skb->sk is NULL. Nobody is charged for the memory.
*/
-
-static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+
+#ifdef CONFIG_IPX_INTERN
+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;
+
+ int is_broadcast = (memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
+ IPX_NODE_LEN) == 0);
+
+ s = intrfc->if_sklist;
+
+ while (s != NULL)
+ {
+ if ( (s->ipx_port == ipx->ipx_dest.sock)
+ && ( is_broadcast
+ || (memcmp(ipx->ipx_dest.node, s->ipx_node,
+ IPX_NODE_LEN) == 0)))
+ {
+ /* We found a socket to which to send */
+ struct sk_buff *skb1;
+
+ if (copy != 0)
+ {
+ skb1 = skb_clone(skb, GFP_ATOMIC);
+ if (skb1 != NULL)
+ {
+ skb1->arp = skb1->free = 1;
+ }
+ else
+ {
+ return -ENOMEM;
+ }
+ }
+ else
+ {
+ skb1 = skb;
+ copy = 1; /* skb may only be used once */
+ }
+ ipxitf_def_skb_handler(s, skb1);
+
+ if (intrfc != ipx_internal_net)
+ {
+ /* on an external interface, at most
+ * one socket can listen.
+ */
+ break;
+ }
+ }
+ s = s->next;
+ }
+
+ if (copy == 0)
+ {
+ /* skb was solely for us, and we did not make a copy,
+ * so free it. FREE_WRITE does not hurt, because
+ * skb->sk is NULL here.
+ */
+ kfree_skb(skb, FREE_WRITE);
+ }
+ return 0;
+}
+
+#else
+
+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;
@@ -444,6 +525,7 @@
return 0;
}
+#endif
static struct sk_buff *
ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
@@ -508,7 +590,10 @@
* Don't charge sender
*/
if(skb->sk)
+ {
skb->sk->wmem_alloc-=skb->truesize;
+ skb->sk=NULL;
+ }
/*
* Will charge receiver
*/
@@ -520,7 +605,10 @@
if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
{
if (!send_to_wire && skb->sk)
+ {
skb->sk->wmem_alloc-=skb->truesize;
+ skb->sk=NULL;
+ }
ipxitf_demux_socket(intrfc, skb, send_to_wire);
if (!send_to_wire)
return 0;
@@ -995,6 +1083,8 @@
rt->ir_next=ipx_routes;
ipx_routes=rt;
}
+ else if (intrfc == ipx_internal_net)
+ return(-EINVAL);
rt->ir_net = network;
rt->ir_intrfc = intrfc;
@@ -1110,7 +1200,21 @@
skb->h.raw = (unsigned char *)ipx;
ipx->ipx_source.net = sk->ipx_intrfc->if_netnum;
- memcpy(ipx->ipx_source.node, sk->ipx_intrfc->if_node, IPX_NODE_LEN);
+#ifdef CONFIG_IPX_INTERN
+ memcpy(ipx->ipx_source.node, sk->ipx_node, IPX_NODE_LEN);
+#else
+ if ((err = ntohs(sk->ipx_port)) == 0x453 || err == 0x452)
+ {
+ /* RIP/SAP special handling for mars_nwe */
+ ipx->ipx_source.net = intrfc->if_netnum;
+ memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
+ }
+ else
+ {
+ ipx->ipx_source.net = sk->ipx_intrfc->if_netnum;
+ memcpy(ipx->ipx_source.node, sk->ipx_intrfc->if_node, IPX_NODE_LEN);
+ }
+#endif
ipx->ipx_source.sock = sk->ipx_port;
ipx->ipx_dest.net=usipx->sipx_network;
memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
@@ -1221,7 +1325,7 @@
off_t begin=0;
/* Theory.. Keep printing in the same place until we pass offset */
-
+
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) {
@@ -1265,15 +1369,29 @@
off_t begin=0;
/* 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",
+#else
len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+#endif
"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) {
- len += sprintf (buffer+len,"%08lX:%04X ",
- htonl(i->if_netnum),
- htons(s->ipx_port));
+#ifdef CONFIG_IPX_INTERN
+ len += sprintf(buffer+len,
+ "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
+ htonl(s->ipx_intrfc->if_netnum),
+ s->ipx_node[0], s->ipx_node[1],
+ s->ipx_node[2], s->ipx_node[3],
+ s->ipx_node[4], s->ipx_node[5],
+ htons(s->ipx_port));
+#else
+ len += sprintf(buffer+len,"%08lX:%04X ",
+ htonl(i->if_netnum),
+ htons(s->ipx_port));
+#endif
if (s->state!=TCP_ESTABLISHED) {
len += sprintf(buffer+len, "%-28s", "Not_Connected");
} else {
@@ -1436,6 +1554,7 @@
return err;
put_fs_long(sizeof(int),(unsigned long *)optlen);
err=verify_area(VERIFY_WRITE,optval,sizeof(int));
+ if (err) return err;
put_fs_long(val,(unsigned long *)optval);
return(0);
}
@@ -1577,7 +1696,59 @@
if(ntohs(addr->sipx_port)<IPX_MIN_EPHEMERAL_SOCKET && !suser())
return -EPERM; /* protect IPX system stuff like routing/sap */
-
+
+ sk->ipx_port=addr->sipx_port;
+
+#ifdef CONFIG_IPX_INTERN
+ if (intrfc == ipx_internal_net)
+ {
+ /* The source address is to be set explicitly if the
+ * socket is to be bound on the internal network. If a
+ * node number 0 was specified, the default is used.
+ */
+
+ if (memcmp(addr->sipx_node, ipx_broadcast_node,
+ IPX_NODE_LEN) == 0)
+ {
+ return -EINVAL;
+ }
+ if (memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN) == 0)
+ {
+ memcpy(sk->ipx_node, intrfc->if_node,
+ IPX_NODE_LEN);
+ }
+ else
+ {
+ memcpy(sk->ipx_node, addr->sipx_node, IPX_NODE_LEN);
+ }
+ if (ipxitf_find_internal_socket(intrfc, sk->ipx_node,
+ sk->ipx_port) != NULL)
+ {
+ if(sk->debug)
+ printk("IPX: bind failed because port %X in"
+ " use.\n", (int)addr->sipx_port);
+ return -EADDRINUSE;
+ }
+ }
+ else
+ {
+ /* Source addresses are easy. It must be our
+ * network:node pair for an interface routed to IPX
+ * with the ipx routing ioctl()
+ */
+
+ memcpy(sk->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;
+ }
+ }
+
+#else
+
/* Source addresses are easy. It must be our network:node pair for
an interface routed to IPX with the ipx routing ioctl() */
@@ -1588,7 +1759,8 @@
return -EADDRINUSE;
}
- sk->ipx_port=addr->sipx_port;
+#endif
+
ipxitf_insert_socket(intrfc, sk);
sk->zapped=0;
if(sk->debug)
@@ -1616,8 +1788,13 @@
int ret;
uaddr.sipx_port = 0;
- uaddr.sipx_network = 0L;
- ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
+ uaddr.sipx_network = 0L;
+#ifdef CONFIG_IPX_INTERN
+ memcpy(uaddr.sipx_node, sk->ipx_intrfc->if_node,
+ IPX_NODE_LEN);
+#endif
+ ret = ipx_bind (sock, (struct sockaddr *)&uaddr,
+ sizeof(struct sockaddr_ipx));
if (ret != 0) return (ret);
}
@@ -1665,8 +1842,13 @@
} else {
if (sk->ipx_intrfc != NULL) {
sipx.sipx_network = sk->ipx_intrfc->if_netnum;
+#ifdef CONFIG_IPX_INTERN
+ memcpy(sipx.sipx_node, sk->ipx_node, IPX_NODE_LEN);
+#else
memcpy(sipx.sipx_node, sk->ipx_intrfc->if_node,
- IPX_NODE_LEN);
+ IPX_NODE_LEN);
+#endif
+
} else {
sipx.sipx_network = 0L;
memset(sipx.sipx_node, '\0', IPX_NODE_LEN);
@@ -1797,7 +1979,12 @@
uaddr.sipx_port = 0;
uaddr.sipx_network = 0L;
- ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
+#ifdef CONFIG_IPX_INTERN
+ memcpy(uaddr.sipx_node, sk->ipx_intrfc->if_node,
+ IPX_NODE_LEN);
+#endif
+ ret = ipx_bind (sock, (struct sockaddr *)&uaddr,
+ sizeof(struct sockaddr_ipx));
if (ret != 0) return ret;
}
@@ -1901,7 +2088,7 @@
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;
+ amount=skb->len-sizeof(struct ipx_packet);
err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
if(err)
return err;
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