File dhcpv6-1.0.22-netconfig.dif of Package dhcpv6

Index: src/dhcp6c.c
===================================================================
--- src/dhcp6c.c.orig
+++ src/dhcp6c.c
@@ -91,6 +91,19 @@
 #include "libdhcp_control.h"
 #endif
 
+#ifdef WITH_NETCONFIG
+#ifndef _GNU_SOURCE
+  #define _GNU_SOURCE
+  #include <getopt.h>
+  #undef  _GNU_SOURCE
+#else
+  #include <getopt.h>
+#endif
+#include "netconfig.h"
+
+static int use_netconfig = 0;
+#endif
+
 static int debug = 0;
 static u_long sig_flags = 0;
 
@@ -196,6 +209,12 @@ int dhcpv6_client(LIBDHCP_Control *libdh
     char *progname, *conffile = DHCP6C_CONF;
     FILE *pidfp;
     char *addr;
+#ifdef WITH_NETCONFIG
+    struct option long_options[] = {
+        {"netconfig", no_argument, NULL, 0x0100},
+        { NULL, 0, NULL, 0 }
+    };
+#endif
 
 #ifdef LIBDHCP
     libdhcp_control = libdhcp_ctl;
@@ -212,8 +231,17 @@ int dhcpv6_client(LIBDHCP_Control *libdh
         progname++;
 
     TAILQ_INIT(&request_list);
+#ifdef WITH_NETCONFIG
+    while ((ch = getopt_long(argc, argv, "c:r:R:P:vfIp:",
+                             long_options, NULL)) != -1) {
+        switch (ch) {
+            case 0x0100:
+                use_netconfig = 1;
+            break;
+#else
     while ((ch = getopt(argc, argv, "c:r:R:P:vfIp:")) != -1) {
         switch (ch) {
+#endif
             case 'p':
                 if (strlen(optarg) >= MAXPATHLEN) {
                     dhcpv6_dprintf(LOG_ERR, "pid file name is too long");
@@ -931,11 +959,25 @@ static void free_resources(struct dhcp6_
         dhcp6_remove_event(ev);
     }
 
-    /* restore /etc/resolv.conf.dhcpv6.bak back to /etc/resolv.conf */
-    if (!lstat(RESOLV_CONF_BAK_FILE, &buf)) {
-        if (rename(RESOLV_CONF_BAK_FILE, RESOLV_CONF_FILE))
-            dhcpv6_dprintf(LOG_ERR, "%s" " failed to backup resolv.conf",
-                           FNAME);
+#ifdef WITH_NETCONFIG
+    if(use_netconfig)
+    {
+        int ret = netconfig_remove("dhcp6c", debug, ifp->ifname);
+        dhcpv6_dprintf(LOG_DEBUG, "netconfig remove(%s): status %d",
+                                  ifp->ifname, ret);
+    }
+    else
+#endif
+#ifdef LIBDHCP
+    if (libdhcp_control && (libdhcp_control->capability & DHCP_CONFIGURE_RESOLVER))
+#endif
+    {
+        /* restore /etc/resolv.conf.dhcpv6.bak back to /etc/resolv.conf */
+        if (!lstat(RESOLV_CONF_BAK_FILE, &buf)) {
+            if (rename(RESOLV_CONF_BAK_FILE, RESOLV_CONF_FILE))
+                dhcpv6_dprintf(LOG_ERR, "%s" " failed to backup resolv.conf",
+                               FNAME);
+        }
     }
 
     free_servers(ifp);
@@ -1857,6 +1899,15 @@ static int client6_recvreply(struct dhcp
         return -1;
     }
 
+#ifdef WITH_NETCONFIG
+    if (use_netconfig)
+    {
+        int ret = netconfig_modify("dhcp6c", debug, ifp->ifname, optinfo, ifp);
+        dhcpv6_dprintf(LOG_DEBUG, "netconfig modify(%s): status %d",
+	                          ifp->ifname, ret);
+    }
+    else
+#endif
     if (!TAILQ_EMPTY(&optinfo->dns_list.addrlist) ||
         optinfo->dns_list.domainlist != NULL) {
 #ifdef LIBDHCP
@@ -2478,3 +2529,8 @@ static void setup_interface(char *ifname
 
     return;
 }
+
+#ifdef WITH_NETCONFIG
+#include "netconfig.c"
+#endif
+
Index: src/netconfig.c
===================================================================
--- /dev/null
+++ src/netconfig.c
@@ -0,0 +1,242 @@
+#ifdef WITH_NETCONFIG
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "netconfig.h"
+
+static int do_netconfig_restore = 0;
+
+int  netconfig_modify(const char *service, int verbose, const char *ifname,
+                      struct dhcp6_optinfo *optinfo, struct dhcp6_if *ifp)
+{
+	if(getuid() != 0 || geteuid() != 0)
+	{
+		return -1;
+	}
+
+	if( !service || !ifname || !optinfo || !ifp)
+	{
+		return -1;
+	}
+
+	int   rc;
+	int   fd[2] = {-1, -1};
+	rc = socketpair(AF_LOCAL, SOCK_STREAM, PF_LOCAL, fd);
+	if(rc == -1)
+	{
+		return -1;
+	}
+
+	pid_t pid;
+	pid = fork();
+	if(pid ==  0)
+	{
+		char *argv[] = {
+			"/sbin/netconfig",
+			"modify",
+			"-s", (char *)service,
+			"-i", (char *)ifname,
+			(verbose ? "-v" : NULL),
+			NULL
+		};
+		extern char **environ;
+
+		close(fd[0]);
+		if(dup2(fd[1], fileno(stdin)) == fileno(stdin))
+		{
+			close(fd[1]);
+			if(freopen("/dev/null", "w", stdout) &&
+			   freopen("/dev/null", "w", stderr))
+			{
+				execve(argv[0], argv, environ);
+			}
+		} else {
+			close(fd[1]);
+		}
+		exit(127);
+	}
+	else
+	if(pid > 0)
+	{
+		close(fd[1]);
+		FILE *out = fdopen(fd[0], "w");
+		if( out)
+		{
+			fprintf(out, "INTERFACE='%s'\n", ifname);
+#if 0
+			/*
+			** FIXME: the optinfo struct changed between 1.0.11 and 1.0.20
+			**        not a problem, since IPADDR is informational only
+			*/
+			struct ia_listval *ia = ia_find_listval(&optinfo->ia_list, ...);
+
+			if(!TAILQ_EMPTY(&ia->addr_list))
+			{
+				struct dhcp6_listval *lv;
+				size_t i = 0;
+				fprintf(out, "IPADDR='");
+				for (lv = TAILQ_FIRST(&ia->addr_list);
+				     lv;
+				     lv = TAILQ_NEXT(lv, link), i++)
+				{
+					if (lv->val_dhcp6addr.type != IAPD) {
+						u_int8_t plen = lv->val_dhcp6addr.plen ?
+								lv->val_dhcp6addr.plen :
+						dhcp6_get_prefixlen(&lv->val_dhcp6addr.addr, ifp);
+
+						dhcpv6_dprintf(LOG_DEBUG,
+							"netconfig modify(%s): "
+							"IPADDR+='%s/%u'",
+							ifname,
+							in6addr2str(&lv->val_dhcp6addr.addr, 0),
+							plen);
+						fprintf(out, "%s%s",
+							(i == 0 ? "" : " "),
+							in6addr2str(&lv->val_dhcp6addr.addr, 0));
+						if( plen)
+							fprintf(out, "/%u", plen);
+					}
+				}
+				fprintf(out, "'\n");
+			}
+#endif
+			fprintf(out, "DNSSERVERS='");
+			if (!TAILQ_EMPTY(&optinfo->dns_list.addrlist))
+			{
+				struct dhcp6_listval *d;
+				size_t i = 0;
+				for (d = TAILQ_FIRST(&optinfo->dns_list.addrlist);
+				     d;
+				     d = TAILQ_NEXT(d, link), i++)
+				{
+					dhcpv6_dprintf(LOG_DEBUG,
+						"netconfig modify(%s): "
+						"DNSSERVERS+='%s'",
+						ifname,
+						in6addr2str(&d->val_addr6, 0));
+
+					fprintf(out, "%s%s",
+						(i == 0 ? "" : " "),
+						in6addr2str(&d->val_addr6, 0));
+				}
+			}
+			else
+			{
+				dhcpv6_dprintf(LOG_DEBUG, "netconfig modify(%s): "
+					"no DNS server available", ifname);
+			}
+			fprintf(out, "'\n");
+
+			fprintf(out, "DNSSEARCH='");
+		        if (optinfo->dns_list.domainlist)
+			{
+				struct domain_list *dlist;
+				size_t i = 0;
+				for (dlist = optinfo->dns_list.domainlist;
+				     dlist;
+				     dlist = dlist->next, i++)
+				{
+					dhcpv6_dprintf(LOG_DEBUG,
+						"netconfig modify(%s): "
+						"DNSSEARCH+='%s'",
+						ifname,
+						dlist->name);
+
+					fprintf(out, "%s%s",
+						(i == 0 ? "" : " "),
+						dlist->name);
+				}
+			}
+			else
+			{
+				dhcpv6_dprintf(LOG_DEBUG, "netconfig modify(%s): "
+					"no DNS search list available", ifname);
+			}
+			fprintf(out, "'\n");
+
+			fclose(out);
+		}
+		else
+		{
+			close(fd[0]);
+		}
+
+		/* wait for child even unable to write */
+		int err;
+		int ret = 0;
+		do
+		{
+			err = waitpid(pid, &ret, 0);
+		} while(err == -1 && errno == EINTR);
+
+		do_netconfig_restore++;
+
+		return (((ret & 0x7f)==0) ?
+			((ret >> 8) & 0xff) :
+			-(ret & 0x7f));
+	}
+	return -1;
+}
+
+int  netconfig_remove(const char *service, int verbose, const char *ifname)
+{
+	if(getuid() != 0 || geteuid() != 0)
+	{
+		return -1;
+	}
+
+	if( !service || !ifname)
+	{
+		return -1;
+	}
+
+	if( do_netconfig_restore == 0)
+	{
+		return 0;
+	}
+
+	pid_t pid;
+
+	pid = fork();
+	if(pid ==  0)
+	{
+		char *argv[] = {
+			"/sbin/netconfig",
+			"remove",
+			"-s", (char *)service,
+			"-i", (char *)ifname,
+			(verbose ? "-v" : NULL),
+			NULL
+		};
+		extern char **environ;
+
+		if(freopen("/dev/null", "r", stdin)  &&
+		   freopen("/dev/null", "w", stdout) &&
+		   freopen("/dev/null", "w", stderr))
+		{
+			execve(argv[0], argv, environ);
+		}
+		exit(127);
+	}
+	else
+	if(pid > 0)
+	{
+		int err;
+		int ret = 0;
+		do
+		{
+			err = waitpid(pid, &ret, 0);
+		} while(err == -1 && errno == EINTR);
+
+		do_netconfig_restore = 0;
+
+		return (((ret & 0x7f)==0)   ?
+			((ret >> 8) & 0xff) :
+			-(ret & 0x7f));
+	}
+	return -1;
+}
+#endif
Index: src/netconfig.h
===================================================================
--- /dev/null
+++ src/netconfig.h
@@ -0,0 +1,12 @@
+#ifdef WITH_NETCONFIG
+#ifndef NETCONFIG_H
+#define NETCONFIG_H
+#include "dhcp6.h"
+
+int  netconfig_modify(const char *service, int verbose, const char *ifname,
+                      struct dhcp6_optinfo *optinfo, struct dhcp6_if *ifp);
+
+int  netconfig_remove(const char *service, int verbose, const char *ifname);
+
+#endif
+#endif
openSUSE Build Service is sponsored by