]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Initialize the environment rather than using temporary client scripts.
authorTed Lemon <source@isc.org>
Thu, 20 Jul 2000 00:53:24 +0000 (00:53 +0000)
committerTed Lemon <source@isc.org>
Thu, 20 Jul 2000 00:53:24 +0000 (00:53 +0000)
Makefile.conf
client/Makefile.dist
client/clparse.c
client/dhclient.c
includes/dhcpd.h

index 576513cad5dc905129bec726f7a4127918e89882..3d601fd52497314c2e3a928cd2a4d9301a2133b7 100644 (file)
@@ -41,6 +41,7 @@ LIBS =
 COPTS = $(BINDDEF)
 RANLIB = ranlib
 MKDEP = mkdep
+CLIENT_PATH = '"PATH=/usr/ucb:/usr/bin:/usr/sbin:/bin:/sbin"'
 
 BINDLIB = ../minires/libres.a
 BINDINC =
index 18322410dc34aaca7a706a9f9a458dbdea0bc016..3e64558ed110fbbe39d01b47de7cc918de1640f2 100644 (file)
@@ -29,7 +29,8 @@ MAN    = dhclient.8 dhclient.conf.5 dhclient-script.8 dhclient.leases.5
 DEBUG  = -g
 INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
 DHCPLIB = ../common/libdhcp.a ../omapip/libomapi.a $(BINDLIB)
-CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
+CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) \
+               -DCLIENT_PATH=${CLIENT_PATH}
 
 all:   $(PROG) $(CATMANPAGES)
 
index 0dacac616d3d87f7a57b9c7935356ec55b0d3299..48ffa7d11a3bc554294c13cfe84fd021eb325c40 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: clparse.c,v 1.47 2000/06/24 05:53:35 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: clparse.c,v 1.48 2000/07/20 00:53:17 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 
 static TIME parsed_time;
 
+char client_script_name [] = "/etc/dhclient-script";
+
 struct client_config top_level_config;
 
 u_int32_t default_requested_options [] = {
@@ -94,7 +96,7 @@ isc_result_t read_client_conf ()
        top_level_config.backoff_cutoff = 15;
        top_level_config.initial_interval = 3;
        top_level_config.bootp_policy = P_ACCEPT;
-       top_level_config.script_name = "/etc/dhclient-script";
+       top_level_config.script_name = client_script_name;
        top_level_config.requested_options = default_requested_options;
        top_level_config.omapi_port = -1;
 
index 9b794006adf435ba027558365c37514316a9273f..de006233b8a65ed99ae7892cee894bb570bf3ffa 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.107 2000/07/17 20:56:11 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.108 2000/07/20 00:53:18 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -2134,46 +2134,29 @@ void script_init (client, reason, medium)
        const char *reason;
        struct string_list *medium;
 {
-       int fd;
-#ifndef HAVE_MKSTEMP
+       struct string_list *sl, *next;
 
-       do {
-#endif
-               strcpy (scriptName, "/tmp/dcsXXXXXX");
-#ifdef HAVE_MKSTEMP
-               fd = mkstemp (scriptName);
-#else
-               if (!mktemp (scriptName))
-                       log_fatal ("can't create temporary script %s: %m",
-                                  scriptName);
-               fd = open (scriptName, O_EXCL | O_CREAT | O_WRONLY, 0600);
-       } while (fd < 0 && errno == EEXIST);
-#endif
-       if (fd < 0)
-               log_fatal ("can't create temporary script %s: %m", scriptName);
-
-
-       scriptFile = fdopen (fd, "w");
-       if (!scriptFile)
-               log_fatal ("can't write script file: %m");
-       fprintf (scriptFile, "#!/bin/sh\n\n");
        if (client) {
+               for (sl = client -> env; sl; sl = next) {
+                       next = sl -> next;
+                       dfree (sl, MDL);
+               }
+               client -> env = (struct string_list *)0;
+               client -> envc = 0;
+               
                if (client -> interface) {
-                       fprintf (scriptFile, "interface=\"%s\"\n",
-                                client -> interface -> name);
-                       fprintf (scriptFile, "export interface\n");
+                       client_envadd (client, "", "interface", "%s",
+                                      client -> interface -> name);
                }
                if (client -> name)
-                       fprintf (scriptFile, "client=\"%s\"\n",
-                                client -> name);
-               fprintf (scriptFile, "export client\n");
-       }
-       if (medium) {
-               fprintf (scriptFile, "medium=\"%s\"\n", medium -> string);
-               fprintf (scriptFile, "export medium\n");
+                       client_envadd (client,
+                                      "", "client", "%s", client -> name);
+               if (medium)
+                       client_envadd (client,
+                                      "", "medium", "%s", medium -> string);
+
+               client_envadd (client, "", "reason", "%s", reason);
        }
-       fprintf (scriptFile, "reason=\"%s\"\n", reason);
-       fprintf (scriptFile, "export reason\n");
 }
 
 void script_write_params (client, prefix, lease)
@@ -2187,9 +2170,8 @@ void script_write_params (client, prefix, lease)
        pair *hash;
        char *s, *t;
 
-       fprintf (scriptFile, "%sip_address=\"%s\"\n",
-                prefix, piaddr (lease -> address));
-       fprintf (scriptFile, "export %sip_address\n", prefix);
+       client_envadd (client,
+                      prefix, "ip_address", "%s", piaddr (lease -> address));
 
        /* For the benefit of Linux (and operating systems which may
           have similar needs), compute the network address based on
@@ -2215,51 +2197,37 @@ void script_write_params (client, prefix, lease)
 
                        subnet = subnet_number (lease -> address, netmask);
                        if (subnet.len) {
-                               fprintf (scriptFile,
-                                        "%snetwork_number=\"%s\";\n",
-                                        prefix, piaddr (subnet));
-                               fprintf (scriptFile,
-                                        "export %snetwork_number\n", prefix);
-
-                               oc = lookup_option (&dhcp_universe,
-                                                   lease -> options,
-                                                   DHO_BROADCAST_ADDRESS);
-                               if (!oc ||
-                                   !(evaluate_option_cache
-                                     (&data, (struct packet *)0,
-                                      (struct lease *)0,
-                                      (struct option_state *)0,
-                                      lease -> options,
-                                      &global_scope, oc, MDL))) {
-                                       broadcast = broadcast_addr (subnet,
-                                                                   netmask);
-                                       if (broadcast.len) {
-                                               fprintf (scriptFile,
-                                                        "%s%s=\"%s\";\n",
-                                                        prefix,
-                                                        "broadcast_address",
-                                                        piaddr (broadcast));
-                                               fprintf (scriptFile,
-                                                        "export %s%s\n",
-                                                        prefix,
-                                                        "broadcast_address");
-                                       }
+                           client_envadd (client, prefix, "network_number",
+                                          "%s", piaddr (subnet));
+
+                           oc = lookup_option (&dhcp_universe,
+                                               lease -> options,
+                                               DHO_BROADCAST_ADDRESS);
+                           if (!oc ||
+                               !(evaluate_option_cache
+                                 (&data, (struct packet *)0,
+                                  (struct lease *)0,
+                                  (struct option_state *)0,
+                                  lease -> options,
+                                  &global_scope, oc, MDL))) {
+                               broadcast = broadcast_addr (subnet, netmask);
+                               if (broadcast.len) {
+                                   client_envadd (client,
+                                                  prefix, "broadcast_address",
+                                                  "%s", piaddr (subnet));
                                }
+                           }
                        }
                }
                data_string_forget (&data, MDL);
        }
 
-       if (lease -> filename) {
-               fprintf (scriptFile, "%sfilename=\"%s\";\n",
-                        prefix, lease -> filename);
-               fprintf (scriptFile, "export %sfilename\n", prefix);
-       }
-       if (lease -> server_name) {
-               fprintf (scriptFile, "%sserver_name=\"%s\";\n",
-                        prefix, lease -> server_name);
-               fprintf (scriptFile, "export %sserver_name\n", prefix);
-       }
+       if (lease -> filename)
+               client_envadd (client,
+                              prefix, "filename", "%s", lease -> filename);
+       if (lease -> server_name)
+               client_envadd (client, prefix, "server_name",
+                              "%s", lease -> server_name);
 
        execute_statements_in_scope ((struct packet *)0,
                                     (struct lease *)0, lease -> options,
@@ -2269,78 +2237,155 @@ void script_write_params (client, prefix, lease)
 
        hash = lease -> options -> universes [dhcp_universe.index];
        for (i = 0; i < OPTION_HASH_SIZE; i++) {
-               pair hp;
+           pair hp;
 
-               for (hp = hash [i]; hp; hp = hp -> cdr) {
-                       oc = (struct option_cache *)hp -> car;
+           for (hp = hash [i]; hp; hp = hp -> cdr) {
+               oc = (struct option_cache *)hp -> car;
 
-                       if (evaluate_option_cache (&data,
-                                                  (struct packet *)0,
-                                                  (struct lease *)0,
-                                                  (struct option_state *)0,
-                                                  lease -> options,
-                                                  &global_scope, oc, MDL)) {
-
-                               if (data.len) {
-                                       char *s = (dhcp_option_ev_name
-                                                  (oc -> option));
-                               
-                                       fprintf (scriptFile,
-                                                "%s%s=\"%s\"\n", prefix, s,
-                                                (pretty_print_option
-                                                 (oc -> option -> code,
-                                                  data.data, data.len,
-                                                  0, 0)));
-                                       fprintf (scriptFile,
-                                                "export %s%s\n", prefix, s);
-                               }
-                               data_string_forget (&data, MDL);
+               if (evaluate_option_cache (&data,
+                                          (struct packet *)0,
+                                          (struct lease *)0,
+                                          (struct option_state *)0,
+                                          lease -> options,
+                                          &global_scope, oc, MDL)) {
+                   if (data.len) {
+                       char name [256];
+                       if (dhcp_option_ev_name (name, sizeof name,
+                                                oc -> option)) {
+                           client_envadd (client, prefix, name, "%s",
+                                          (pretty_print_option
+                                           (oc -> option -> code,
+                                            data.data, data.len,
+                                            0, 0)));
+                           data_string_forget (&data, MDL);
                        }
+                   }
                }
+           }
        }
-       fprintf (scriptFile, "%sexpiry=\"%d\"\n",
-                prefix, (int)lease -> expiry); /* XXX */
-       fprintf (scriptFile, "export %sexpiry\n", prefix);
+       client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
 }
 
 int script_go (client)
        struct client_state *client;
 {
        int rval;
+       char *scriptName;
+       char *argv [2];
+       char **envp;
+       char *epp [3];
+       char reason [] = "REASON=NBI";
+       static char client_path [] = CLIENT_PATH;
+       int i;
+       struct string_list *sp, *next;
+       int pid, wpid, wstatus;
 
-       if (client)
-               fprintf (scriptFile, "%s\n",
-                        client -> config -> script_name);
-       else
-               fprintf (scriptFile, "%s\n",
-                        top_level_config.script_name);
-       fprintf (scriptFile, "exit $?\n");
-       fclose (scriptFile);
-       chmod (scriptName, 0700);
-       rval = system (scriptName);     
-       if (!save_scripts)
-               unlink (scriptName);
-       return rval;
+       if (client) {
+               scriptName = client -> config -> script_name;
+               envp = dmalloc ((client -> envc + 2) * sizeof (char *),
+                               MDL);
+               if (!envp) {
+                       log_error ("No memory for client script environment.");
+                       return 0;
+               }
+               i = 0;
+               for (sp = client -> env; sp; sp = sp -> next) {
+                       envp [i++] = sp -> string;
+               }
+               envp [i++] = client_path;
+               envp [i] = (char *)0;
+       } else {
+               scriptName = top_level_config.script_name;
+               epp [0] = reason;
+               epp [1] = client_path;
+               epp [2] = (char *)0;
+               envp = epp;
+       }
+
+       argv [0] = scriptName;
+       argv [1] = (char *)0;
+
+       pid = fork ();
+       if (pid < 0) {
+               log_error ("fork: %m");
+               wstatus = 0;
+       } else if (pid) {
+               do {
+                       wpid = wait (&wstatus);
+               } while (wpid != pid && wpid > 0);
+               if (wpid < 0) {
+                       log_error ("wait: %m");
+                       wstatus = 0;
+               }
+       } else {
+               execve (scriptName, argv, envp);
+               log_error ("execve (%s, ...): %m", scriptName);
+               exit (0);
+       }
+
+       if (client) {
+               for (sp = client -> env; sp; sp = next) {
+                       next = sp -> next;
+                       dfree (sp, MDL);
+               }
+               client -> env = (struct string_list *)0;
+               client -> envc = 0;
+               dfree (envp, MDL);
+       }
+       return wstatus & 0xff;
 }
 
-char *dhcp_option_ev_name (option)
+void client_envadd (struct client_state *client,
+                   const char *prefix, const char *name, const char *fmt, ...)
+{
+       char spbuf [1024];
+       char *s;
+       unsigned len, i;
+       struct string_list *val;
+       va_list list;
+
+       va_start (list, fmt);
+       len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
+       va_end (list);
+
+       val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
+                      len + sizeof *val, MDL);
+       if (!val)
+               return;
+       s = val -> string;
+       strcpy (s, prefix);
+       strcat (s, name);
+       s += strlen (s);
+       *s++ = '=';
+       if (len >= sizeof spbuf) {
+               va_start (list, fmt);
+               vsnprintf (s, len + 1, fmt, list);
+               va_end (list);
+       } else
+               strcpy (s, spbuf);
+       val -> next = client -> env;
+       client -> env = val;
+       client -> envc++;
+}
+
+int dhcp_option_ev_name (buf, buflen, option)
+       char *buf;
+       unsigned buflen;
        struct option *option;
 {
-       static char evbuf [256];
        int i;
 
-       if (strlen (option -> name) + 1 > sizeof evbuf)
-               log_fatal ("option %s name is larger than static buffer.",
-                          option -> name);
        for (i = 0; option -> name [i]; i++) {
+               if (i + 1 == buflen)
+                       return 0;
                if (option -> name [i] == '-')
-                       evbuf [i] = '_';
+                       buf [i] = '_';
                else
-                       evbuf [i] = option -> name [i];
+                       buf [i] = option -> name [i];
        }
 
-       evbuf [i] = 0;
-       return evbuf;
+       buf [i] = 0;
+       return 1;
 }
 
 void go_daemon ()
index 93784c576a2a80363dbe18024f0747c105688b72..5a0bdc28ae395e1920a95e0a53f89e1271dec962 100644 (file)
@@ -665,7 +665,7 @@ struct client_config {
        u_int32_t requested_lease;      /* Requested lease time, if user
                                           doesn't configure one. */
        struct string_list *media;      /* Possible network media values. */
-       const char *script_name;        /* Name of config script. */
+       char *script_name;              /* Name of config script. */
        enum policy bootp_policy;
                                        /* Ignore, accept or prefer BOOTP
                                           responses. */
@@ -708,6 +708,8 @@ struct client_state {
        struct iaddr requested_address;     /* Address we would like to get. */
 
        struct client_config *config;               /* Client configuration. */
+       struct string_list *env;               /* Client script environment. */
+       int envc;                       /* Number of entries in environment. */
 };
 
 /* Information about each network interface. */
@@ -1636,13 +1638,16 @@ void destroy_client_lease PROTO ((struct client_lease *));
 void rewrite_client_leases PROTO ((void));
 int write_client_lease PROTO ((struct client_state *,
                               struct client_lease *, int, int));
-char *dhcp_option_ev_name PROTO ((struct option *));
+int dhcp_option_ev_name (char *, size_t, struct option *);
 
 void script_init PROTO ((struct client_state *, const char *,
                         struct string_list *));
 void script_write_params PROTO ((struct client_state *,
                                 const char *, struct client_lease *));
 int script_go PROTO ((struct client_state *));
+void client_envadd (struct client_state *,
+                   const char *, const char *, const char *, ...)
+       __attribute__((__format__(__printf__,4,5)));
 
 struct client_lease *packet_to_lease PROTO ((struct packet *));
 void go_daemon PROTO ((void));