source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c @ eae664e

55-freebsd-126-freebsd-12
Last change on this file since eae664e was bc9e939, checked in by Christian Mauderer <Christian.Mauderer@…>, on 08/04/16 at 11:20:04

pf: Add configuration via rc.conf.

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * Handle the PF firewall directives found in rc.conf.
34 * - pf_enable
35 * - pf_rules
36 * - pf_flags
37 *
38 * Note: RTEMS ignores the
39 * - pf_program
40 * directive.
41 */
42
43#include <errno.h>
44#include <stdint.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <strings.h>
49
50#include <machine/rtems-bsd-commands.h>
51#include <machine/rtems-bsd-rc-conf-services.h>
52
53static char firewall_pf_rules_default[] = "/etc/pf.conf";
54
55static int
56firewall_pf_enable(rtems_bsd_rc_conf* rc_conf)
57{
58  char *args[] = {
59    "pfctl",
60    "-q",
61    "-e",
62    NULL
63  };
64
65  rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", RTEMS_BSD_ARGC(args),
66      (const char **) args);
67  return rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(args), args);
68}
69
70static int
71firewall_pf_flush(
72    rtems_bsd_rc_conf* rc_conf,
73    char what[])
74{
75  char *flush[] = {
76    "pfctl",
77    "-q",
78    "-F",
79    what,
80    NULL
81  };
82
83  rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", RTEMS_BSD_ARGC(flush),
84      (const char **) flush);
85  return rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(flush), flush);
86}
87
88/*
89 * Executes something like the following command line:
90 *   pfctl -f <rules> [<argv[1]> [<argv[2]> [..]]]
91 */
92static int
93firewall_pf_load_rules_with_extra_args(
94    rtems_bsd_rc_conf* rc_conf,
95    char *rules,
96    int argc,
97    const char **argv)
98{
99  char** args;
100  const int fixed_args = 2; /* "-f" and filename */
101  int arg;
102  int r = -1;
103  bool prepare_failed = false;
104
105  /*
106   * argc/argv contains something like the following:
107   *   argc = 3
108   *   argv = {"pf_flags", "-i", "lo0"}
109   *
110   * Alternatively it might be
111   *   argc = 0
112   *   argv = NULL
113   */
114
115  /* The code below assumes an argc >= 1. Fake it if there are no additional
116   * arguments. */
117  if(argc == 0) {
118    argc = 1;
119  }
120
121  args = calloc(argc + fixed_args + 1, sizeof(char*));
122  if (args == NULL) {
123    return -1;
124  }
125
126  args[0] = "pfctl";
127  args[1] = "-f";
128  args[2] = rules;
129  args[argc + fixed_args] = NULL;
130
131  for (arg = 1; arg < argc; ++arg) {
132    args[arg + fixed_args] = strdup(argv[arg]);
133    if (args[arg + fixed_args] == NULL) {
134      prepare_failed = true;
135      break;
136    }
137  }
138
139  if (prepare_failed == false) {
140    rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", argc + fixed_args,
141        (const char **) args);
142    r = rtems_bsd_command_pfctl(argc + fixed_args, args);
143  } else {
144    r = EXIT_FAILURE;
145  }
146
147  for (arg = 1; arg < argc; ++arg) {
148    free(args[arg + fixed_args]);
149  }
150  free(args);
151
152  return r;
153}
154
155static int
156firewall_pf_service(rtems_bsd_rc_conf* rc_conf)
157{
158  rtems_bsd_rc_conf_argc_argv* aa;
159  int r;
160  int erroroccured = 0;
161
162  aa = rtems_bsd_rc_conf_argc_argv_create();
163  if (aa == NULL)
164    return -1;
165
166  r = rtems_bsd_rc_conf_find(rc_conf, "pf_enable", aa);
167  if (r == 0) {
168    if (aa->argc == 2 && strcasecmp("YES", aa->argv[1]) == 0) {
169      char* rules = firewall_pf_rules_default;
170      int argc = 0;
171      const char** argv = NULL;
172
173      if (erroroccured == 0) {
174        r = rtems_bsd_rc_conf_find(rc_conf, "pf_rules", aa);
175        if (r == 0) {
176          if (aa->argc == 2) {
177            rules = strdup(aa->argv[1]);
178            if (rules == NULL) {
179              fprintf(stderr,
180                  "error: pf: Could not create rule file string: %s\n",
181                  strerror(errno));
182              erroroccured = -1;
183            }
184          } else {
185            fprintf(stderr,
186                "error: pf: Syntax error in pf_rules directive.\n");
187              erroroccured = -1;
188          }
189        }
190      }
191
192      if (erroroccured == 0) {
193        r = rtems_bsd_rc_conf_find(rc_conf, "pf_flags", aa);
194        if (r == 0) {
195          argc = aa->argc;
196          argv = aa->argv;
197        }
198      }
199
200      /*
201       * FreeBSD does the following on pf_start() in /etc/rc.d/pf:
202       * ----
203       *    check_startmsgs && echo -n 'Enabling pf'
204       *    $pf_program -F all > /dev/null 2>&1
205       *    $pf_program -f "$pf_rules" $pf_flags
206       *    if ! $pf_program -s info | grep -q "Enabled" ; then
207       *        $pf_program -eq
208       *    fi
209       *    check_startmsgs && echo '.'
210       * ----
211       * We should do roughly the same
212       */
213      if (erroroccured == 0) {
214        r = firewall_pf_flush(rc_conf, "all");
215        if(r != EXIT_SUCCESS) {
216          fprintf(stderr,
217              "error: pf: Could not flush.\n");
218          erroroccured = -1;
219        }
220      }
221
222      if (erroroccured == 0) {
223        r = firewall_pf_load_rules_with_extra_args(rc_conf, rules, argc, argv);
224        if (r != EXIT_SUCCESS) {
225          fprintf(stderr,
226              "error: pf: Could not load rules.\n");
227          erroroccured = -1;
228        }
229      }
230
231      if (erroroccured == 0) {
232        r = firewall_pf_enable(rc_conf);
233        if (r != EXIT_SUCCESS) {
234          fprintf(stderr,
235              "error: pf: Could not enable firewall.\n");
236          erroroccured = -1;
237        }
238      }
239
240      if (rules != firewall_pf_rules_default && rules != NULL) {
241        free(rules);
242      }
243    }
244  }
245
246  rtems_bsd_rc_conf_argc_argv_destroy(aa);
247
248  return erroroccured;
249}
250
251void
252rc_conf_firewall_pf_init(void* arg)
253{
254  int r;
255  r = rtems_bsd_rc_conf_service_add("pf",
256                                    "after:network;before:telnetd;",
257                                    firewall_pf_service);
258  if (r < 0)
259    fprintf(stderr,
260            "error: pf service add failed: %s\n", strerror(errno));
261}
Note: See TracBrowser for help on using the repository browser.