summaryrefslogtreecommitdiff
path: root/libmachdev
diff options
context:
space:
mode:
Diffstat (limited to 'libmachdev')
-rw-r--r--libmachdev/Makefile2
-rw-r--r--libmachdev/if_hdr.h165
-rw-r--r--libmachdev/mach_glue.h7
-rw-r--r--libmachdev/net.c118
4 files changed, 240 insertions, 52 deletions
diff --git a/libmachdev/Makefile b/libmachdev/Makefile
index 22909949..224dfddb 100644
--- a/libmachdev/Makefile
+++ b/libmachdev/Makefile
@@ -30,7 +30,7 @@ OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
include ../Makeconf
-CFLAGS += -I$(top_srcdir)/libddekit/include
+CFLAGS += -I$(top_srcdir)/libddekit/include -I$(top_srcdir)/libbpf
ourdevice.defs: device.defs
$(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@
diff --git a/libmachdev/if_hdr.h b/libmachdev/if_hdr.h
new file mode 100644
index 00000000..74d0fa8a
--- /dev/null
+++ b/libmachdev/if_hdr.h
@@ -0,0 +1,165 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Taken from (bsd)net/if.h. Modified for MACH kernel.
+ */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. The name of the Laboratory may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if.h 7.3 (Berkeley) 6/27/88
+ */
+
+#ifndef _IF_HDR_
+#define _IF_HDR_
+
+#include <queue.h>
+#include <cthreads.h>
+#include <bpf_impl.h>
+
+#if 0
+/*
+ * Queue for network output and filter input.
+ */
+struct ifqueue {
+ queue_head_t ifq_head; /* queue of io_req_t */
+ int ifq_len; /* length of queue */
+ int ifq_maxlen; /* maximum length of queue */
+ int ifq_drops; /* number of packets dropped
+ because queue full */
+ decl_simple_lock_data(,
+ ifq_lock) /* lock for queue and counters */
+};
+#endif
+
+/*
+ * Header for network interface drivers.
+ */
+struct ifnet {
+ short if_unit; /* unit number */
+ short if_flags; /* up/down, broadcast, etc. */
+ short if_timer; /* time until if_watchdog called */
+ short if_mtu; /* maximum transmission unit */
+ short if_header_size; /* length of header */
+ short if_header_format; /* format of hardware header */
+ short if_address_size; /* length of hardware address */
+ short if_alloc_size; /* size of read buffer to allocate */
+ char *if_address; /* pointer to hardware address */
+// struct ifqueue if_snd; /* output queue */
+ if_filter_list_t port_list;
+ struct mutex if_rcv_port_list_lock;/* lock for input filter list */
+ struct mutex if_snd_port_list_lock;/* lock for output filter list */
+/* statistics */
+ int if_ipackets; /* packets received */
+ int if_ierrors; /* input errors */
+ int if_opackets; /* packets sent */
+ int if_oerrors; /* output errors */
+ int if_collisions; /* collisions on csma interfaces */
+ int if_rcvdrops; /* packets received but dropped */
+};
+
+#define IFF_UP 0x0001 /* interface is up */
+#define IFF_BROADCAST 0x0002 /* interface can broadcast */
+#define IFF_DEBUG 0x0004 /* turn on debugging */
+#define IFF_LOOPBACK 0x0008 /* is a loopback net */
+#define IFF_POINTOPOINT 0x0010 /* point-to-point link */
+#define IFF_RUNNING 0x0040 /* resources allocated */
+#define IFF_NOARP 0x0080 /* no address resolution protocol */
+#define IFF_PROMISC 0x0100 /* receive all packets */
+#define IFF_ALLMULTI 0x0200 /* receive all multicast packets */
+#define IFF_BRIDGE 0x0100 /* support token ring routing field */
+#define IFF_SNAP 0x0200 /* support extended sap header */
+
+/* internal flags only: */
+#define IFF_CANTCHANGE (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING)
+
+/*
+ * Output queues (ifp->if_snd)
+ * have queues of messages stored on ifqueue structures. Entries
+ * are added to and deleted from these structures by these macros, which
+ * should be called with ipl raised to splimp().
+ * XXX locking XXX
+ */
+
+#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
+#define IF_DROP(ifq) ((ifq)->ifq_drops++)
+#define IF_ENQUEUE(ifq, ior) { \
+ simple_lock(&(ifq)->ifq_lock); \
+ enqueue_tail(&(ifq)->ifq_head, (queue_entry_t)ior); \
+ (ifq)->ifq_len++; \
+ simple_unlock(&(ifq)->ifq_lock); \
+}
+#define IF_PREPEND(ifq, ior) { \
+ simple_lock(&(ifq)->ifq_lock); \
+ enqueue_head(&(ifq)->ifq_head, (queue_entry_t)ior); \
+ (ifq)->ifq_len++; \
+ simple_unlock(&(ifq)->ifq_lock); \
+}
+
+#define IF_DEQUEUE(ifq, ior) { \
+ simple_lock(&(ifq)->ifq_lock); \
+ if (((ior) = (io_req_t)dequeue_head(&(ifq)->ifq_head)) != 0) \
+ (ifq)->ifq_len--; \
+ simple_unlock(&(ifq)->ifq_lock); \
+}
+
+#define IFQ_MAXLEN 50
+
+#define IFQ_INIT(ifq) { \
+ queue_init(&(ifq)->ifq_head); \
+ simple_lock_init(&(ifq)->ifq_lock); \
+ (ifq)->ifq_len = 0; \
+ (ifq)->ifq_maxlen = IFQ_MAXLEN; \
+ (ifq)->ifq_drops = 0; \
+}
+
+#define IFNET_SLOWHZ 1 /* granularity is 1 second */
+
+#endif /* _IF_HDR_ */
diff --git a/libmachdev/mach_glue.h b/libmachdev/mach_glue.h
index 6d0870ed..d1bd1fc7 100644
--- a/libmachdev/mach_glue.h
+++ b/libmachdev/mach_glue.h
@@ -9,8 +9,15 @@ struct net_device;
void skb_done_queue(struct sk_buff *skb);
struct sk_buff *skb_done_dequeue();
void *skb_reply(struct sk_buff *skb);
+
int netdev_flags(struct net_device *dev);
char *netdev_addr(struct net_device *dev);
+char *netdev_name (struct net_device *dev);
+unsigned int netdev_mtu (struct net_device *dev);
+unsigned short netdev_header_len (struct net_device *dev);
+unsigned short netdev_type (struct net_device *dev);
+unsigned char netdev_addr_len (struct net_device *dev);
+
int dev_change_flags (struct net_device *dev, short flags);
int linux_pkg_xmit (char *pkg_data, int len, void *del_data,
int (*del_func) (struct sk_buff *, void *),
diff --git a/libmachdev/net.c b/libmachdev/net.c
index b9d76731..88b1d6c8 100644
--- a/libmachdev/net.c
+++ b/libmachdev/net.c
@@ -61,6 +61,7 @@
#include <assert.h>
#include <string.h>
#include <arpa/inet.h>
+#include <error.h>
#include "mach_U.h"
@@ -75,6 +76,7 @@
#include "if_ether.h"
#include "util.h"
#include "mach_glue.h"
+#include "if_hdr.h"
#define ether_header ethhdr
@@ -86,9 +88,8 @@ extern struct port_class *dev_class;
struct net_data
{
struct port_info port; /* device port */
-// struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */
struct emul_device device; /* generic device structure */
- mach_port_t delivery_port;
+ struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */
struct net_device *dev; /* Linux network device structure */
struct net_data *next;
};
@@ -174,10 +175,12 @@ pre_kfree_skb (struct sk_buff *skb, void *data)
* Deliver the message to all right pfinet servers that
* connects to the virtual network interface.
*/
-static int
-deliver_msg(mach_port_t dest, struct net_rcv_msg *msg)
+int
+deliver_msg(struct net_rcv_msg *msg, if_filter_list_t *ifp)
{
mach_msg_return_t err;
+ queue_head_t *if_port_list;
+ net_rcv_port_t infp, nextfp;
msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
/* remember message sizes must be rounded up */
@@ -185,19 +188,42 @@ deliver_msg(mach_port_t dest, struct net_rcv_msg *msg)
msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL;
msg->msg_hdr.msgh_id = NET_RCV_MSG_ID;
- msg->msg_hdr.msgh_remote_port = dest;
- err = mach_msg ((mach_msg_header_t *)msg,
- MACH_SEND_MSG|MACH_SEND_TIMEOUT,
- msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL,
- 0, MACH_PORT_NULL);
- if (err != MACH_MSG_SUCCESS)
+ if_port_list = &ifp->if_rcv_port_list;
+ FILTER_ITERATE (if_port_list, infp, nextfp, &infp->input)
{
- mach_port_deallocate(mach_task_self (),
- ((mach_msg_header_t *)msg)->msgh_remote_port);
- return err;
+ mach_port_t dest;
+ net_hash_entry_t entp, *hash_headp;
+ int ret_count;
+
+ entp = (net_hash_entry_t) 0;
+ ret_count = bpf_do_filter (infp,
+ msg->packet + sizeof (struct packet_header),
+ msg->net_rcv_msg_packet_count, msg->header,
+ sizeof (struct ethhdr), &hash_headp, &entp);
+ if (entp == (net_hash_entry_t) 0)
+ dest = infp->rcv_port;
+ else
+ dest = entp->rcv_port;
+
+ if (ret_count)
+ {
+ msg->msg_hdr.msgh_remote_port = dest;
+ err = mach_msg ((mach_msg_header_t *)msg,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT,
+ msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL,
+ 0, MACH_PORT_NULL);
+ if (err != MACH_MSG_SUCCESS)
+ {
+ mach_port_deallocate(mach_task_self (),
+ ((mach_msg_header_t *)msg)->msgh_remote_port);
+ error (0, err, "mach_msg");
+ return -1;
+ }
+ }
}
+ FILTER_ITERATE_END
- return MACH_MSG_SUCCESS;
+ return 0;
}
/* Accept packet SKB received on an interface. */
@@ -241,7 +267,7 @@ netif_rx_handle (char *data, int len, struct net_device *dev)
net_msg->header_type = header_type;
net_msg->packet_type = packet_type;
net_msg->net_rcv_msg_packet_count = ph->length;
- deliver_msg (nd->delivery_port, net_msg);
+ deliver_msg (net_msg, &nd->ifnet.port_list);
free (net_msg);
}
@@ -256,20 +282,18 @@ dev_to_port (void *nd)
: MACH_PORT_NULL);
}
-#if 0
/*
* Initialize send and receive queues on an interface.
*/
void if_init_queues(ifp)
register struct ifnet *ifp;
{
- IFQ_INIT(&ifp->if_snd);
- queue_init(&ifp->if_rcv_port_list);
- queue_init(&ifp->if_snd_port_list);
- simple_lock_init(&ifp->if_rcv_port_list_lock);
- simple_lock_init(&ifp->if_snd_port_list_lock);
+// IFQ_INIT(&ifp->if_snd);
+ queue_init(&ifp->port_list.if_rcv_port_list);
+ queue_init(&ifp->port_list.if_snd_port_list);
+ mutex_init(&ifp->if_rcv_port_list_lock);
+ mutex_init(&ifp->if_snd_port_list_lock);
}
-#endif
static io_return_t
device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
@@ -279,7 +303,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
io_return_t err = D_SUCCESS;
struct net_device *dev;
struct net_data *nd;
-// struct ifnet *ifp;
+ struct ifnet *ifp;
/* Search for the device. */
dev = search_netdev (name);
@@ -293,6 +317,8 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
nd = search_nd (dev);
if (!nd)
{
+ char *name;
+
err = create_device_port (sizeof (*nd), &nd);
if (err)
{
@@ -305,23 +331,17 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
nd->device.emul_ops = &linux_net_emulation_ops;
nd->next = nd_head;
nd_head = nd;
-#if 0
- ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE);
- notify = ipc_port_make_sonce (nd->port);
- ip_lock (nd->port);
- ipc_port_nsrequest (nd->port, 1, notify, &notify);
- assert (notify == IP_NULL);
ifp = &nd->ifnet;
- ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0';
+ name = netdev_name (dev);
+ ifp->if_unit = name[strlen (name) - 1] - '0';
ifp->if_flags = IFF_UP | IFF_RUNNING;
- ifp->if_mtu = dev->mtu;
- ifp->if_header_size = dev->hard_header_len;
- ifp->if_header_format = dev->type;
- ifp->if_address_size = dev->addr_len;
- ifp->if_address = dev->dev_addr;
+ ifp->if_mtu = netdev_mtu (dev);
+ ifp->if_header_size = netdev_header_len (dev);
+ ifp->if_header_format = netdev_type (dev);
+ ifp->if_address_size = netdev_addr_len (dev);
+ ifp->if_address = netdev_addr (dev);
if_init_queues (ifp);
-#endif
if ((err = dev_open(dev)) < 0)
{
@@ -425,8 +445,8 @@ device_write (void *d, mach_port_t reply_port,
* Other network operations
*/
static io_return_t
-net_getstat(dev, flavor, status, count)
- struct net_device *dev;
+net_getstat(ifp, flavor, status, count)
+ struct ifnet *ifp;
dev_flavor_t flavor;
dev_status_t status; /* pointer to OUT array */
natural_t *count; /* OUT */
@@ -440,12 +460,12 @@ net_getstat(dev, flavor, status, count)
if (*count < NET_STATUS_COUNT)
return (D_INVALID_OPERATION);
- ns->min_packet_size = 60;
- ns->max_packet_size = ETH_HLEN + ETHERMTU;
- ns->header_format = HDR_ETHERNET;
- ns->header_size = ETH_HLEN;
- ns->address_size = ETH_ALEN;
- ns->flags = 0;
+ ns->min_packet_size = ifp->if_header_size;
+ ns->max_packet_size = ifp->if_header_size + ifp->if_mtu;
+ ns->header_format = ifp->if_header_format;
+ ns->header_size = ifp->if_header_size;
+ ns->address_size = ifp->if_address_size;
+ ns->flags = ifp->if_flags;
ns->mapped_size = 0;
*count = NET_STATUS_COUNT;
@@ -469,7 +489,7 @@ net_getstat(dev, flavor, status, count)
return (D_INVALID_OPERATION);
}
- memcpy(status, netdev_addr(dev), addr_byte_count);
+ memcpy(status, ifp->if_address, addr_byte_count);
if (addr_byte_count < addr_int_count * sizeof(int))
memset((char *)status + addr_byte_count, 0,
(addr_int_count * sizeof(int)
@@ -556,7 +576,7 @@ device_get_status (void *d, dev_flavor_t flavor, dev_status_t status,
#endif
{
/* common get_status request */
- return net_getstat (net->dev, flavor, status, count);
+ return net_getstat (&net->ifnet, flavor, status, count);
}
}
@@ -618,12 +638,8 @@ static io_return_t
device_set_filter (void *d, mach_port_t port, int priority,
filter_t * filter, unsigned filter_count)
{
- ((struct net_data *) d)->delivery_port = port;
- return 0;
-#if 0
- return net_set_filter (&((struct net_data *) d)->ifnet,
+ return net_set_filter (&((struct net_data *) d)->ifnet.port_list,
port, priority, filter, filter_count);
-#endif
}
/* Do any initialization required for network devices. */