diff options
author | Ted Lemon <source@isc.org> | 2000-07-20 00:53:24 +0000 |
---|---|---|
committer | Ted Lemon <source@isc.org> | 2000-07-20 00:53:24 +0000 |
commit | 32a47563331e1c278d9b6d284857dd24326ee202 (patch) | |
tree | fcf223879d48113b70f356c33583e42782ae05b2 | |
parent | cfa7212d267350bcc2b2e8de334ed8aaeb3598be (diff) | |
download | isc-dhcp-32a47563331e1c278d9b6d284857dd24326ee202.tar.gz |
Initialize the environment rather than using temporary client scripts.
-rw-r--r-- | Makefile.conf | 1 | ||||
-rw-r--r-- | client/Makefile.dist | 3 | ||||
-rw-r--r-- | client/clparse.c | 6 | ||||
-rw-r--r-- | client/dhclient.c | 297 | ||||
-rw-r--r-- | includes/dhcpd.h | 9 |
5 files changed, 185 insertions, 131 deletions
diff --git a/Makefile.conf b/Makefile.conf index 576513ca..3d601fd5 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -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 = diff --git a/client/Makefile.dist b/client/Makefile.dist index 18322410..3e64558e 100644 --- a/client/Makefile.dist +++ b/client/Makefile.dist @@ -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) diff --git a/client/clparse.c b/client/clparse.c index 0dacac61..48ffa7d1 100644 --- a/client/clparse.c +++ b/client/clparse.c @@ -43,13 +43,15 @@ #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; diff --git a/client/dhclient.c b/client/dhclient.c index 9b794006..de006233 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -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 () diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 93784c57..5a0bdc28 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -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)); |