Print this page
    
OS-4741 Add support for multiple addresses & IPv6 to lx-branded zones
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libdhcpagent/common/dhcpagent_util.c
          +++ new/usr/src/lib/libdhcpagent/common/dhcpagent_util.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  #include <sys/types.h>
  27   27  #include <sys/ctfs.h>
  28   28  #include <sys/contract/process.h>
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
  29   29  #include <sys/socket.h>
  30   30  #include <sys/time.h>
  31   31  #include <sys/wait.h>
  32   32  #include <fcntl.h>
  33   33  #include <libcontract.h>
  34   34  #include <libcontract_priv.h>
  35   35  #include <unistd.h>
  36   36  #include <stdio.h>
  37   37  #include <stdlib.h>
  38   38  #include <string.h>
       39 +#include <zone.h>
  39   40  
  40   41  #include "dhcpagent_ipc.h"
  41   42  #include "dhcpagent_util.h"
  42   43  
  43   44  /*
  44   45   * Strings returned by dhcp_status_hdr_string() and
  45   46   * dhcp_status_reply_to_string(). The first define is the header line, and
  46   47   * the second defines line printed underneath.
  47   48   * The spacing of fields must match.
  48   49   */
  49   50  #define DHCP_STATUS_HDR "Interface  State         Sent  Recv  Declined  Flags\n"
  50   51  #define DHCP_STATUS_STR "%-10s %-12s %5d %5d %9d  "
  51   52  
  52   53  static const char *time_to_string(time_t abs_time);
  53   54  
  54   55  /*
  55   56   * dhcp_state_to_string(): given a state, provides the state's name
  56   57   *
  57   58   *    input: DHCPSTATE: the state to get the name of
  58   59   *   output: const char *: the state's name
  59   60   */
  60   61  
  61   62  const char *
  62   63  dhcp_state_to_string(DHCPSTATE state)
  63   64  {
  64   65          const char *states[] = {
  65   66                  "INIT",
  66   67                  "SELECTING",
  67   68                  "REQUESTING",
  68   69                  "PRE_BOUND",
  69   70                  "BOUND",
  70   71                  "RENEWING",
  71   72                  "REBINDING",
  72   73                  "INFORMATION",
  73   74                  "INIT_REBOOT",
  74   75                  "ADOPTING",
  75   76                  "INFORM_SENT",
  76   77                  "DECLINING",
  77   78                  "RELEASING"
  78   79          };
  79   80  
  80   81          if (state < 0 || state >= DHCP_NSTATES)
  81   82                  return ("<unknown>");
  82   83  
  83   84          return (states[state]);
  84   85  }
  85   86  
  86   87  static int
  87   88  init_template(void)
  88   89  {
  89   90          int fd;
  90   91          int err = 0;
  91   92  
  92   93          fd = open64(CTFS_ROOT "/process/template", O_RDWR);
  93   94          if (fd == -1)
  94   95                  return (-1);
  95   96  
  96   97          /*
  97   98           * Deliver no events, don't inherit, and allow it to be orphaned.
  98   99           */
  99  100          err |= ct_tmpl_set_critical(fd, 0);
 100  101          err |= ct_tmpl_set_informative(fd, 0);
 101  102          err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
 102  103          err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
 103  104          if (err != 0 || ct_tmpl_activate(fd) != 0) {
 104  105                  (void) close(fd);
 105  106                  return (-1);
 106  107          }
 107  108  
 108  109          return (fd);
 109  110  }
 110  111  
 111  112  /*
 112  113   * dhcp_start_agent(): starts the agent if not already running
 113  114   *
 114  115   *   input: int: number of seconds to wait for agent to start (-1 is forever)
 115  116   *  output: int: 0 on success, -1 on failure
 116  117   */
 117  118  
  
    | 
      ↓ open down ↓ | 
    69 lines elided | 
    
      ↑ open up ↑ | 
  
 118  119  int
 119  120  dhcp_start_agent(int timeout)
 120  121  {
 121  122          int                     error;
 122  123          time_t                  start_time = time(NULL);
 123  124          dhcp_ipc_request_t      *request;
 124  125          dhcp_ipc_reply_t        *reply;
 125  126          int                     ctfd;
 126  127          pid_t                   childpid;
 127  128          ctid_t                  ct;
      129 +        char                    dhcpcmd[MAXPATHLEN];
      130 +        const char              *zroot = zone_get_nroot();
 128  131  
      132 +        /* Prepend the root of the native code in the brand to the command */
      133 +        (void) snprintf(dhcpcmd, sizeof (dhcpcmd), "%s%s", zroot != NULL ?
      134 +            zroot : "", DHCP_AGENT_PATH);
      135 +
 129  136          /*
 130  137           * just send a dummy request to the agent to find out if it's
 131  138           * up.  we do this instead of directly connecting to it since
 132  139           * we want to make sure we follow its IPC conventions
 133  140           * (otherwise, it will log warnings to syslog).
 134  141           */
 135  142  
 136  143          request = dhcp_ipc_alloc_request(DHCP_PING, "", NULL, 0,
 137  144              DHCP_TYPE_NONE);
 138  145          if (request == NULL)
 139  146                  return (-1);
 140  147  
 141  148          error = dhcp_ipc_make_request(request, &reply, 0);
 142  149          if (error == 0) {
 143  150                  free(reply);
 144  151                  free(request);
 145  152                  return (0);
 146  153          }
 147  154          if (error != DHCP_IPC_E_CONNECT)
 148  155                  goto fail;
 149  156  
 150  157          if ((ctfd = init_template()) == -1)
 151  158                  goto fail;
 152  159  
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
 153  160          childpid = fork();
 154  161  
 155  162          (void) ct_tmpl_clear(ctfd);
 156  163          (void) close(ctfd);
 157  164  
 158  165          switch (childpid) {
 159  166          case -1:
 160  167                  goto fail;
 161  168  
 162  169          case  0:
 163      -                (void) execl(DHCP_AGENT_PATH, DHCP_AGENT_PATH, (char *)0);
      170 +                (void) execl(dhcpcmd, dhcpcmd, (char *)0);
 164  171                  _exit(EXIT_FAILURE);
 165  172  
 166  173          default:
 167  174                  break;
 168  175          }
 169  176  
 170  177          /* wait for the daemon to run and then abandon the contract */
 171  178          (void) waitpid(childpid, NULL, 0);
 172  179  
 173  180          if (contract_latest(&ct) != -1)
 174  181                  (void) contract_abandon_id(ct);
 175  182  
 176  183          while ((timeout != -1) && (time(NULL) - start_time < timeout)) {
 177  184                  error = dhcp_ipc_make_request(request, &reply, 0);
 178  185                  if (error == 0) {
 179  186                          free(reply);
 180  187                          free(request);
 181  188                          return (0);
 182  189                  } else if (error != DHCP_IPC_E_CONNECT)
 183  190                          break;
 184  191                  (void) sleep(1);
 185  192          }
 186  193  
 187  194  fail:
 188  195          free(request);
 189  196          return (-1);
 190  197  }
 191  198  
 192  199  /*
 193  200   * dhcp_status_hdr_string(): Return a string suitable to use as the header
 194  201   *                           when printing DHCP_STATUS reply.
 195  202   *  output: const char *: newline terminated printable string
 196  203   */
 197  204  const char *
 198  205  dhcp_status_hdr_string(void)
 199  206  {
 200  207          return (DHCP_STATUS_HDR);
 201  208  }
 202  209  
 203  210  /*
 204  211   * time_to_string(): Utility routine for printing time
 205  212   *
 206  213   *   input: time_t *: time_t to stringify
 207  214   *  output: const char *: printable time
 208  215   */
 209  216  static const char *
 210  217  time_to_string(time_t abs_time)
 211  218  {
 212  219          static char time_buf[24];
 213  220          time_t tm = abs_time;
 214  221  
 215  222          if (tm == DHCP_PERM)
 216  223                  return ("Never");
 217  224  
 218  225          if (strftime(time_buf, sizeof (time_buf), "%m/%d/%Y %R",
 219  226              localtime(&tm)) == 0)
 220  227                  return ("<unknown>");
 221  228  
 222  229          return (time_buf);
 223  230  }
 224  231  
 225  232  /*
 226  233   * dhcp_status_reply_to_string(): Return DHCP IPC reply of type DHCP_STATUS
 227  234   *                                as a printable string
 228  235   *
 229  236   *   input: dhcp_reply_t *: contains the status structure to print
 230  237   *  output: const char *: newline terminated printable string
 231  238   */
 232  239  const char *
 233  240  dhcp_status_reply_to_string(dhcp_ipc_reply_t *reply)
 234  241  {
 235  242          static char str[1024];
 236  243          size_t reply_size;
 237  244          dhcp_status_t *status;
 238  245  
 239  246          status = dhcp_ipc_get_data(reply, &reply_size, NULL);
 240  247          if (reply_size < DHCP_STATUS_VER1_SIZE)
 241  248                  return ("<Internal error: status msg size>\n");
 242  249  
 243  250          (void) snprintf(str, sizeof (str), DHCP_STATUS_STR,
 244  251              status->if_name, dhcp_state_to_string(status->if_state),
 245  252              status->if_sent, status->if_recv, status->if_bad_offers);
 246  253  
 247  254          if (status->if_dflags & DHCP_IF_PRIMARY)
 248  255                  (void) strlcat(str, "[PRIMARY] ", sizeof (str));
 249  256  
 250  257          if (status->if_dflags & DHCP_IF_BOOTP)
 251  258                  (void) strlcat(str, "[BOOTP] ", sizeof (str));
 252  259  
 253  260          if (status->if_dflags & DHCP_IF_FAILED)
 254  261                  (void) strlcat(str, "[FAILED] ", sizeof (str));
 255  262  
 256  263          if (status->if_dflags & DHCP_IF_BUSY)
 257  264                  (void) strlcat(str, "[BUSY] ", sizeof (str));
 258  265  
 259  266          if (status->if_dflags & DHCP_IF_V6)
 260  267                  (void) strlcat(str, "[V6] ", sizeof (str));
 261  268  
 262  269          (void) strlcat(str, "\n", sizeof (str));
 263  270  
 264  271          switch (status->if_state) {
 265  272          case BOUND:
 266  273          case RENEWING:
 267  274          case REBINDING:
 268  275                  break;
 269  276          default:
 270  277                  return (str);
 271  278          }
 272  279  
 273  280          (void) strlcat(str, "(Began, Expires, Renew) = (", sizeof (str));
 274  281          (void) strlcat(str, time_to_string(status->if_began), sizeof (str));
 275  282          (void) strlcat(str, ", ", sizeof (str));
 276  283          (void) strlcat(str, time_to_string(status->if_lease), sizeof (str));
 277  284          (void) strlcat(str, ", ", sizeof (str));
 278  285          (void) strlcat(str, time_to_string(status->if_t1), sizeof (str));
 279  286          (void) strlcat(str, ")\n", sizeof (str));
 280  287          return (str);
 281  288  }
  
    | 
      ↓ open down ↓ | 
    108 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX