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