summaryrefslogtreecommitdiffstats
path: root/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemsbsd/rtems/rtems-bsd-rc-conf-net.c')
-rw-r--r--rtemsbsd/rtems/rtems-bsd-rc-conf-net.c280
1 files changed, 230 insertions, 50 deletions
diff --git a/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c b/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c
index f4dc0d6f..81812266 100644
--- a/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c
+++ b/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c
@@ -39,11 +39,16 @@
#include <sysexits.h>
#include <ifaddrs.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <rtems.h>
@@ -52,6 +57,8 @@
#include <machine/rtems-bsd-commands.h>
#include <machine/rtems-bsd-rc-conf-services.h>
+#include <rtems/rtems-routes.h>
+
/*
* Default defaultroute_delay is 30seconds.
*/
@@ -335,45 +342,6 @@ defaultrouter(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
return 0;
}
-/*
- * defaultroute_delay
- *
- * eg defaultroute=120
- *
- * See 'man rc.conf(5)' on FreeBSD.
- */
-static int
-defaultroute_delay(rtems_bsd_rc_conf* rc_conf,
- int argc,
- const char** argv)
-{
- int value;
- char* end = NULL;
-
- if (argc != 2) {
- errno = EINVAL;
- return -1;
- }
-
- value = strtol(argv[1], &end, 10);
-
- if (end == NULL) {
- const char* args[] = {
- "defaultrouter_delay", argv[1], NULL
- };
-
- rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 2, args);
-
- defaultroute_delay_secs = value;
- }
- else {
- errno = EINVAL;
- return -1;
- }
-
- return 0;
-}
-
static int
show_interfaces(const char* msg, struct ifaddrs* ifap)
{
@@ -381,6 +349,10 @@ show_interfaces(const char* msg, struct ifaddrs* ifap)
fprintf(stdout, msg);
+ /*
+ * Always have lo0 first.
+ */
+
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcasecmp("lo0", ifa->ifa_name) == 0) {
fprintf(stdout, "%s ", ifa->ifa_name);
@@ -400,9 +372,20 @@ show_interfaces(const char* msg, struct ifaddrs* ifap)
}
static int
+dhcp_check(rtems_bsd_rc_conf_argc_argv* aa)
+{
+ if (aa->argc == 2 &&
+ (strcasecmp("DHCP", aa->argv[1]) == 0 ||
+ strcasecmp("SYNCDHCP", aa->argv[1]) == 0))
+ return true;
+ return false;
+}
+
+static int
setup_lo0(rtems_bsd_rc_conf* rc_conf, struct ifaddrs* ifap)
{
struct ifaddrs* ifa;
+
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcasecmp("lo0", ifa->ifa_name) == 0) {
const char* lo0_argv[] = {
@@ -412,34 +395,45 @@ setup_lo0(rtems_bsd_rc_conf* rc_conf, struct ifaddrs* ifap)
return 0;
}
}
+
fprintf(stderr, "warning: no loopback interface found\n");
+
return -1;
}
static int
setup_interfaces(rtems_bsd_rc_conf* rc_conf,
rtems_bsd_rc_conf_argc_argv* aa,
- struct ifaddrs* ifap)
+ struct ifaddrs* ifap,
+ bool* dhcp)
{
struct ifaddrs* ifa;
+ int r;
+
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcasecmp("lo0", ifa->ifa_name) != 0) {
char iface[64];
- int r;
snprintf(iface, sizeof(iface), "ifconfig_%s", ifa->ifa_name);
r = rtems_bsd_rc_conf_find(rc_conf, iface, aa);
if (r == 0) {
- show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
+ if (dhcp_check(aa)) {
+ *dhcp = true;
+ }
+ else {
+ show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
+ }
}
}
}
+
return 0;
}
static int
setup_vlans(rtems_bsd_rc_conf* rc_conf,
rtems_bsd_rc_conf_argc_argv* aa,
- struct ifaddrs* ifap)
+ struct ifaddrs* ifap,
+ bool* dhcp)
{
rtems_bsd_rc_conf_argc_argv* vaa;
struct ifaddrs* ifa;
@@ -481,8 +475,13 @@ setup_vlans(rtems_bsd_rc_conf* rc_conf,
"ifconfig_%s_%s", ifa->ifa_name, aa->argv[arg]);
r = rtems_bsd_rc_conf_find(rc_conf, expr, vaa);
if (r == 0) {
- show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
- vaa->argc, vaa->argv));
+ if (dhcp_check(vaa)) {
+ *dhcp = true;
+ }
+ else {
+ show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
+ vaa->argc, vaa->argv));
+ }
}
}
}
@@ -495,10 +494,189 @@ setup_vlans(rtems_bsd_rc_conf* rc_conf,
return 0;
}
+/*
+ * The rc_conf struct cannot be passed to a thread as a pointer. It can only be
+ * used in the rc.conf worker thread. As a result the values need to print a
+ * verbose message to aid debugging needs to have local oopies made and passed
+ * to the dhcpcd worker. The dhcpcd worker runs for ever.
+ */
+typedef struct dhcpcd_data {
+ rtems_bsd_rc_conf_argc_argv* argc_argv;
+ bool verbose;
+ const char* name;
+} dhcpcd_data;
+
+static void
+dhcpcd_worker(rtems_task_argument arg)
+{
+ dhcpcd_data* dd = (dhcpcd_data*) arg;
+ int argc;
+ const char** argv;
+ const char* dhcpcd_argv[] = { "dhcpcd", NULL };
+ struct stat sb;
+ int r;
+
+ r = stat("/var", &sb);
+ if (r < 0) {
+ mkdir("/var", S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+
+ r = stat("/var/db", &sb);
+ if (r < 0) {
+ mkdir("/var/db", S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+
+ if (dd->argc_argv->argc > 0) {
+ argc = dd->argc_argv->argc;
+ argv = dd->argc_argv->argv;
+ }
+ else {
+ argc = 1;
+ argv = dhcpcd_argv;
+ }
+
+ if (dd->verbose) {
+ fprintf(stdout, "rc.conf: %s: dhcpcd ", dd->name);
+ for (r = 1; r < argc; ++r)
+ fprintf(stdout, "%s ", argv[r]);
+ fprintf(stdout, "\n");
+ }
+
+ r = rtems_bsd_command_dhcpcd(argc, argv);
+ if (r != EX_OK)
+ fprintf(stderr, "error: dhcpcd: stopped\n");
+
+ free(dd->name);
+ rtems_bsd_rc_conf_argc_argv_destroy(dd->argc_argv);
+ free(dd);
+
+ rtems_task_delete(RTEMS_SELF);
+}
+
+static int
+run_dhcp(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
+{
+ dhcpcd_data* dd;
+ rtems_status_code sc;
+ rtems_id id;
+ rtems_task_priority priority = RTEMS_MAXIMUM_PRIORITY - 1;
+ char* end = NULL;
+ int delay = 30;
+ int r;
+
+ /*
+ * These are passed to the worker and cleaned up there if it ever exits. Do
+ * not destroy here unless an error before the thread runs.
+ */
+ dd = calloc(1, sizeof(*dd));
+ if (dd == NULL) {
+ fprintf(stderr, "error: dhcpcd data: no memory\n");
+ errno = ENOMEM;
+ return -1;
+ }
+
+ dd->name = strdup(rtems_bsd_rc_conf_name(rc_conf));
+ if (dd == NULL) {
+ free(dd);
+ fprintf(stderr, "error: dhcpcd data: no memory\n");
+ errno = ENOMEM;
+ return -1;
+ }
+
+ dd->argc_argv = rtems_bsd_rc_conf_argc_argv_create();
+ if (dd->argc_argv == NULL) {
+ free(dd->name);
+ free(dd);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ dd->verbose = rtems_bsd_rc_conf_verbose(rc_conf);
+
+ r = rtems_bsd_rc_conf_find(rc_conf, "dhcpcd_priority", dd->argc_argv);
+ if (r == 0) {
+ if (dd->argc_argv->argc == 2) {
+ priority = strtoul(dd->argc_argv->argv[1], &end, 10);
+ if (priority == 0 || *end != '\0')
+ priority = RTEMS_MAXIMUM_PRIORITY - 1;
+ }
+ }
+
+ rtems_bsd_rc_conf_find(rc_conf, "dhcpcd_options", dd->argc_argv);
+
+ sc = rtems_task_create(rtems_build_name('D', 'H', 'C', 'P'),
+ priority,
+ 2 * RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_FLOATING_POINT,
+ &id);
+ if (sc == RTEMS_SUCCESSFUL)
+ sc = rtems_task_start(id, dhcpcd_worker, (rtems_task_argument) dd);
+ if (sc != RTEMS_SUCCESSFUL) {
+ fprintf(stderr,
+ "error: dhcpcd: thread create/start: %s\n", rtems_status_text(sc));
+ rtems_bsd_rc_conf_argc_argv_destroy(dd->argc_argv);
+ free(dd->name);
+ free(dd);
+ errno = EIO;
+ return -1;
+ }
+
+ /*
+ * See if a delay is specified else use default to 30 seconds. Wait for a
+ * valid default route.
+ */
+ r = rtems_bsd_rc_conf_find(rc_conf, "defaultroute_delay", aa);
+ if (r == 0 && aa->argc == 2) {
+ delay = (int) strtol(aa->argv[1], &end, 10);
+ if (*end != '\0') {
+ fprintf(stderr, "error: defaultroute_delay: invalid delay value\n");
+ delay = 30;
+ }
+ }
+
+ printf("Waiting %ds for default route interface: ", delay);
+ fflush(stdout);
+
+ while (delay > 0) {
+ struct sockaddr_in sin;
+ struct sockaddr* rti_info[RTAX_MAX];
+
+ --delay;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ inet_pton(AF_INET, "0.0.0.0.", &sin.sin_addr);
+
+ r = rtems_get_route(&sin, rti_info);
+ if (r == 0 && rti_info[RTAX_GATEWAY] != NULL) {
+ break;
+ }
+ else if (r < 0 && errno != ESRCH) {
+ fprintf(stderr,
+ "error: get routes %d: %d %s\n", r, errno, strerror(errno));
+ }
+
+ sleep(1);
+ }
+
+ /*
+ * We should print the interface but I cannot see how to get the interface
+ * with the default route without a lot of code.
+ */
+ if (delay > 0)
+ printf("found.\n");
+ else
+ printf("\nerror: no default route found\n");
+
+ return 0;
+}
+
static int
interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
{
struct ifaddrs* ifap;
+ bool dhcp = false;
if (getifaddrs(&ifap) != 0) {
fprintf(stderr, "error: interfaces: getifaddrs: %s\n", strerror(errno));
@@ -508,8 +686,11 @@ interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
show_interfaces("Starting network: ", ifap);
show_result("cloned_interfaces", cloned_interfaces(rc_conf, aa));
show_result("lo0", setup_lo0(rc_conf, ifap));
- show_result("ifaces", setup_interfaces(rc_conf, aa, ifap));
- show_result("vlans", setup_vlans(rc_conf, aa, ifap));
+ show_result("ifaces", setup_interfaces(rc_conf, aa, ifap, &dhcp));
+ show_result("vlans", setup_vlans(rc_conf, aa, ifap, &dhcp));
+ show_result("defaultrouter", defaultrouter(rc_conf, aa));
+ if (dhcp)
+ show_result("dhcp", run_dhcp(rc_conf, aa));
free(ifap);
@@ -534,8 +715,6 @@ network_service(rtems_bsd_rc_conf* rc_conf)
return -1;
}
- show_result("defaultrouter", defaultrouter(rc_conf, aa));
-
rtems_bsd_rc_conf_argc_argv_destroy(aa);
return 0;
@@ -549,5 +728,6 @@ rc_conf_net_init(void* arg)
"after:first;",
network_service);
if (r < 0)
- fprintf(stderr, "error: network service add failed: %s\n", strerror(errno));
+ fprintf(stderr,
+ "error: network service add failed: %s\n", strerror(errno));
}