source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-rc-conf-net.c @ 55c564a

5-freebsd-12freebsd-9.3
Last change on this file since 55c564a was 55c564a, checked in by Chris Johns <chrisj@…>, on Jun 27, 2016 at 3:24:43 AM

Refactor rc.conf processing to be services based.

  • Property mode set to 100644
File size: 13.2 KB
Line 
1/*
2 * Copyright (c) 2016 Chris Johns <chrisj@rtems.org>.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/*
27 * Handle the networking directives found in rc.conf.
28 *  - ifconfig_*
29 *  - cloned_interfaces
30 *  - autobridge_interfaces
31 *  - autobridge_bridge*
32 *  - defaultrouter
33 */
34
35#include <rtems/bsd/sys/param.h>
36#include <sys/types.h>
37#include <sys/queue.h>
38#include <sys/kernel.h>
39#include <sysexits.h>
40
41#include <ifaddrs.h>
42
43#include <errno.h>
44#include <stddef.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <unistd.h>
48
49#include <rtems.h>
50#include <rtems/chain.h>
51
52#include <machine/rtems-bsd-commands.h>
53#include <machine/rtems-bsd-rc-conf-services.h>
54
55/*
56 * Default defaultroute_delay is 30seconds.
57 */
58static int defaultroute_delay_secs = 30;
59
60/*
61 * Show a result.
62 */
63static void
64show_result(const char* label, int r)
65{
66  if (r < 0)
67    fprintf(stderr, "error: %s: %s\n", label, strerror(errno));
68}
69
70/*
71 * cloned_interfaces
72 *
73 * eg cloned_interfaces="vlan0 bridge0 tap1 tap2"
74 *
75 * See 'man rc.conf(5)' on FreeBSD.
76 */
77static int
78cloned_interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
79{
80  int arg;
81  int r = 0;
82
83  r = rtems_bsd_rc_conf_find(rc_conf, "cloned_interfaces", aa);
84  if (r < 0) {
85    if (errno == ENOENT)
86      r = 0;
87    return r;
88  }
89
90  for (arg = 1; arg < aa->argc; ++arg) {
91    const char* ifconfg_args[] = {
92      "ifconfig", aa->argv[arg], "create", NULL
93    };
94    rtems_bsd_rc_conf_print_cmd(rc_conf, "cloning_interfaces", 3, ifconfg_args);
95    rtems_bsd_command_ifconfig(3, (char**) ifconfg_args);
96  }
97
98  return 0;
99}
100
101/*
102 * create_args_'interface'
103 *
104 * eg create_args_myvlan="vlan 102"
105 *
106 * See 'man rc.conf(5)' on FreeBSD.
107 */
108typedef struct {
109  rtems_chain_node node;
110  const char*      label;
111  int              argc;
112  const char**     argv;
113} create_args_item;
114
115static RTEMS_CHAIN_DEFINE_EMPTY(create_args_items);
116
117static int
118load_create_args(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
119{
120  int r = 0;
121
122  r = rtems_bsd_rc_conf_find(rc_conf, "create_args_.*", aa);
123
124  while (r == 0) {
125    rtems_chain_node* node;
126    const char*       label;
127    create_args_item* item;
128    int               arg;
129
130    rtems_bsd_rc_conf_print_cmd(rc_conf, "create_args_", aa->argc, aa->argv);
131
132    label = aa->argv[0] + strlen("create_args_");
133
134    node = rtems_chain_first(&create_args_items);
135
136    while (!rtems_chain_is_tail(&create_args_items, node)) {
137      item = (create_args_item*) node;
138      if (strcasecmp(item->label, label) == 0) {
139        fprintf(stderr, "error: %s:%d: duplicate create args entry: %s\n",
140                rtems_bsd_rc_conf_name(rc_conf),
141                rtems_bsd_rc_conf_line(rc_conf),
142                aa->argv[0]);
143        errno = EEXIST;
144        return -1;
145      }
146      node = rtems_chain_next(node);
147    }
148
149    item = calloc(1, sizeof(*item));
150    if (item == NULL) {
151      errno = ENOMEM;
152      fprintf(stderr, "error: %s:%d: %s\n",
153              rtems_bsd_rc_conf_name(rc_conf),
154              rtems_bsd_rc_conf_line(rc_conf),
155              strerror(errno));
156      return -1;
157    }
158
159    item->argc = aa->argc;
160
161    item->label = strdup(label);
162    if (item->label == NULL) {
163      free(item);
164      errno = ENOMEM;
165      fprintf(stderr, "error: %s:%d: %s\n",
166              rtems_bsd_rc_conf_name(rc_conf),
167              rtems_bsd_rc_conf_line(rc_conf),
168              strerror(errno));
169      return -1;
170    }
171
172    item->argv = calloc(aa->argc + 1, sizeof(char*));
173    if (item->argv == NULL) {
174      free((void*) item->label);
175      free(item);
176      errno = ENOMEM;
177      fprintf(stderr, "error: %s:%d: %s\n",
178              rtems_bsd_rc_conf_name(rc_conf),
179              rtems_bsd_rc_conf_line(rc_conf),
180              strerror(errno));
181      return -1;
182    }
183
184    for (arg = 0; arg < aa->argc; ++arg) {
185      item->argv[arg] = strdup(aa->argv[0]);
186      if (item->argv[arg] == NULL) {
187        int a;
188        for (a = 0; a < arg; ++a)
189          free((void*) item->argv[a]);
190        free(item->argv);
191        free((void*) item->label);
192        free(item);
193        errno = ENOMEM;
194        fprintf(stderr, "error: %s:%d: %s\n",
195                rtems_bsd_rc_conf_name(rc_conf),
196                rtems_bsd_rc_conf_line(rc_conf),
197                strerror(errno));
198        return -1;
199      }
200    }
201
202    rtems_chain_append(&create_args_items, &item->node);
203
204    r = rtems_bsd_rc_conf_find_next(rc_conf, aa);
205  }
206
207  /*
208   * ignore not found.
209   */
210  if (r < 0 && errno == ENOENT)
211    r = 0;
212
213  return 0;
214}
215
216/*
217 * ifconfig_'interface'
218 *
219 * eg ifconfig_em0="inet 10.10.5.33 netmask 255.255.255.0"
220 *
221 * See 'man rc.conf(5)' on FreeBSD.
222 */
223static int
224ifconfig_(rtems_bsd_rc_conf* rc_conf,
225          const char*        ifname,
226          int                argc,
227          const char**       argv)
228{
229  const char**      args;
230  int               arg;
231  int               r;
232  const char const* ifconfig_show[] = { "ifconfig", ifname, NULL };
233
234  for (arg = 1; arg < argc; ++arg) {
235    if (strcasecmp(argv[arg], "NOAUTO") == 0)
236      return 0;
237  }
238
239  args = calloc(argc + 3, sizeof(char*));
240  if (args == NULL) {
241    errno = ENOMEM;
242    return -1;
243  }
244
245  args[0] = "ifconfig";
246  args[1] = ifname;
247
248  for (arg = 1; arg < argc; ++arg)
249    args[arg + 1] = argv[arg];
250
251  args[argc + 1] = "up";
252
253  rtems_bsd_rc_conf_print_cmd(rc_conf, "ifconfig", argc + 2, args);
254
255  r = rtems_bsd_command_ifconfig(argc + 2, (char**) args);
256
257  free(args);
258
259  if (r != EX_OK) {
260    errno = ECANCELED;
261    return -1;
262  }
263
264  r = rtems_bsd_command_ifconfig(2, (char**) ifconfig_show);
265
266  return r;
267}
268
269/*
270 * hostname
271 *
272 * eg hostname="myhost"
273 *
274 * See 'man rc.conf(5)' on FreeBSD.
275 */
276static int
277hostname(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
278{
279  const char**      argv;
280  int               r;
281  const char const* default_argv[] = { "hostname", "Amnesiac", NULL };
282
283  r = rtems_bsd_rc_conf_find(rc_conf, "hostname", aa);
284  if (r < 0 && errno != ENOENT)
285    return -1;
286
287  if (r < 0 || (r == 0 && aa->argc != 2)) {
288    argv = default_argv;
289  }
290  else {
291    argv = aa->argv;
292  }
293
294  fprintf(stdout, "Setting hostname: %s.\n", argv[1]);
295
296  return sethostname(argv[1], strlen(argv[1]));
297}
298
299/*
300 * defaultrouter
301 *
302 * eg defaultrouter="1.2.3.4"
303 *
304 * See 'man rc.conf(5)' on FreeBSD.
305 */
306static int
307defaultrouter(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
308{
309  int r;
310
311  r = rtems_bsd_rc_conf_find(rc_conf, "defaultrouter", aa);
312  if (r < 0 && errno != ENOENT)
313    return -1;
314
315  if (r == 0) {
316    if (aa->argc > 2) {
317      errno = EINVAL;
318      return -1;
319    }
320
321    if (strcasecmp(aa->argv[1], "NO") != 0) {
322      const char* args[] = { "route", "add", "default", aa->argv[1], NULL };
323      int         r;
324
325      rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 4, args);
326
327      r = rtems_bsd_command_route(4, (char**) args);
328      if (r != EX_OK) {
329        errno = ECANCELED;
330        return -1;
331      }
332    }
333  }
334
335  return 0;
336}
337
338/*
339 * defaultroute_delay
340 *
341 * eg defaultroute=120
342 *
343 * See 'man rc.conf(5)' on FreeBSD.
344 */
345static int
346defaultroute_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
377static int
378show_interfaces(const char* msg, struct ifaddrs* ifap)
379{
380  struct ifaddrs* ifa;
381
382  fprintf(stdout, msg);
383
384  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
385    if (strcasecmp("lo0", ifa->ifa_name) == 0) {
386      fprintf(stdout, "%s ", ifa->ifa_name);
387      break;
388    }
389  }
390
391  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
392    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
393      fprintf(stdout, "%s ", ifa->ifa_name);
394    }
395  }
396
397  fprintf(stdout, "\b.\n");
398
399  return 0;
400}
401
402static int
403setup_lo0(rtems_bsd_rc_conf* rc_conf, struct ifaddrs* ifap)
404{
405  struct ifaddrs* ifa;
406  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
407    if (strcasecmp("lo0", ifa->ifa_name) == 0) {
408      const char* lo0_argv[] = {
409        "ifconfig_lo0", "inet", "127.0.0.1", "netmask", "255.0.0.0", NULL
410      };
411      show_result("lo0", ifconfig_(rc_conf, "lo0", 5, lo0_argv));
412      return 0;
413    }
414  }
415  fprintf(stderr, "warning: no loopback interface found\n");
416  return -1;
417}
418
419static int
420setup_interfaces(rtems_bsd_rc_conf*           rc_conf,
421                 rtems_bsd_rc_conf_argc_argv* aa,
422                 struct ifaddrs*              ifap)
423{
424  struct ifaddrs* ifa;
425  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
426    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
427      char iface[64];
428      int  r;
429      snprintf(iface, sizeof(iface), "ifconfig_%s", ifa->ifa_name);
430      r = rtems_bsd_rc_conf_find(rc_conf, iface, aa);
431      if (r == 0) {
432        show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
433      }
434    }
435  }
436  return 0;
437}
438
439static int
440setup_vlans(rtems_bsd_rc_conf*           rc_conf,
441            rtems_bsd_rc_conf_argc_argv* aa,
442            struct ifaddrs*              ifap)
443{
444  rtems_bsd_rc_conf_argc_argv* vaa;
445  struct ifaddrs*              ifa;
446
447  vaa = rtems_bsd_rc_conf_argc_argv_create();
448  if (vaa == NULL)
449    return -1;
450
451  show_result("create_args", load_create_args(rc_conf, aa));
452
453  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
454    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
455      char expr[128];
456      int  r;
457      /*
458       * Look for vlans_'iface'="101 102 103"
459       */
460      snprintf(expr, sizeof(expr), "vlans_%s", ifa->ifa_name);
461      r = rtems_bsd_rc_conf_find(rc_conf, expr, aa);
462      if (r == 0) {
463        int arg;
464        for (arg = 1; arg < aa->argc; ++arg) {
465          char vlan_name[64];
466          const char* vlan_create[] = {
467            "ifconfig", vlan_name, "create", NULL
468          };
469          /*
470           * Create the VLAN name as 'iface'.'vlan'.
471           */
472          snprintf(vlan_name, sizeof(vlan_name),
473                   "%s.%s", ifa->ifa_name, aa->argv[arg]);
474          rtems_bsd_rc_conf_print_cmd(rc_conf, "vlan", 3, vlan_create);
475          r = rtems_bsd_command_ifconfig(3, (char**) vlan_create);
476          if (r == 0) {
477            /*
478             * Look for ifconfig_'iface'_'vlan'="..."
479             */
480            snprintf(expr, sizeof(expr),
481                     "ifconfig_%s_%s", ifa->ifa_name, aa->argv[arg]);
482            r = rtems_bsd_rc_conf_find(rc_conf, expr, vaa);
483            if (r == 0) {
484              show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
485                                               vaa->argc, vaa->argv));
486            }
487          }
488        }
489      }
490    }
491  }
492
493  rtems_bsd_rc_conf_argc_argv_destroy(vaa);
494
495  return 0;
496}
497
498static int
499interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
500{
501  struct ifaddrs* ifap;
502
503  if (getifaddrs(&ifap) != 0) {
504    fprintf(stderr, "error: interfaces: getifaddrs: %s\n", strerror(errno));
505    return -1;
506  }
507
508  show_interfaces("Starting network: ", ifap);
509  show_result("cloned_interfaces", cloned_interfaces(rc_conf, aa));
510  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));
513
514  free(ifap);
515
516  return 0;
517}
518
519static int
520network_service(rtems_bsd_rc_conf* rc_conf)
521{
522  rtems_bsd_rc_conf_argc_argv* aa;
523  int                          r;
524
525  aa = rtems_bsd_rc_conf_argc_argv_create();
526  if (aa == NULL)
527    return -1;
528
529  show_result("hostname",    hostname(rc_conf, aa));
530
531  r = interfaces(rc_conf, aa);
532  if (r < 0) {
533    rtems_bsd_rc_conf_argc_argv_destroy(aa);
534    return -1;
535  }
536
537  show_result("defaultrouter", defaultrouter(rc_conf, aa));
538
539  rtems_bsd_rc_conf_argc_argv_destroy(aa);
540
541  return 0;
542}
543
544void
545rc_conf_net_init(void* arg)
546{
547  int r;
548  r = rtems_bsd_rc_conf_service_add("network",
549                                    "after:first;",
550                                    network_service);
551  if (r < 0)
552    fprintf(stderr, "error: network service add failed: %s\n", strerror(errno));
553}
Note: See TracBrowser for help on using the repository browser.