patch-1.3.36 linux/net/ipx/af_ipx.c
Next file: linux/net/netrom/af_netrom.c
Previous file: linux/net/ipv4/udp.c
Back to the patch index
Back to the overall index
- Lines: 300
- Date:
Tue Oct 17 13:42:37 1995
- Orig file:
v1.3.35/linux/net/ipx/af_ipx.c
- Orig date:
Wed Sep 13 12:45:35 1995
diff -u --recursive --new-file v1.3.35/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
@@ -37,8 +37,8 @@
* Don't set address length on recvfrom that errors.
* Incorrect verify_area.
* Revision 0.31: New sk_buffs. This still needs a lot of testing. <Alan Cox>
- *
- * TODO: use sock_alloc_send_skb to allocate sending buffers. Check with Caldera first
+ * Revision 0.32: Using sock_alloc_send_skb, firewall hooks. <Alan Cox>
+ * Supports sendmsg/recvmsg
*
* Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
* Neither Greg Page nor Caldera, Inc. admit liability nor provide
@@ -73,12 +73,13 @@
#include <net/psnap.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/firewall.h>
#ifdef CONFIG_IPX
/* Configuration Variables */
static unsigned char ipxcfg_max_hops = 16;
-static char ipxcfg_auto_select_primary = 0;
-static char ipxcfg_auto_create_interfaces = 0;
+static char ipxcfg_auto_select_primary = 0;
+static char ipxcfg_auto_create_interfaces = 0;
/* Global Variables */
static struct datalink_proto *p8022_datalink = NULL;
@@ -560,24 +561,40 @@
static const char * ipx_device_name(ipx_interface *);
static int ipxrtr_route_skb(struct sk_buff *);
-static int
-ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
+static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
ipx_packet *ipx = (ipx_packet *) (skb->h.raw);
ipx_interface *i;
+#ifdef CONFIG_FIREWALL
+ /*
+ * We firewall first, ask questions later.
+ */
+
+ if (call_in_firewall(PF_IPX, skb, ipx)!=FW_ACCEPT)
+ {
+ kfree_skb(skb, FREE_READ);
+ return 0;
+ }
+
+#endif
+
/* See if we should update our network number */
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("IPX: Network number collision %lx\n\t%s %s and %s %s\n",
htonl(ipx->ipx_source.net),
ipx_device_name(i),
@@ -592,7 +609,18 @@
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, ipx)!=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))
@@ -604,7 +632,8 @@
/* 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)) {
+ || (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
+ {
return ipxitf_demux_socket(intrfc, skb, 0);
}
@@ -988,8 +1017,11 @@
return -ENOENT;
}
-static int
-ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, const void *ubuf, int len)
+/*
+ * Route an outgoing frame from a socket.
+ */
+
+static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len)
{
struct sk_buff *skb;
ipx_interface *intrfc;
@@ -997,12 +1029,16 @@
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) {
return -ENETUNREACH;
@@ -1014,12 +1050,10 @@
size=sizeof(ipx_packet)+len;
size += ipx_offset;
- if(size+sk->wmem_alloc>sk->sndbuf) return -EAGAIN;
-
- skb=alloc_skb(size,GFP_KERNEL);
- if(skb==NULL) return -ENOMEM;
+ skb=sock_alloc_send_skb(sk, size, 0, 0, &err);
+ if(skb==NULL)
+ return err;
- skb->sk=sk;
skb_reserve(skb,ipx_offset);
skb->free=1;
skb->arp=1;
@@ -1039,7 +1073,16 @@
memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
ipx->ipx_dest.sock=usipx->sipx_port;
- memcpy_fromfs(skb_put(skb,len),ubuf,len);
+ memcpy_fromiovec(skb_put(skb,len),iov,len);
+
+#ifdef CONFIG_FIREWALL
+ if(call_out_firewall(PF_IPX, skb, ipx)!=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);
}
@@ -1691,11 +1734,11 @@
return ipxitf_rcv(intrfc, skb);
}
-static int ipx_sendto(struct socket *sock, const void *ubuf, int len, int noblock,
- unsigned flags, struct sockaddr *usip, int addr_len)
+static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock,
+ int flags)
{
ipx_socket *sk=(ipx_socket *)sock->data;
- struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)usip;
+ struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)msg->msg_name;
struct sockaddr_ipx local_sipx;
int retval;
@@ -1713,7 +1756,7 @@
if (ret != 0) return ret;
}
- if(addr_len <sizeof(*usipx))
+ if(msg->msg_namelen <sizeof(*usipx))
return -EINVAL;
if(usipx->sipx_family != AF_IPX)
return -EINVAL;
@@ -1728,22 +1771,40 @@
memcpy(usipx->sipx_node,sk->ipx_dest_addr.node,IPX_NODE_LEN);
}
- retval = ipxrtr_route_packet(sk, usipx, ubuf, len);
+ retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len);
if (retval < 0) return retval;
return len;
}
+static int ipx_sendto(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags,
+ struct sockaddr *sa, int addr_len)
+{
+ struct iovec iov;
+ struct msghdr msg;
+
+ iov.iov_base = (void *)ubuf;
+ iov.iov_len = size;
+
+ msg.msg_name = (void *)sa;
+ msg.msg_namelen = addr_len;
+ msg.msg_accrights = NULL;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ return ipx_sendmsg(sock, &msg, size, noblock, flags);
+}
+
static int ipx_send(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags)
{
return ipx_sendto(sock,ubuf,size,noblock,flags,NULL,0);
}
-static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags, struct sockaddr *sip, int *addr_len)
+static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock,
+ int flags, int *addr_len)
{
ipx_socket *sk=(ipx_socket *)sock->data;
- struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)sip;
+ struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)msg->msg_name;
struct ipx_packet *ipx = NULL;
int copied = 0;
int truesize;
@@ -1764,13 +1825,14 @@
skb=skb_recv_datagram(sk,flags,noblock,&er);
if(skb==NULL)
return er;
+
if(addr_len)
*addr_len=sizeof(*sipx);
ipx = (ipx_packet *)(skb->h.raw);
truesize=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
copied = (truesize > size) ? size : truesize;
- skb_copy_datagram(skb,sizeof(struct ipx_packet),ubuf,copied);
+ skb_copy_datagram_iovec(skb,sizeof(struct ipx_packet),msg->msg_iov,copied);
if(sipx)
{
@@ -1789,6 +1851,25 @@
return ipx_send(sock,ubuf,size,noblock,0);
}
+static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags,
+ struct sockaddr *sa, int *addr_len)
+{
+ struct iovec iov;
+ struct msghdr msg;
+
+ iov.iov_base = ubuf;
+ iov.iov_len = size;
+
+ msg.msg_name = (void *)sa;
+ msg.msg_namelen = 0;
+ if (addr_len)
+ msg.msg_namelen = *addr_len;
+ msg.msg_accrights = NULL;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ return ipx_recvmsg(sock, &msg, size, noblock, flags, addr_len);
+}
static int ipx_recv(struct socket *sock, void *ubuf, int size , int noblock,
unsigned flags)
@@ -1915,6 +1996,8 @@
ipx_setsockopt,
ipx_getsockopt,
ipx_fcntl,
+ ipx_sendmsg,
+ ipx_recvmsg
};
/* Called by ddi.c on kernel start up */
@@ -1990,7 +2073,7 @@
ipx_rt_get_info
});
- printk("Swansea University Computer Society IPX 0.31 for NET3.031\n");
+ printk("Swansea University Computer Society IPX 0.33 for NET3.032\n");
printk("IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
}
#endif
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