]> git.ipfire.org Git - thirdparty/xtables-addons.git/blame - extensions/libxt_iface.c
build: resolve compiler warnings with gcc-13
[thirdparty/xtables-addons.git] / extensions / libxt_iface.c
CommitLineData
9b198fe6
JE
1/*
2 * Shared library add-on to iptables to add interface state matching
3 * support.
4 *
5 * (C) 2008 Gáspár Lajos <gaspar.lajos@glsys.eu>
6 *
7 * This program is released under the terms of GNU GPL version 2.
8 */
9
10#include <getopt.h>
11#include <stdbool.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include <xtables.h>
17#include "xt_iface.h"
b5e2c725 18#include "compat_user.h"
9b198fe6 19
21cdf786
JE
20enum {
21 XT_IFACE_IFACE = 1 << 16,
22};
23
be2061c5 24static const struct option iface_mt_opts[] = {
f5ed98fb 25 {.name = "iface", .has_arg = true, .val = 'i'},
db76ea9a
JE
26 {.name = "dev-in", .has_arg = false, .val = 'I'},
27 {.name = "dev-out", .has_arg = false, .val = 'O'},
f5ed98fb
JE
28 {.name = "up", .has_arg = false, .val = 'u'},
29 {.name = "down", .has_arg = false, .val = 'U'}, /* not up */
30 {.name = "broadcast", .has_arg = false, .val = 'b'},
31 {.name = "loopback", .has_arg = false, .val = 'l'},
32 {.name = "pointopoint", .has_arg = false, .val = 'p'},
33 {.name = "pointtopoint", .has_arg = false, .val = 'p'}, /* eq pointopoint */
34 {.name = "running", .has_arg = false, .val = 'r'},
35 {.name = "noarp", .has_arg = false, .val = 'n'},
36 {.name = "arp", .has_arg = false, .val = 'N'}, /* not noarp */
37 {.name = "promisc", .has_arg = false, .val = 'o'},
38 {.name = "multicast", .has_arg = false, .val = 'm'},
39 {.name = "dynamic", .has_arg = false, .val = 'd'},
40 {.name = "lower-up", .has_arg = false, .val = 'w'},
41 {.name = "dormant", .has_arg = false, .val = 'a'},
42 {NULL},
9b198fe6
JE
43};
44
45static void iface_print_opt(const struct xt_iface_mtinfo *info,
46 const unsigned int option, const char *command)
47{
9b198fe6 48 if (info->flags & option)
67332653 49 printf(" %s%s", (info->invflags & option) ? "! " : "", command);
9b198fe6
JE
50}
51
52static void iface_setflag(struct xt_iface_mtinfo *info,
53 unsigned int *flags, int invert, u_int16_t flag, const char *command)
54{
9b198fe6
JE
55 if (*flags & flag)
56 xtables_error(PARAMETER_PROBLEM,
57 "iface: \"--%s\" flag already specified", command);
67332653 58 info->flags |= flag;
9b198fe6
JE
59 if (invert)
60 info->invflags |= flag;
9b198fe6
JE
61 *flags |= flag;
62}
63
64static bool iface_valid_name(const char *name)
65{
be2061c5 66 static const char invalid_chars[] = ".+!*";
9b198fe6 67
0d36136f 68 return strlen(name) < IFNAMSIZ && strpbrk(name, invalid_chars) == NULL;
9b198fe6
JE
69}
70
71static void iface_mt_help(void)
72{
73 printf(
6d8ce3ac 74 "iface match options:\n"
db76ea9a
JE
75 " --iface interface Name of interface\n"
76 " --dev-in / --dev-out Use incoming/outgoing interface instead\n"
77 "[!] --up / --down match if UP flag (not) set\n"
78 "[!] --broadcast match if BROADCAST flag (not) set\n"
79 "[!] --loopback match if LOOPBACK flag (not) set\n"
9b198fe6 80 "[!] --pointopoint\n"
db76ea9a
JE
81 "[!] --pointtopoint match if POINTOPOINT flag (not) set\n"
82 "[!] --running match if RUNNING flag (not) set\n"
83 "[!] --noarp / --arp match if NOARP flag (not) set\n"
84 "[!] --promisc match if PROMISC flag (not) set\n"
85 "[!] --multicast match if MULTICAST flag (not) set\n"
86 "[!] --dynamic match if DYNAMIC flag (not) set\n"
87 "[!] --lower-up match if LOWER_UP flag (not) set\n"
88 "[!] --dormant match if DORMANT flag (not) set\n");
9b198fe6
JE
89}
90
9b198fe6
JE
91static int iface_mt_parse(int c, char **argv, int invert, unsigned int *flags,
92 const void *entry, struct xt_entry_match **match)
93{
9b198fe6
JE
94 struct xt_iface_mtinfo *info = (void *)(*match)->data;
95
96 switch (c) {
97 case 'U':
98 c = 'u';
99 invert = !invert;
100 break;
101 case 'N':
102 c = 'n';
103 invert = !invert;
104 break;
105 }
106
107 switch (c) {
108 case 'i': /* interface name */
109 if (*flags & XT_IFACE_IFACE)
110 xtables_error(PARAMETER_PROBLEM,
111 "iface: Interface name already specified");
112 if (!iface_valid_name(optarg))
113 xtables_error(PARAMETER_PROBLEM,
114 "iface: Invalid interface name!");
115 strcpy(info->ifname, optarg);
116 *flags |= XT_IFACE_IFACE;
a6ba463c 117 return true;
db76ea9a
JE
118 case 'I': /* --dev-in */
119 xtables_param_act(XTF_ONLY_ONCE, "iface", "--dev-in",
120 *flags & XT_IFACE_IFACE);
121 *flags |= XT_IFACE_IFACE;
122 iface_setflag(info, flags, invert, XT_IFACE_DEV_IN, "dev-in");
123 return true;
124 case 'O': /* --dev-out */
125 xtables_param_act(XTF_ONLY_ONCE, "iface", "--dev-out",
126 *flags & XT_IFACE_IFACE);
127 *flags |= XT_IFACE_IFACE;
128 iface_setflag(info, flags, invert, XT_IFACE_DEV_OUT, "dev-out");
129 return true;
9b198fe6
JE
130 case 'u': /* UP */
131 iface_setflag(info, flags, invert, XT_IFACE_UP, "up");
a6ba463c 132 return true;
9b198fe6
JE
133 case 'b': /* BROADCAST */
134 iface_setflag(info, flags, invert, XT_IFACE_BROADCAST, "broadcast");
a6ba463c 135 return true;
9b198fe6
JE
136 case 'l': /* LOOPBACK */
137 iface_setflag(info, flags, invert, XT_IFACE_LOOPBACK, "loopback");
a6ba463c 138 return true;
9b198fe6
JE
139 case 'p': /* POINTOPOINT */
140 iface_setflag(info, flags, invert, XT_IFACE_POINTOPOINT, "pointopoint");
a6ba463c 141 return true;
9b198fe6
JE
142 case 'r': /* RUNNING */
143 iface_setflag(info, flags, invert, XT_IFACE_RUNNING, "running");
a6ba463c 144 return true;
9b198fe6
JE
145 case 'n': /* NOARP */
146 iface_setflag(info, flags, invert, XT_IFACE_NOARP, "noarp");
a6ba463c 147 return true;
9b198fe6
JE
148 case 'o': /* PROMISC */
149 iface_setflag(info, flags, invert, XT_IFACE_PROMISC, "promisc");
a6ba463c 150 return true;
9b198fe6
JE
151 case 'm': /* MULTICAST */
152 iface_setflag(info, flags, invert, XT_IFACE_MULTICAST, "multicast");
a6ba463c 153 return true;
9b198fe6
JE
154 case 'd': /* DYNAMIC */
155 iface_setflag(info, flags, invert, XT_IFACE_DYNAMIC, "dynamic");
a6ba463c 156 return true;
9b198fe6
JE
157 case 'w': /* LOWER_UP */
158 iface_setflag(info, flags, invert, XT_IFACE_LOWER_UP, "lower_up");
a6ba463c 159 return true;
9b198fe6
JE
160 case 'a': /* DORMANT */
161 iface_setflag(info, flags, invert, XT_IFACE_DORMANT, "dormant");
a6ba463c 162 return true;
9b198fe6 163 }
a6ba463c 164 return false;
9b198fe6
JE
165}
166
167static void iface_mt_check(unsigned int flags)
168{
9b198fe6
JE
169 if (!(flags & XT_IFACE_IFACE))
170 xtables_error(PARAMETER_PROBLEM,
171 "iface: You must specify an interface");
db76ea9a
JE
172 if ((flags & ~(XT_IFACE_IFACE | XT_IFACE_DEV_IN |
173 XT_IFACE_DEV_OUT)) == 0)
9b198fe6
JE
174 xtables_error(PARAMETER_PROBLEM,
175 "iface: You must specify at least one option");
176}
177
9b198fe6
JE
178static void iface_mt_save(const void *ip, const struct xt_entry_match *match)
179{
9b198fe6
JE
180 const struct xt_iface_mtinfo *info = (const void *)match->data;
181
db76ea9a 182 if (info->flags & XT_IFACE_DEV_IN)
ebfa7779 183 printf(" --dev-in");
db76ea9a 184 else if (info->flags & XT_IFACE_DEV_OUT)
ebfa7779 185 printf(" --dev-out");
db76ea9a 186 else
ebfa7779 187 printf(" --iface %s", info->ifname);
9b198fe6
JE
188 iface_print_opt(info, XT_IFACE_UP, "--up");
189 iface_print_opt(info, XT_IFACE_BROADCAST, "--broadcast");
190 iface_print_opt(info, XT_IFACE_LOOPBACK, "--loopback");
191 iface_print_opt(info, XT_IFACE_POINTOPOINT, "--pointopoint");
192 iface_print_opt(info, XT_IFACE_RUNNING, "--running");
193 iface_print_opt(info, XT_IFACE_NOARP, "--noarp");
194 iface_print_opt(info, XT_IFACE_PROMISC, "--promisc");
195 iface_print_opt(info, XT_IFACE_MULTICAST, "--multicast");
196 iface_print_opt(info, XT_IFACE_DYNAMIC, "--dynamic");
197 iface_print_opt(info, XT_IFACE_LOWER_UP, "--lower_up");
198 iface_print_opt(info, XT_IFACE_DORMANT, "--dormant");
199 printf(" ");
200}
201
13db8d78
JE
202static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
203 int numeric)
204{
205 printf(" -m iface");
206 iface_mt_save(ip, match);
207}
208
9b198fe6
JE
209static struct xtables_match iface_mt_reg = {
210 .version = XTABLES_VERSION,
6d8ce3ac
JE
211 .name = "iface",
212 .revision = 0,
414e95ff 213 .family = NFPROTO_UNSPEC,
9b198fe6
JE
214 .size = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
215 .userspacesize = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
216 .help = iface_mt_help,
9b198fe6
JE
217 .parse = iface_mt_parse,
218 .final_check = iface_mt_check,
219 .print = iface_mt_print,
220 .save = iface_mt_save,
221 .extra_opts = iface_mt_opts,
222};
223
a711985a 224static __attribute__((constructor)) void iface_mt_ldr(void)
9b198fe6 225{
9b198fe6 226 xtables_register_match(&iface_mt_reg);
9b198fe6 227}