Apply by doing: cd /usr/src patch -p0 < 012_dhclient.patch cd usr.sbin/dhcp/ make obj && make cleandir && make depend && make && make install Finally, kill and restart dhclient. No configuration changes are necessary. ========================================================================== --- usr.sbin/dhcp/dhclient/dhclient.c.orig Sun Jun 25 03:53:25 2000 +++ usr.sbin/dhcp/dhclient/dhclient.c Sun Jun 25 03:53:50 2000 @@ -91,7 +91,6 @@ u_int16_t remote_port; int log_priority; int no_daemon; -int save_scripts; int onetry; static void usage PROTO ((void)); @@ -124,8 +123,6 @@ ntohs (local_port)); } else if (!strcmp (argv [i], "-d")) { no_daemon = 1; - } else if (!strcmp (argv [i], "-D")) { - save_scripts = 1; } else if (!strcmp (argv [i], "-1")) { onetry = 1; } else if (argv [i][0] == '-') { @@ -1771,47 +1768,76 @@ /* Variables holding name of script and file pointer for writing to script. Needless to say, this is not reentrant - only one script can be invoked at a time. */ -char scriptName [256]; -FILE *scriptFile; +char **scriptEnv = NULL; +int scriptEnvsize = 0; + +void script_set_env (name, value) + char *name; + char *value; +{ + int i, namelen; + + namelen = strlen(name); + + for (i = 0; scriptEnv[i]; i++) { + if (strncmp(scriptEnv[i], name, namelen) == 0 && + scriptEnv[i][namelen] == '=') + break; + } + if (scriptEnv[i]) { + /* Reuse the slot. */ + free(scriptEnv[i]); + } else { + /* New variable. Expand if necessary. */ + if (i >= scriptEnvsize - 1) { + scriptEnvsize += 50; + scriptEnv = realloc(scriptEnv, scriptEnvsize); + if (scriptEnv == NULL) + error("script_set_env: no memory for variable"); + } + /* Need to set the NULL pointer at end of array beyond + the new slot. */ + scriptEnv[i + 1] = NULL; + } + /* Allocate space and format the variable in the appropriate slot. */ + scriptEnv[i] = malloc(strlen(name) + 1 + strlen(value) + 1); + if (scriptEnv[i] == NULL) + error("script_set_env: no memory for variable assignment"); + + snprintf(scriptEnv[i], strlen(name) + 1 + strlen(value) + 1, + "%s=%s", name, value); +} + +void script_flush_env() +{ + int i; + + for (i = 0; scriptEnv[i]; i++) { + free(scriptEnv[i]); + scriptEnv[i] = NULL; + } +} void script_init (ip, reason, medium) struct interface_info *ip; char *reason; struct string_list *medium; { - int fd; -#ifndef HAVE_MKSTEMP + scriptEnvsize = 100; + scriptEnv = malloc(scriptEnvsize * sizeof(char *)); - do { -#endif - strcpy (scriptName, "/tmp/dcsXXXXXX"); -#ifdef HAVE_MKSTEMP - fd = mkstemp (scriptName); -#else - mktemp (scriptName); - fd = creat (scriptName, 0600); - } while (fd < 0); -#endif + if (scriptEnv == NULL) + error ("script_init: no memory for environment initialization"); + + scriptEnv[0] = NULL; -#ifdef HAVE_MKSTEMP - if (fd == -1) - error ("can't write script file: %m"); -#endif - - scriptFile = fdopen (fd, "w"); - if (!scriptFile) - error ("can't write script file: %m"); - fprintf (scriptFile, "#!/bin/sh\n\n"); if (ip) { - fprintf (scriptFile, "interface=\"%s\"\n", ip -> name); - fprintf (scriptFile, "export interface\n"); + script_set_env ("interface", ip -> name); } if (medium) { - fprintf (scriptFile, "medium=\"%s\"\n", medium -> string); - fprintf (scriptFile, "export medium\n"); + script_set_env ("medium", medium -> string); } - fprintf (scriptFile, "reason=\"%s\"\n", reason); - fprintf (scriptFile, "export reason\n"); + script_set_env ("reason", reason); } void script_write_params (ip, prefix, lease) @@ -1821,11 +1847,11 @@ { int i; u_int8_t dbuf [1500]; + char name[1024], value[1024]; int len; - fprintf (scriptFile, "%sip_address=\"%s\"\n", - prefix, piaddr (lease -> address)); - fprintf (scriptFile, "export %sip_address\n", prefix); + snprintf (name, sizeof(name), "%sip_address", prefix); + script_set_env (name, piaddr (lease -> address)); /* For the benefit of Linux (and operating systems which may have similar needs), compute the network address based on @@ -1843,42 +1869,37 @@ lease -> options [DHO_SUBNET_MASK].data, lease -> options [DHO_SUBNET_MASK].len); netmask.len = lease -> options [DHO_SUBNET_MASK].len; - + 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); - + snprintf (name, sizeof(name), "%snetwork_number", + prefix); + script_set_env (name, piaddr (subnet)); + if (!lease -> options [DHO_BROADCAST_ADDRESS].len) { 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"); + snprintf (name, sizeof(name), + "%sbroadcast_address", + prefix); + script_set_env (name, + piaddr (broadcast)); } } } } - + if (lease -> filename) { - fprintf (scriptFile, "%sfilename=\"%s\";\n", - prefix, lease -> filename); - fprintf (scriptFile, "export %sfilename\n", prefix); + snprintf (name, sizeof(name), "%sfilename", prefix); + script_set_env (name, lease -> filename); } if (lease -> server_name) { - fprintf (scriptFile, "%sserver_name=\"%s\";\n", - prefix, lease -> server_name); - fprintf (scriptFile, "export %sserver_name\n", prefix); + snprintf (name, sizeof(name), "%sserver_name", prefix); + script_set_env (name, lease -> server_name); } for (i = 0; i < 256; i++) { u_int8_t *dp; - + if (ip -> client -> config -> defaults [i].len) { if (lease -> options [i].len) { switch (ip -> client -> @@ -1948,35 +1969,54 @@ } if (len) { char *s = dhcp_option_ev_name (&dhcp_options [i]); - - fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s, - pretty_print_option (i, dp, len, 0, 0)); - fprintf (scriptFile, "export %s%s\n", prefix, s); + + snprintf (name, sizeof(name), "%s%s", prefix, s); + script_set_env (name, pretty_print_option (i, dp, len, 0, 0)); } } - fprintf (scriptFile, "%sexpiry=\"%d\"\n", - prefix, (int)lease -> expiry); /* XXX */ - fprintf (scriptFile, "export %sexpiry\n", prefix); + snprintf (name, sizeof(name), "%sexpiry", prefix); + snprintf (value, sizeof(value), "%d", (int)lease -> expiry); /* XXX */ + script_set_env (name, value); } int script_go (ip) struct interface_info *ip; { - int rval; + char *p, *script_name, *script_argv[2]; + pid_t pid, wait_pid; + int status; if (ip) - fprintf (scriptFile, "%s\n", - ip -> client -> config -> script_name); + script_name = ip -> 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; + script_name = top_level_config.script_name; + + if ((p = strrchr(script_name, '/')) != NULL) + p++; + else + p = script_name; + + script_argv[0] = p; + script_argv[1] = NULL; + + if ((pid = fork()) < 0) + error("Can't fork script: %m"); + + if (pid == 0) { + execve(script_name, script_argv, scriptEnv); + error("script_go: exec: %m"); + } + script_flush_env(); + + wait_pid = wait((int *) &status); + + if (wait_pid != -1) { + if (wait_pid != pid) + error ("got wrong pid"); + if (WIFEXITED(status) || WIFSIGNALED(status)) + return (WEXITSTATUS(status)); + } + return (-1); } char *dhcp_option_ev_name (option) --- usr.sbin/dhcp/dhclient/scripts/dhclient-script.orig Sun Jun 25 03:52:55 2000 +++ usr.sbin/dhcp/dhclient/scripts/dhclient-script Sun Jun 25 03:55:56 2000 @@ -3,98 +3,107 @@ # $OpenBSD: dhclient-script,v 1.5 2000/04/20 08:14:21 angelos Exp $ # -if [ x$new_network_number != x ]; then - echo New Network Number: $new_network_number +if [ "x$new_network_number" != "x" ]; then + echo "New Network Number: $new_network_number" fi -if [ x$new_broadcast_address != x ]; then - echo New Broadcast Address: $new_broadcast_address +if [ "x$new_broadcast_address" != "x" ]; then + echo "New Broadcast Address: $new_broadcast_address" new_broadcast_arg="broadcast $new_broadcast_address" fi -if [ x$old_broadcast_address != x ]; then +if [ "x$old_broadcast_address" != "x" ]; then old_broadcast_arg="broadcast $old_broadcast_address" fi -if [ x$new_subnet_mask != x ]; then +if [ "x$new_subnet_mask" != "x" ]; then new_netmask_arg="netmask $new_subnet_mask" fi -if [ x$old_subnet_mask != x ]; then +if [ "x$old_subnet_mask" != "x" ]; then old_netmask_arg="netmask $old_subnet_mask" fi -if [ x$alias_subnet_mask != x ]; then +if [ "x$alias_subnet_mask" != "x" ]; then alias_subnet_arg="netmask $alias_subnet_mask" fi -if [ x$reason = xMEDIUM ]; then - ifconfig $interface $medium - ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1 +if [ "x$reason" = "xMEDIUM" ]; then + ifconfig "$interface" "$medium" + ifconfig "$interface" inet -alias 0.0.0.0 "$medium" >/dev/null 2>&1 sleep 1 exit 0 fi -if [ x$reason = xPREINIT ]; then - if [ x$alias_ip_address != x ]; then - ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 - route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 +if [ "x$reason" = "xPREINIT" ]; then + if [ "x$alias_ip_address" != "x" ]; then + ifconfig "$interface" inet -alias "$alias_ip_address" > /dev/null 2>&1 + route delete "$alias_ip_address" 127.0.0.1 > /dev/null 2>&1 fi - ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + ifconfig "$interface" inet 0.0.0.0 netmask 0.0.0.0 \ broadcast 255.255.255.255 up exit 0 fi -if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then +if [ "x$reason" = "xARPCHECK" ] || [ "x$reason" = "xARPSEND" ]; then exit 0; fi -if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ - [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then - if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ - [ x$alias_ip_address != x$old_ip_address ]; then - ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 - route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 - fi - if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then - ifconfig $interface inet -alias $old_ip_address $medium - route delete $old_ip_address 127.1 >/dev/null 2>&1 - for router in $old_routers; do - route delete default $router >/dev/null 2>&1 +if [ "x$reason" = "xBOUND" ] || [ "x$reason" = "xRENEW" ] || \ + [ "x$reason" = "xREBIND" ] || [ "x$reason" = "xREBOOT" ]; then + if [ "x$old_ip_address" != "x" ] && [ "x$alias_ip_address" != "x" ] && \ + [ "x$alias_ip_address" != "x$old_ip_address" ]; then + ifconfig "$interface" inet -alias "$alias_ip_address" > /dev/null 2>&1 + route delete "$alias_ip_address" 127.0.0.1 > /dev/null 2>&1 + fi + if [ "x$old_ip_address" != "x" ] && [ "x$old_ip_address" != "x$new_ip_address" ]; then + if [ "x$medium" != "x" ]; then + ifconfig "$interface" inet -alias "$old_ip_address" "$medium" + else + ifconfig "$interface" inet -alias "$old_ip_address" + fi + route delete "$old_ip_address" 127.1 >/dev/null 2>&1 + for router in "$old_routers"; do + route delete default "$router" >/dev/null 2>&1 done if [ "$old_static_routes" != "" ]; then set $old_static_routes while [ $# -gt 1 ]; do - route delete $1 $2 + route delete "$1" "$2" shift; shift done fi arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh fi - if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ - [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then - ifconfig $interface inet $new_ip_address $new_netmask_arg \ - $new_broadcast_arg $medium - route add $new_ip_address 127.1 >/dev/null 2>&1 - for router in $new_routers; do - route add default $router >/dev/null 2>&1 + if [ "x$old_ip_address" = "x" ] || [ "x$old_ip_address" != "x$new_ip_address" ] || \ + [ "x$reason" = "xBOUND" ] || [ "x$reason" = "xREBOOT" ]; then + if [ "x$medium" != "x" ]; then + ifconfig "$interface" inet "$new_ip_address" $new_netmask_arg \ + $new_broadcast_arg "$medium" + else + ifconfig "$interface" inet "$new_ip_address" $new_netmask_arg \ + $new_broadcast_arg + fi + route add "$new_ip_address" 127.1 >/dev/null 2>&1 + for router in "$new_routers"; do + route add default "$router" >/dev/null 2>&1 done if [ "$new_static_routes" != "" ]; then - set $new_static_routes + set "$new_static_routes" while [ $# -gt 1 ]; do - route add $1 $2 + route add "$1" "$2" shift; shift done fi fi - if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + if [ "x$new_ip_address" != "x$alias_ip_address" ] && [ "x$alias_ip_address" != "x" ]; then - ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg - route add $alias_ip_address 127.0.0.1 + ifconfig "$interface" inet alias "$alias_ip_address" $alias_subnet_arg + route add "$alias_ip_address" 127.0.0.1 fi - if [ x$new_domain_name != x ]; + if [ "x$new_domain_name" != "x" ]; then if [ -n "$new_domain_name_servers" ]; then - echo search $new_domain_name >/etc/resolv.conf - for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo "search $new_domain_name" >/etc/resolv.conf + for nameserver in "$new_domain_name_servers"; do + echo "nameserver $nameserver" >>/etc/resolv.conf done if [ -f /etc/resolv.conf.tail ]; then cat /etc/resolv.conf.tail >>/etc/resolv.conf @@ -104,66 +113,75 @@ fi fi -if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then - if [ x$alias_ip_address != x ]; then - ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 - route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 - fi - if [ x$old_ip_address != x ]; then - ifconfig $interface inet -alias $old_ip_address $medium - route delete $old_ip_address 127.1 >/dev/null 2>&1 - for router in $old_routers; do - route delete default $router >/dev/null 2>&1 +if [ "x$reason" = "xEXPIRE" ] || [ "x$reason" = "xFAIL" ]; then + if [ "x$alias_ip_address" != "x" ]; then + ifconfig "$interface" inet -alias "$alias_ip_address" > /dev/null 2>&1 + route delete "$alias_ip_address" 127.0.0.1 > /dev/null 2>&1 + fi + if [ "x$old_ip_address" != "x" ]; then + if [ "x$medium" != "x" ]; then + ifconfig "$interface" inet -alias "$old_ip_address" "$medium" + else + ifconfig "$interface" inet -alias "$old_ip_address" + fi + route delete "$old_ip_address" 127.1 >/dev/null 2>&1 + for router in "$old_routers"; do + route delete default "$router" >/dev/null 2>&1 done if [ "$old_static_routes" != "" ]; then - set $old_static_routes + set "$old_static_routes" while [ $# -gt 1 ]; do - route delete $1 $2 + route delete "$1" "$2" shift; shift done fi arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ |sh >/dev/null 2>&1 fi - if [ x$alias_ip_address != x ]; then - ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg - route add $alias_ip_address 127.0.0.1 + if [ "x$alias_ip_address" != "x" ]; then + ifconfig "$interface" inet alias "$alias_ip_address" $alias_subnet_arg + route add "$alias_ip_address" 127.0.0.1 fi exit 0 fi -if [ x$reason = xTIMEOUT ]; then - if [ x$alias_ip_address != x ]; then - ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 - route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 +if [ "x$reason" = "xTIMEOUT" ]; then + if [ "x$alias_ip_address" != "x" ]; then + ifconfig "$interface" inet -alias "$alias_ip_address" > /dev/null 2>&1 + route delete "$alias_ip_address" 127.0.0.1 > /dev/null 2>&1 + fi + if [ "x$medium" != "x" ]; then + ifconfig "$interface" inet "$new_ip_address" $new_netmask_arg \ + $new_broadcast_arg "$medium" + else + ifconfig "$interface" inet "$new_ip_address" $new_netmask_arg \ + $new_broadcast_arg fi - ifconfig $interface inet $new_ip_address $new_netmask_arg \ - $new_broadcast_arg $medium sleep 1 if [ "$new_routers" != "" ]; then - set $new_routers - if ping -q -c 1 -w 1 $1; then - if [ x$new_ip_address != x$alias_ip_address ] && \ - [ x$alias_ip_address != x ]; then - ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg - route add $alias_ip_address 127.0.0.1 + set "$new_routers" + if ping -q -c 1 -w 1 "$1"; then + if [ "x$new_ip_address" != "x$alias_ip_address" ] && \ + [ "x$alias_ip_address" != "x" ]; then + ifconfig "$interface" inet alias "$alias_ip_address" $alias_subnet_arg + route add "$alias_ip_address" 127.0.0.1 fi - route add $new_ip_address 127.1 >/dev/null 2>&1 - for router in $new_routers; do - route add default $router >/dev/null 2>&1 + route add "$new_ip_address" 127.1 >/dev/null 2>&1 + for router in "$new_routers"; do + route add default "$router" >/dev/null 2>&1 done if [ "$new_static_routes" != "" ]; then - set $new_static_routes + set "$new_static_routes" while [ $# -gt 1 ]; do - route add $1 $2 + route add "$1" "$2" shift; shift done fi if [ "$new_domain_name" != "" ]; then if [ -n "$new_domain_name_servers" ]; then - echo search $new_domain_name >/etc/resolv.conf.std - for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf.std + echo "search $new_domain_name" >/etc/resolv.conf.std + for nameserver in "$new_domain_name_servers"; do + echo "nameserver $nameserver" >>/etc/resolv.conf.std done if [ -f /etc/resolv.conf.tail ]; then cat /etc/resolv.conf.tail >>/etc/resolv.conf.std @@ -177,14 +195,18 @@ fi fi fi - ifconfig $interface inet -alias $new_ip_address $medium - for router in $old_routers; do - route delete default $router >/dev/null 2>&1 + if [ "x$medium" != "x" ]; then + ifconfig "$interface" inet -alias "$new_ip_address" "$medium" + else + ifconfig "$interface" inet -alias "$new_ip_address" + fi + for router in "$old_routers"; do + route delete default "$router" >/dev/null 2>&1 done if [ "$old_static_routes" != "" ]; then - set $old_static_routes + set "$old_static_routes" while [ $# -gt 1 ]; do - route delete $1 $2 + route delete "$1" "$2" shift; shift done fi