bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The patch of pfinet


From: zhengda
Subject: Re: The patch of pfinet
Date: Tue, 12 Aug 2008 15:52:58 +0200
User-agent: Thunderbird 2.0.0.16 (X11/20080707)

olafBuddenhagen@gmx.net wrote:
Hi,

On Fri, Aug 08, 2008 at 08:09:24AM +0200, zhengda wrote:

The patch enables the pfinet to work with the multiplexer and use the
filter rule that only accepts the packet whose destination  is the
pfinet server.

This rather sounds like two totally orthogonal changes, that really
should go into two separate patches?
I separate them into 3 patches.
pfinet1.patch. To make it open the virtual network interface.
pfinet2.patch. To use the proper filter rule in pfinet.
pfinet3.patch. To enable ioctl to set the network device into the promiscuous mode. Since my mail client might reformat the patches, I put them in the attachment.

Zheng Da

Needed for Hurd 0.3

2008-07-29 Zheng Da <zhengda1936@gmail.com>

        * ethernet.c: Open the virtual network device.
        (ether_filter): Use the bpf filter.
        (ethernet_open): Open the virtual network device if the user specifies 
one.

        * options.c: Add another option to open the virtual network interface.

diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet.old/ethernet.c pfinet/ethernet.c
--- pfinet.old/ethernet.c       2007-10-09 10:01:34.590000000 +0200
+++ pfinet/ethernet.c   2008-08-11 04:33:20.000000000 +0200
@@ -68,16 +68,17 @@
 {
 }
 
-static short ether_filter[] =
+/* The BPF instruction allows IP and ARP packets */
+static struct bpf_insn ether_filter[] =
 {
-#ifdef NETF_IN
-  /* We have to tell the packet filtering code that we're interested in
-     incoming packets.  */
-  NETF_IN, /* Header.  */
-#endif
-  NETF_PUSHLIT | NETF_NOP,
-  1
-};
+    {NETF_IN|NETF_BPF, /* Header. */ 0, 0, 0},
+    {40, 0, 0, 12},
+    {21, 1, 0, 2054},
+    {21, 0, 1, 2048},
+    {6, 0, 0, 1500},
+    {6, 0, 0, 0}
+ };
+
 static int ether_filter_len = sizeof (ether_filter) / sizeof (short);
 
 static struct port_bucket *etherport_bucket;
@@ -151,6 +152,7 @@
 int
 ethernet_open (struct device *dev)
 {
+  extern char *master_device_file;
   error_t err;
   device_t master_device;
   struct ether_device *edev = (struct ether_device *) dev->priv;
@@ -166,9 +168,18 @@
 
   mach_port_set_qlimit (mach_task_self (), edev->readptname, 
MACH_PORT_QLIMIT_MAX);
 
-  err = get_privileged_ports (0, &master_device);
-  if (err)
-    error (2, err, "cannot get device master port");
+  if (master_device_file)
+    {
+      master_device = file_name_lookup (master_device_file , 0 , 0);
+      if (master_device == MACH_PORT_NULL)
+        error (2, 0, "file_name_lookup %s", master_device_file);
+    }
+  else
+    {
+      err = get_privileged_ports (0, &master_device);
+      if (err)
+        error (2, err, "cannot get device master port");
+    }
 
   err = device_open (master_device, D_WRITE | D_READ, dev->name, 
&edev->ether_port);
   mach_port_deallocate (mach_task_self (), master_device);
diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet.old/options.c pfinet/options.c
--- pfinet.old/options.c        2007-10-14 04:26:10.000000000 +0200
+++ pfinet/options.c    2008-08-11 04:41:24.000000000 +0200
@@ -60,6 +60,7 @@
 extern int inet6_addr_add (int ifindex, struct in6_addr *pfx, int plen);
 extern int inet6_addr_del (int ifindex, struct in6_addr *pfx, int plen);
 
+char *master_device_file = NULL;
 
 /* Pfinet options.  Used for both startup and runtime.  */
 static const struct argp_option options[] =
@@ -77,6 +78,7 @@
   {"gateway6",  'G', "ADDRESS", 0, "Set the IPv6 default gateway"},
 #endif
   {"shutdown",  's', 0,         0, "Shut it down"},
+  {"master",    'M', "FILE",    0, "Get a master device port"},
   {0}
 };
 
@@ -90,6 +92,9 @@
   /* The network interface in question.  */
   struct device *device;
 
+/* the name of the network interface */
+  char *name;
+
   /* New values to apply to it. (IPv4) */
   uint32_t address, netmask, peer, gateway;
 
@@ -126,6 +131,7 @@
   h->num_interfaces++;
   h->curint = new + h->num_interfaces - 1;
   h->curint->device = 0;
+  h->curint->name = 0;
   h->curint->address = INADDR_NONE;
   h->curint->netmask = INADDR_NONE;
   h->curint->peer = INADDR_NONE;
@@ -195,12 +201,12 @@
     case 'i':
       /* An interface.  */
       err = 0;
-      if (h->curint->device)
+      if (h->curint->name)
        /* The current interface slot is not available.  */
        {
          /* First see if a previously specified one is being re-specified.  */
          for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
-           if (strcmp (in->device->name, arg) == 0)
+            if (strcmp (in->name, arg) == 0)
              /* Re-use an old slot.  */
              {
                h->curint = in;
@@ -213,9 +219,7 @@
       in = h->curint;
 
       if (! err)
-       err = find_device (arg, &in->device);
-      if (err)
-       FAIL (err, 10, err, "%s", arg);
+        in->name = arg;
 
       break;
 
@@ -240,6 +244,8 @@
       h->curint->peer = ADDR (arg, "peer"); break;
     case 'g':
       h->curint->gateway = ADDR (arg, "gateway"); break;
+    case 'M':
+      master_device_file = arg; break;
 
     case '4':
       pfinet_bind (PORTCLASS_INET, arg);
@@ -303,18 +309,27 @@
       break;
 
     case ARGP_KEY_SUCCESS:
+      for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
+        {
+          if (in->name)
+            {
+              err = find_device (in->name, &in->device);
+              if (err)
+                FAIL (err, 10, err, "%s", in->name);
+            }
+          if (! in->device)
+            /* No specific interface specified; is that ok?  */
+            if (in->address != INADDR_NONE || in->netmask != INADDR_NONE
+                || in->gateway != INADDR_NONE)
+              /* Some options were specified, so we need an interface.  See if
+                 there's a single extant interface to use as a default.  */
+              {
+                err = find_device (0, &in->device);
+                if (err)
+                  FAIL (err, 13, 0, "No default interface");
+              }
+        }
       in = h->curint;
-      if (! in->device)
-       /* No specific interface specified; is that ok?  */
-       if (in->address != INADDR_NONE || in->netmask != INADDR_NONE
-           || in->gateway != INADDR_NONE)
-         /* Some options were specified, so we need an interface.  See if
-             there's a single extant interface to use as a default.  */
-         {
-           err = find_device (0, &in->device);
-           if (err)
-             FAIL (err, 13, 0, "No default interface");
-         }
 #if 0                          /* XXX what does this mean??? */
       /* Check for bogus option combinations.  */
       for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
Needed for Hurd 0.3

2008-07-29 Zheng Da <zhengda1936@gmail.com>

        * Makefile: Compile pcap_filter.c.

        * ethernet.c: Open the virtual network device.
        [HAVE_PCAP] (ethernet_reset_filter, ethernet_reset_ipfilter): New 
functions.

        * linux-src/net/ipv4/devinet.c (configure_device, devinet_ioctl):
        Set the filter rules when IP address is changed.

        * pcap_filter.c: New file.
        (trans_filter_program): New function.

diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet1/Makefile pfinet/Makefile
--- pfinet1/Makefile    2008-08-11 05:11:35.910000000 +0200
+++ pfinet/Makefile     2008-08-11 05:15:30.300000000 +0200
@@ -83,7 +83,7 @@
 SRCS           = sched.c timer-emul.c socket.c main.c ethernet.c \
                  io-ops.c socket-ops.c misc.c time.c options.c loopback.c \
                  kmem_cache.c stubs.c dummy.c tunnel.c pfinet-ops.c \
-                 iioctl-ops.c
+                 iioctl-ops.c pcap_filter.c
 MIGSRCS                = ioServer.c socketServer.c startup_notifyServer.c \
                  pfinetServer.c iioctlServer.c
 OBJS           = $(patsubst %.S,%.o,$(patsubst %.c,%.o,\
@@ -117,6 +117,11 @@
 # compiling `pfinet' with GCC 4.2.
 CFLAGS += -fno-strict-aliasing
 
+ifdef LIBPCAP
+CFLAGS += -DHAVE_PCAP
+LDFLAGS += -lpcap
+endif
+
 asm/checksum.h: ../config.status
        mkdir -p $(@D)
        echo > $@.new \
diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet1/ethernet.c pfinet/ethernet.c
--- pfinet1/ethernet.c  2008-08-11 05:43:29.000000000 +0200
+++ pfinet/ethernet.c   2008-08-11 05:46:20.230000000 +0200
@@ -31,6 +31,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
+#include <device/bpf.h>
 
 
 struct port_class *etherreadclass;
@@ -285,3 +286,54 @@
   err = - register_netdevice (dev);
   assert_perror (err);
 }
+
+#ifdef HAVE_PCAP
+
+int
+ethernet_reset_filter (struct device *dev, char *filter_str)
+{
+  error_t err;
+  struct ether_device *edev = (struct ether_device *) dev->priv;
+  int len;
+  struct bpf_insn *insn;
+
+  insn = trans_filter_program (filter_str, 0, &len);
+  if (insn == NULL)
+    return -1;
+
+  /* if the device isn't initialized */
+  if (edev->readpt == NULL)
+    return -1;
+
+  err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt),
+                           MACH_MSG_TYPE_MAKE_SEND, 0, (short *)insn, len);
+  if (err)
+    error (2, err, "ethernet_reset_filter: %s", dev->name);
+
+  free (insn);
+  return 0;
+}
+
+int ethernet_reset_ipfilter (struct device *dev, struct in_addr addr)
+{
+  char ip_str[INET_ADDRSTRLEN];
+  char filter_str[128];
+
+  if (inet_ntop (AF_INET, &addr, ip_str, INET_ADDRSTRLEN) == NULL)
+    {
+      perror ("inet_ntop");
+      return -1;
+    }
+  snprintf (filter_str, sizeof (filter_str), "arp or (ip host %s)", ip_str);
+  return ethernet_reset_filter (dev, filter_str);
+}
+
+#else
+
+int ethernet_reset_ipfilter (struct device *dev, struct in_addr addr)
+{
+  return 0;
+}
+
+#endif
+
diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet1/linux-src/net/ipv4/devinet.c pfinet/linux-src/net/ipv4/devinet.c
--- pfinet1/linux-src/net/ipv4/devinet.c        2008-08-11 05:12:07.530000000 
+0200
+++ pfinet/linux-src/net/ipv4/devinet.c 2008-08-11 05:21:42.000000023 +0200
@@ -447,6 +447,12 @@
   if (broadcast != INADDR_NONE)
     ifa->ifa_broadcast = broadcast;
 
+  if (addr != INADDR_NONE)
+    {
+      struct in_addr in_addr = {addr};
+      ethernet_reset_ipfilter (dev, in_addr);
+    }
+
   return - (inet_set_ifa (dev, ifa)
            ?: dev_change_flags (dev, dev->flags | IFF_UP));
 }
@@ -631,6 +637,7 @@
                                ifa->ifa_mask = inet_make_mask(32);
                        }
                        ret = inet_set_ifa(dev, ifa);
+                       ethernet_reset_ipfilter (dev, sin->sin_addr);
                        break;
 
                case SIOCSIFBRDADDR:    /* Set the broadcast address */
diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet1/pcap_filter.c pfinet/pcap_filter.c
--- pfinet1/pcap_filter.c       1970-01-01 01:00:00.000000000 +0100
+++ pfinet/pcap_filter.c        2008-08-11 05:22:25.890000000 +0200
@@ -0,0 +1,75 @@
+/* 
+   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 the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * This file translates a string into a bpf program.
+ * The BPF structures are defined in both of bpf.h and pcap-bpf.h
+ * Hopefully, there is no conflict between them.
+ * This file uses the BPF definition in pcap-bpf.h.
+ */
+
+#ifdef HAVE_PCAP
+
+#include <pcap.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NETF_IN 0x1
+#define NETF_OUT 0x2
+#define NETF_NBPA 10
+#define NETF_BPF (1 << NETF_NBPA)
+
+/* this function translates the bpf program
+ * from the string into the instructions */
+struct bpf_insn *trans_filter_program (char *str, int send, int *filter_len)
+{
+  struct bpf_program program;
+  struct bpf_insn *insn;
+  pcap_t *pcap;
+  int err;
+
+  pcap = pcap_open_dead (DLT_EN10MB, 1500);
+  if (pcap == NULL)
+    return NULL;
+  err = pcap_compile (pcap, &program, str, 1, 0);
+  if (err < 0) 
+    {
+      fprintf (stderr, "pcap_compile: %s\n", pcap_geterr (pcap));
+      pcap_close (pcap);
+      return NULL;
+    }
+
+  insn = (struct bpf_insn *) malloc ((program.bf_len + 1) * sizeof (*insn));
+  /* clear the first instruction */
+  memset (insn, 0, sizeof (*insn));
+  if (send)
+    insn->code = NETF_OUT | NETF_BPF;
+  else
+    insn->code = NETF_IN | NETF_BPF;
+  memcpy (insn + 1, program.bf_insns, program.bf_len * sizeof (*insn));
+  *filter_len = ((program.bf_len + 1) * sizeof (*insn)) / sizeof (short);
+  pcap_freecode (&program);
+  pcap_close (pcap);
+
+  return insn;
+}
+
+#endif
Needed for Hurd 0.3

2008-07-29 Zheng Da <zhengda1936@gmail.com>

        * ethernet.c (machdev_change_flags): New function.

        * iioctl-ops.c (S_iioctl_siocsifflags): Change the flags of the Mach 
device.

diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet2/ethernet.c pfinet/ethernet.c
--- pfinet2/ethernet.c  2008-08-11 05:50:34.000000000 +0200
+++ pfinet/ethernet.c   2008-08-11 05:55:17.060000000 +0200
@@ -337,3 +337,11 @@
 
 #endif
 
+int machdev_change_flags (struct device *dev, short flags)
+{
+  /* Change the  Mach device flags. Some  flags (e.g., promiscuous
+     and multicast) are handled by the drivers. */
+  return device_set_status(((struct ether_device *)dev->priv)->ether_port, 
+                    NET_FLAGS, (dev_status_t) &flags, sizeof (flags));
+}
+
diff -urN -x '*.[od]' -x '*Server.c' -x '*_S.h' -x '*.prof_d' -x '*~' 
pfinet2/iioctl-ops.c pfinet/iioctl-ops.c
--- pfinet2/iioctl-ops.c        2008-08-11 05:50:34.000000000 +0200
+++ pfinet/iioctl-ops.c 2008-08-11 05:57:12.570000000 +0200
@@ -188,7 +188,10 @@
   else if (!dev)
     err = ENODEV;
   else
-    err = dev_change_flags(dev, flags);
+    {
+      err = dev_change_flags(dev, flags);
+      err = machdev_change_flags (dev, flags);
+    }
 
   __mutex_unlock (&global_lock);
   end_using_socket_port (user);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]