diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-04-08 23:09:39 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-04-08 23:09:39 +0000 |
commit | 5499792c357777dcfc5ee461fa64baaba1d2dde5 (patch) | |
tree | 15363c44fe541b3adcd720edf39696e9230d7feb /eth-multiplexer/vdev.c | |
parent | e5fca9a10c2622b85cc77e776ea56c8dbb9847e6 (diff) | |
parent | c6db537edac054a03847b1b99f78c00703f48d6b (diff) |
Merge branch 'dde' of git.debian.org:/git/pkg-hurd/hurd into dde
Diffstat (limited to 'eth-multiplexer/vdev.c')
-rw-r--r-- | eth-multiplexer/vdev.c | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/eth-multiplexer/vdev.c b/eth-multiplexer/vdev.c deleted file mode 100644 index 29e2b4b1..00000000 --- a/eth-multiplexer/vdev.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -/* This file implement the virtual network interface */ - -#include <string.h> -#include <stdio.h> -#include <netinet/ip.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <stdlib.h> -#include <error.h> - -#include <cthreads.h> - -#include "vdev.h" -#include "queue.h" -#include "bpf_impl.h" -#include "util.h" - -#define ETH_HLEN sizeof (struct ethhdr) - -static struct vether_device *dev_head; -static int dev_num; - -/* This lock is only used to protected the virtual device list. - * TODO every device structure should has its own lock to protect itself. */ -static struct mutex dev_list_lock = MUTEX_INITIALIZER; - -mach_msg_type_t header_type = -{ - MACH_MSG_TYPE_BYTE, - 8, - NET_HDW_HDR_MAX, - TRUE, - FALSE, - FALSE, - 0 -}; - -mach_msg_type_t packet_type = -{ - MACH_MSG_TYPE_BYTE, /* name */ - 8, /* size */ - 0, /* number */ - TRUE, /* inline */ - FALSE, /* longform */ - FALSE /* deallocate */ -}; - -int -get_dev_num () -{ - return dev_num; -} - -struct vether_device * -lookup_dev_by_name (char *name) -{ - struct vether_device *vdev; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - if (strncmp (vdev->name, name, IFNAMSIZ) == 0) - break; - } - mutex_unlock (&dev_list_lock); - return vdev; -} - -int -foreach_dev_do (int (func) (struct vether_device *)) -{ - struct vether_device *vdev; - int rval = 0; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - mutex_unlock (&dev_list_lock); - /* func() can stop the loop by returning <> 0 */ - rval = func (vdev); - mutex_lock (&dev_list_lock); - if (rval) - break; - } - mutex_unlock (&dev_list_lock); - return rval; -} - -/* Remove all filters with the dead name. */ -int -remove_dead_port_from_dev (mach_port_t dead_port) -{ - struct vether_device *vdev; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - remove_dead_filter (&vdev->port_list, - &vdev->port_list.if_rcv_port_list, dead_port); - remove_dead_filter (&vdev->port_list, - &vdev->port_list.if_snd_port_list, dead_port); - } - mutex_unlock (&dev_list_lock); - return 0; -} - -/* Add a new virtual interface to the multiplexer. */ -struct vether_device * -add_vdev (char *name, int size, - struct port_class *class, struct port_bucket *bucket) -{ - error_t err; - struct vether_device *vdev; - - if (size < sizeof (*vdev)) - size = sizeof (*vdev); - err = ports_create_port (class, bucket, size, &vdev); - if (err) - return NULL; - - vdev->dev_port = ports_get_right (vdev); - ports_port_deref (vdev); - strncpy (vdev->name, name, IFNAMSIZ); - vdev->if_header_size = ETH_HLEN; - vdev->if_mtu = ETH_MTU; - vdev->if_header_format = HDR_ETHERNET; - vdev->if_address_size = ETH_ALEN; - vdev->if_flags = 0; - vdev->if_address[0] = 0x52; - vdev->if_address[1] = 0x54; - *(int *)(vdev->if_address + 2) = random (); - - queue_init (&vdev->port_list.if_rcv_port_list); - queue_init (&vdev->port_list.if_snd_port_list); - - mutex_lock (&dev_list_lock); - vdev->next = dev_head; - dev_head = vdev; - vdev->pprev = &dev_head; - if (vdev->next) - vdev->next->pprev = &vdev->next; - dev_num++; - mutex_unlock (&dev_list_lock); - - debug ("initialize the virtual device\n"); - return vdev; -} - -void -destroy_vdev (void *port) -{ - struct vether_device *vdev = (struct vether_device *)port; - - debug ("device %s is going to be destroyed\n", vdev->name); - /* Delete it from the virtual device list */ - mutex_lock (&dev_list_lock); - *vdev->pprev = vdev->next; - if (vdev->next) - vdev->next->pprev = vdev->pprev; - dev_num--; - mutex_unlock (&dev_list_lock); - - /* TODO Delete all filters in the interface, - * there shouldn't be any filters left */ - destroy_filters (&vdev->port_list); -} - -/* Test if there are devices existing in the list */ -int -has_vdev () -{ - return dev_head != NULL; -} - -/* Broadcast the packet to all virtual interfaces - * except the one the packet is from */ -int -broadcast_pack (char *data, int datalen, struct vether_device *from_vdev) -{ - int internal_deliver_pack (struct vether_device *vdev) - { - if (from_vdev == vdev) - return 0; - return deliver_pack (data, datalen, vdev); - } - - return foreach_dev_do (internal_deliver_pack); -} - -/* Create a message, and deliver it. */ -int -deliver_pack (char *data, int datalen, struct vether_device *vdev) -{ - struct net_rcv_msg msg; - int pack_size; - struct ethhdr *header; - struct packet_header *packet; - - pack_size = datalen - sizeof (struct ethhdr); - /* remember message sizes must be rounded up */ - msg.msg_hdr.msgh_size = (((mach_msg_size_t) (sizeof(struct net_rcv_msg) - - NET_RCV_MAX + pack_size)) + 3) & ~3; - - header = (struct ethhdr *) msg.header; - packet = (struct packet_header *) msg.packet; - msg.header_type = header_type; - memcpy (header, data, sizeof (struct ethhdr)); - msg.packet_type = packet_type; - memcpy (packet + 1, data + sizeof (struct ethhdr), pack_size); - packet->type = header->h_proto; - packet->length = pack_size + sizeof (struct packet_header); - msg.packet_type.msgt_number = packet->length; - - return deliver_msg (&msg, vdev); -} - -/* Broadcast the message to all virtual interfaces. */ -int -broadcast_msg (struct net_rcv_msg *msg) -{ - int rval = 0; - mach_msg_header_t header; - - int internal_deliver_msg (struct vether_device *vdev) - { - return deliver_msg (msg, vdev); - } - - /* Save the message header because deliver_msg will change it. */ - header = msg->msg_hdr; - rval = foreach_dev_do (internal_deliver_msg); - msg->msg_hdr = header; - return rval; -} - -/* - * Deliver the message to all right pfinet servers that - * connects to the virtual network interface. - */ -int -deliver_msg(struct net_rcv_msg *msg, struct vether_device *vdev) -{ - 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 */ - msg->msg_hdr.msgh_local_port = MACH_PORT_NULL; - msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; - msg->msg_hdr.msgh_id = NET_RCV_MSG_ID; - - if_port_list = &vdev->port_list.if_rcv_port_list; - FILTER_ITERATE (if_port_list, infp, nextfp, &infp->input) - { - 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) - { - debug ("before delivering the packet\n"); - 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; - } - debug ("after delivering the packet\n"); - } - } - FILTER_ITERATE_END - - return 0; -} - |