Hi Thomas!

On Mon, Oct 08, 2007 at 08:31:15PM +0200, Thomas Schwinge wrote:
> [...] Have pfinet include the IPv6 code by default, but
> only activate the IPv6 engine if IPv6 services are actually needed, i.e.,
> if they are requested by the pfinet translator setting.  The increase in
> the pfinet translator's executable size does not matter in my opinion.

You're right that it doesn't make much sense to enable the IPv6 protocol
bits, if /servers/socket/26 is not bound.  I've now patched pfinet to
to do late (on demand) initialization of the engine, however we now need
to manually care for the protocol <-> device link (see new
pfinet_activate_ipv6 function).

Now you can even first start pfinet (passivly), bound to
/servers/socket/2 only, and then activate the IPv6 engine using:

    fsysopts /servers/socket/2 -6 /servers/socket/26 -a ...

It even works the other way round, but IPv6-only (currently) doesn't
make much sense, since DNS is usually configured to happen over IPv4.

cheers,
  stesie

diff --git a/ChangeLog b/ChangeLog
index c95cea7..7fc1aa5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,7 +4,6 @@
 	set to 1.
 	* Makefile (ipv6-srcs): New variable.
 	(LINUXSRCS): Add ipv6-srcs.
-	(target): Set to pfinet6.
 	
 	* ethernet.c (ethernet_demuxer): Call skb_put instead of changing
 	skb->len directly, and thus now update skb->tail accordingly.
@@ -20,6 +19,7 @@
 	(trivfs_protid_nportclasses, trivfs_cntl_nportclasses): Set to 2.
 	(pfinet_bootstrap_portclass): New variable.
 	(pfinet_bind): New function.
+	(pfinet_active_ipv6) [CONFIG_IPV6]: New function.
 	(main) [CONFIG_IPV6]: Call inet6_proto_init.
 	(main): Reordered to allow pfinet to not be started as a
 	translator, if pfinet_bind is used.  If started as a translator,
diff --git a/Makefile b/Makefile
index 3e8c7a6..9bc97e8 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@
 #   along with this program; if not, write to the Free Software
 #   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
-dir		:= pfinet6
+dir		:= pfinet
 makemode	:= server
 
 core-srcs	:= datagram.c						      \
@@ -101,7 +101,7 @@ ASMHEADERS=bitops.h segment.h system.h
 
 HURDLIBS=trivfs fshelp threads ports ihash shouldbeinlibc iohelp
 
-target = pfinet6
+target = pfinet
 
 include ../Makeconf
 
@@ -114,7 +114,7 @@ CPPFLAGS += -imacros $(srcdir)/config.h		\
 	    -I$(srcdir)/linux-src/include
 
 # Don't ask...  We use Linux code.  The problem was first noticed when
-# compiling `pfinet6' with GCC 4.2.
+# compiling `pfinet' with GCC 4.2.
 CFLAGS += -fno-strict-aliasing
 
 asm/checksum.h: ../config.status
diff --git a/main.c b/main.c
index fbf3f4a..c1e080a 100644
--- a/main.c
+++ b/main.c
@@ -37,11 +37,17 @@
 #include <linux/netdevice.h>
 #include <linux/inet.h>
 
+static void pfinet_activate_ipv6 (void);
+
 /* devinet.c */
 extern error_t configure_device (struct device *dev,
                                  uint32_t addr, uint32_t netmask,
 				 uint32_t peer, uint32_t broadcast);
 
+/* addrconf.c */
+extern int addrconf_notify(struct notifier_block *this, unsigned long event, 
+			   void * data);
+
 int trivfs_fstype = FSTYPE_MISC;
 int trivfs_fsid;
 int trivfs_support_read = 1;
@@ -267,10 +273,6 @@ main (int argc,
 #endif
   inet_proto_init (0);
 
-#ifdef CONFIG_IPV6
-  inet6_proto_init (0);
-#endif
-
   /* This initializes the Linux network device layer, including
      initializing each device on the `dev_base' list.  For us,
      that means just loopback_dev, which will get fully initialized now.
@@ -298,6 +300,11 @@ main (int argc,
     if(trivfs_protid_portclasses[pfinet_bootstrap_portclass]
        != MACH_PORT_NULL)
       error(1, 0, "No portclass left to assign to bootstrap port");
+
+#ifdef CONFIG_IPV6
+    if (pfinet_bootstrap_portclass == PORTCLASS_INET6)
+      pfinet_activate_ipv6 ();
+#endif
     
     trivfs_protid_portclasses[pfinet_bootstrap_portclass] =
       ports_create_class (trivfs_clean_protid, 0);
@@ -345,6 +352,29 @@ main (int argc,
   return 0;
 }
 
+#ifdef CONFIG_IPV6
+static void
+pfinet_activate_ipv6 (void)
+{
+  inet6_proto_init (0);
+
+  /* Since we're registering the protocol after the devices have been
+     initialized, we need to care for the linking by ourselves. */
+  struct device *dev = dev_base;
+  
+  if (dev)
+    do
+      {
+	if (!(dev->flags & IFF_UP))
+	  continue;
+
+	addrconf_notify (NULL, NETDEV_REGISTER, dev);
+	addrconf_notify (NULL, NETDEV_UP, dev);
+      }
+    while ((dev = dev->next));
+}
+#endif /* CONFIG_IPV6 */
+
 void
 pfinet_bind (int portclass, const char *name)
 {
@@ -357,6 +387,14 @@ pfinet_bind (int portclass, const char *name)
     err = errno;
 
   if (! err) {
+    if (trivfs_protid_portclasses[portclass] != MACH_PORT_NULL)
+      error (1, 0, "Cannot bind one protocol to multiple nodes.\n");
+
+#ifdef CONFIG_IPV6
+    if (portclass == PORTCLASS_INET6)
+      pfinet_activate_ipv6 ();
+#endif
+
     trivfs_protid_portclasses[portclass] =
       ports_create_class (trivfs_clean_protid, 0);
     trivfs_cntl_portclasses[portclass] =
diff --git a/options.c b/options.c
index 8a9d2a3..85738a5 100644
--- a/options.c
+++ b/options.c
@@ -343,7 +343,8 @@ parse_opt (int opt, char *arg, struct argp_state *state)
 	{
 #ifdef CONFIG_IPV6
 	  struct inet6_dev *idev = NULL;
-	  if (in->device)
+	  if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL
+	      && in->device)
 	    idev = ipv6_find_idev(in->device);
 #endif
 
@@ -438,9 +439,12 @@ parse_opt (int opt, char *arg, struct argp_state *state)
 
       /* Set IPv6 default router. */
 #ifdef CONFIG_IPV6
-      rt6_purge_dflt_routers (0);
-      if (gw6_in)
-	rt6_add_dflt_router (&gw6_in->gateway6, gw6_in->device);
+      if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL)
+	{
+	  rt6_purge_dflt_routers (0);
+	  if (gw6_in)
+	    rt6_add_dflt_router (&gw6_in->gateway6, gw6_in->device);
+	}
 #endif       
 
       __mutex_unlock (&global_lock);
@@ -502,7 +506,11 @@ trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
 #undef ADD_ADDR_OPT
 
 #ifdef CONFIG_IPV6
-      struct inet6_dev *idev = ipv6_find_idev(dev);
+      struct inet6_dev *idev = NULL;
+
+      if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL)
+	idev = ipv6_find_idev(dev);
+
       if (idev)
 	{
 	  struct inet6_ifaddr *ifa = idev->addr_list;
_______________________________________________
Bug-hurd mailing list
Bug-hurd@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-hurd

Reply via email to