Changeset 573b1982 in rtems-libbsd for rtemsbsd/rtems/rtems-bsd-rc-conf-net.c


Ignore:
Timestamp:
Jun 29, 2016, 11:19:52 PM (4 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
a8f29d695e152575479ad1a97fa354f661bebd4d, freebsd-9.3, d892051f37c2c4ad7f345f6a817ea3d38e56a431
Children:
dc5b267
Parents:
912b685
Message:

Add DHCP support to rc.conf.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • rtemsbsd/rtems/rtems-bsd-rc-conf-net.c

    r912b685 r573b1982  
    4040
    4141#include <ifaddrs.h>
     42#include <net/if.h>
     43#include <net/route.h>
     44#include <netinet/in.h>
     45#include <sys/socket.h>
    4246
    4347#include <errno.h>
     
    4549#include <stdio.h>
    4650#include <stdlib.h>
     51#include <sys/stat.h>
    4752#include <unistd.h>
    4853
     
    5257#include <machine/rtems-bsd-commands.h>
    5358#include <machine/rtems-bsd-rc-conf-services.h>
     59
     60#include <rtems/rtems-routes.h>
    5461
    5562/*
     
    336343}
    337344
    338 /*
    339  * defaultroute_delay
    340  *
    341  * eg defaultroute=120
    342  *
    343  * See 'man rc.conf(5)' on FreeBSD.
    344  */
    345 static int
    346 defaultroute_delay(rtems_bsd_rc_conf* rc_conf,
    347                    int                argc,
    348                    const char**       argv)
    349 {
    350   int   value;
    351   char* end = NULL;
    352 
    353   if (argc != 2) {
    354     errno = EINVAL;
    355     return -1;
    356   }
    357 
    358   value = strtol(argv[1], &end, 10);
    359 
    360   if (end == NULL) {
    361       const char* args[] = {
    362         "defaultrouter_delay", argv[1], NULL
    363     };
    364 
    365     rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 2, args);
    366 
    367     defaultroute_delay_secs = value;
    368   }
    369   else {
    370     errno = EINVAL;
    371     return -1;
    372   }
    373 
    374   return 0;
    375 }
    376 
    377345static int
    378346show_interfaces(const char* msg, struct ifaddrs* ifap)
     
    381349
    382350  fprintf(stdout, msg);
     351
     352  /*
     353   * Always have lo0 first.
     354   */
    383355
    384356  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     
    401373
    402374static int
     375dhcp_check(rtems_bsd_rc_conf_argc_argv* aa)
     376{
     377  if (aa->argc == 2 &&
     378      (strcasecmp("DHCP",     aa->argv[1]) == 0 ||
     379       strcasecmp("SYNCDHCP", aa->argv[1]) == 0))
     380    return true;
     381  return false;
     382}
     383
     384static int
    403385setup_lo0(rtems_bsd_rc_conf* rc_conf, struct ifaddrs* ifap)
    404386{
    405387  struct ifaddrs* ifa;
     388
    406389  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    407390    if (strcasecmp("lo0", ifa->ifa_name) == 0) {
     
    413396    }
    414397  }
     398
    415399  fprintf(stderr, "warning: no loopback interface found\n");
     400
    416401  return -1;
    417402}
     
    420405setup_interfaces(rtems_bsd_rc_conf*           rc_conf,
    421406                 rtems_bsd_rc_conf_argc_argv* aa,
    422                  struct ifaddrs*              ifap)
     407                 struct ifaddrs*              ifap,
     408                 bool*                        dhcp)
    423409{
    424410  struct ifaddrs* ifa;
     411  int             r;
     412
    425413  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    426414    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
    427415      char iface[64];
    428       int  r;
    429416      snprintf(iface, sizeof(iface), "ifconfig_%s", ifa->ifa_name);
    430417      r = rtems_bsd_rc_conf_find(rc_conf, iface, aa);
    431418      if (r == 0) {
    432         show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
     419        if (dhcp_check(aa)) {
     420          *dhcp = true;
     421        }
     422        else {
     423          show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
     424        }
    433425      }
    434426    }
    435427  }
     428
    436429  return 0;
    437430}
     
    440433setup_vlans(rtems_bsd_rc_conf*           rc_conf,
    441434            rtems_bsd_rc_conf_argc_argv* aa,
    442             struct ifaddrs*              ifap)
     435            struct ifaddrs*              ifap,
     436            bool*                        dhcp)
    443437{
    444438  rtems_bsd_rc_conf_argc_argv* vaa;
     
    482476            r = rtems_bsd_rc_conf_find(rc_conf, expr, vaa);
    483477            if (r == 0) {
    484               show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
    485                                                vaa->argc, vaa->argv));
     478              if (dhcp_check(vaa)) {
     479                *dhcp = true;
     480              }
     481              else {
     482                show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
     483                                                 vaa->argc, vaa->argv));
     484              }
    486485            }
    487486          }
     
    496495}
    497496
     497/*
     498 * The rc_conf struct cannot be passed to a thread as a pointer. It can only be
     499 * used in the rc.conf worker thread. As a result the values need to print a
     500 * verbose message to aid debugging needs to have local oopies made and passed
     501 * to the dhcpcd worker. The dhcpcd worker runs for ever.
     502 */
     503typedef struct dhcpcd_data {
     504  rtems_bsd_rc_conf_argc_argv* argc_argv;
     505  bool                         verbose;
     506  const char*                  name;
     507} dhcpcd_data;
     508
     509static void
     510dhcpcd_worker(rtems_task_argument arg)
     511{
     512  dhcpcd_data*  dd = (dhcpcd_data*) arg;
     513  int           argc;
     514  const char**  argv;
     515  const char*   dhcpcd_argv[] = { "dhcpcd", NULL };
     516  struct stat   sb;
     517  int           r;
     518
     519  r = stat("/var", &sb);
     520  if (r < 0) {
     521    mkdir("/var", S_IRWXU | S_IRWXG | S_IRWXO);
     522  }
     523
     524  r = stat("/var/db", &sb);
     525  if (r < 0) {
     526    mkdir("/var/db", S_IRWXU | S_IRWXG | S_IRWXO);
     527  }
     528
     529  if (dd->argc_argv->argc > 0) {
     530    argc = dd->argc_argv->argc;
     531    argv = dd->argc_argv->argv;
     532  }
     533  else {
     534    argc = 1;
     535    argv = dhcpcd_argv;
     536  }
     537
     538  if (dd->verbose) {
     539    fprintf(stdout, "rc.conf: %s: dhcpcd ", dd->name);
     540    for (r = 1; r < argc; ++r)
     541      fprintf(stdout, "%s ", argv[r]);
     542    fprintf(stdout, "\n");
     543  }
     544
     545  r = rtems_bsd_command_dhcpcd(argc, argv);
     546  if (r != EX_OK)
     547    fprintf(stderr, "error: dhcpcd: stopped\n");
     548
     549  free(dd->name);
     550  rtems_bsd_rc_conf_argc_argv_destroy(dd->argc_argv);
     551  free(dd);
     552
     553  rtems_task_delete(RTEMS_SELF);
     554}
     555
     556static int
     557run_dhcp(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
     558{
     559  dhcpcd_data*        dd;
     560  rtems_status_code   sc;
     561  rtems_id            id;
     562  rtems_task_priority priority = RTEMS_MAXIMUM_PRIORITY - 1;
     563  char*               end = NULL;
     564  int                 delay = 30;
     565  int                 r;
     566
     567  /*
     568   * These are passed to the worker and cleaned up there if it ever exits. Do
     569   * not destroy here unless an error before the thread runs.
     570   */
     571  dd = calloc(1, sizeof(*dd));
     572  if (dd == NULL) {
     573    fprintf(stderr, "error: dhcpcd data: no memory\n");
     574    errno = ENOMEM;
     575    return -1;
     576  }
     577
     578  dd->name = strdup(rtems_bsd_rc_conf_name(rc_conf));
     579  if (dd == NULL) {
     580    free(dd);
     581    fprintf(stderr, "error: dhcpcd data: no memory\n");
     582    errno = ENOMEM;
     583    return -1;
     584  }
     585
     586  dd->argc_argv = rtems_bsd_rc_conf_argc_argv_create();
     587  if (dd->argc_argv == NULL) {
     588    free(dd->name);
     589    free(dd);
     590    errno = ENOMEM;
     591    return -1;
     592  }
     593
     594  dd->verbose = rtems_bsd_rc_conf_verbose(rc_conf);
     595
     596  r = rtems_bsd_rc_conf_find(rc_conf, "dhcpcd_priority", dd->argc_argv);
     597  if (r == 0) {
     598    if (dd->argc_argv->argc == 2) {
     599      priority = strtoul(dd->argc_argv->argv[1], &end, 10);
     600      if (priority == 0 || *end != '\0')
     601        priority = RTEMS_MAXIMUM_PRIORITY - 1;
     602    }
     603  }
     604
     605  rtems_bsd_rc_conf_find(rc_conf, "dhcpcd_options", dd->argc_argv);
     606
     607  sc = rtems_task_create(rtems_build_name('D', 'H', 'C', 'P'),
     608                         priority,
     609                         2 * RTEMS_MINIMUM_STACK_SIZE,
     610                         RTEMS_DEFAULT_MODES,
     611                         RTEMS_FLOATING_POINT,
     612                         &id);
     613  if (sc == RTEMS_SUCCESSFUL)
     614    sc = rtems_task_start(id, dhcpcd_worker, (rtems_task_argument) dd);
     615  if (sc != RTEMS_SUCCESSFUL) {
     616    fprintf(stderr,
     617            "error: dhcpcd: thread create/start: %s\n", rtems_status_text(sc));
     618    rtems_bsd_rc_conf_argc_argv_destroy(dd->argc_argv);
     619    free(dd->name);
     620    free(dd);
     621    errno = EIO;
     622    return -1;
     623  }
     624
     625  /*
     626   * See if a delay is specified else use default to 30 seconds. Wait for a
     627   * valid default route.
     628   */
     629  r = rtems_bsd_rc_conf_find(rc_conf, "defaultroute_delay", aa);
     630  if (r == 0 && aa->argc == 2) {
     631    delay = (int) strtol(aa->argv[1], &end, 10);
     632    if (*end != '\0') {
     633      fprintf(stderr, "error: defaultroute_delay: invalid delay value\n");
     634      delay = 30;
     635    }
     636  }
     637
     638  printf("Waiting %ds for default route interface: ", delay);
     639  fflush(stdout);
     640
     641  while (delay > 0) {
     642    struct sockaddr_in sin;
     643    struct sockaddr*   rti_info[RTAX_MAX];
     644
     645    --delay;
     646
     647    memset(&sin, 0, sizeof(sin));
     648    sin.sin_family = AF_INET;
     649    inet_pton(AF_INET, "0.0.0.0.", &sin.sin_addr);
     650
     651    r = rtems_get_route(&sin, rti_info);
     652    if (r == 0 && rti_info[RTAX_GATEWAY] != NULL) {
     653      break;
     654    }
     655    else if (r < 0 && errno != ESRCH) {
     656      fprintf(stderr,
     657              "error: get routes %d: %d %s\n", r, errno, strerror(errno));
     658    }
     659
     660    sleep(1);
     661  }
     662
     663  /*
     664   * We should print the interface but I cannot see how to get the interface
     665   * with the default route without a lot of code.
     666   */
     667  if (delay > 0)
     668    printf("found.\n");
     669  else
     670    printf("\nerror: no default route found\n");
     671
     672  return 0;
     673}
     674
    498675static int
    499676interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
    500677{
    501678  struct ifaddrs* ifap;
     679  bool            dhcp = false;
    502680
    503681  if (getifaddrs(&ifap) != 0) {
     
    509687  show_result("cloned_interfaces", cloned_interfaces(rc_conf, aa));
    510688  show_result("lo0", setup_lo0(rc_conf, ifap));
    511   show_result("ifaces", setup_interfaces(rc_conf, aa, ifap));
    512   show_result("vlans", setup_vlans(rc_conf, aa, ifap));
     689  show_result("ifaces", setup_interfaces(rc_conf, aa, ifap, &dhcp));
     690  show_result("vlans", setup_vlans(rc_conf, aa, ifap, &dhcp));
     691  show_result("defaultrouter", defaultrouter(rc_conf, aa));
     692  if (dhcp)
     693    show_result("dhcp", run_dhcp(rc_conf, aa));
    513694
    514695  free(ifap);
     
    534715    return -1;
    535716  }
    536 
    537   show_result("defaultrouter", defaultrouter(rc_conf, aa));
    538717
    539718  rtems_bsd_rc_conf_argc_argv_destroy(aa);
     
    550729                                    network_service);
    551730  if (r < 0)
    552     fprintf(stderr, "error: network service add failed: %s\n", strerror(errno));
    553 }
     731    fprintf(stderr,
     732            "error: network service add failed: %s\n", strerror(errno));
     733}
Note: See TracChangeset for help on using the changeset viewer.