blob: ead6de7053e7abbd49154b3fd7fdcb4587113cb6 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Shared library add-on to iptables to add LED support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <syslog.h>
7#include <getopt.h>
8#include <xtables.h>
9#include <linux/netfilter_ipv4/ipt_LED.h>
10#include <linux/ledman.h>
11
12static struct option opts[] = {
13 { .name = "led", .has_arg = 1, .flag = 0, .val = '1' },
14 { .name = "save", .has_arg = 0, .flag = 0, .val = '2' },
15 { .name = "restore", .has_arg = 0, .flag = 0, .val = '3' },
16 { .name = NULL }
17};
18
19static void
20init(struct xt_entry_target *t)
21{
22 struct ipt_led_info *ledinfo = (struct ipt_led_info *)t->data;
23
24 ledinfo->led = LEDMAN_ALL;
25 ledinfo->mode = IPT_LED_SET;
26}
27
28struct ipt_led_names {
29 const char *name;
30 u_int32_t led;
31};
32
33static struct ipt_led_names ipt_led_names[] = {
34#include "libipt_LED_def.c"
35 { }
36};
37
38static u_int32_t
39parse_led(const char *name)
40{
41 unsigned int led = -1;
42 unsigned int set = 0;
43
44 if (!xtables_strtoui(name, NULL, &led, 0, 7)) {
45 unsigned int i = 0;
46
47 for (i = 0; ipt_led_names[i].name; i++) {
48 if (strcasecmp(name, ipt_led_names[i].name) == 0) {
49 set++;
50 led = ipt_led_names[i].led;
51 break;
52 }
53 if (strncasecmp(name, ipt_led_names[i].name,
54 strlen(name)) == 0) {
55 if (set++)
56 xtables_error(PARAMETER_PROBLEM,
57 "led `%s' ambiguous", name);
58 led = ipt_led_names[i].led;
59 }
60 }
61
62 if (!set)
63 xtables_error(PARAMETER_PROBLEM,
64 "led `%s' unknown", name);
65 }
66
67 return led;
68}
69
70#define IPT_LED_OPT_LED 0x01
71#define IPT_LED_OPT_MODE 0x02
72#define IPT_LED_OPT_NO_LED 0x04
73
74static int
75parse(int c, char **argv, int invert, unsigned int *flags,
76 const void *entry,
77 struct xt_entry_target **target)
78{
79 struct ipt_led_info *ledinfo = (struct ipt_led_info *)(*target)->data;
80
81 switch (c) {
82 case '1':
83 if (*flags & IPT_LED_OPT_LED)
84 xtables_error(PARAMETER_PROBLEM,
85 "Can't specify --led twice");
86
87 ledinfo->led = parse_led(optarg);
88 *flags |= IPT_LED_OPT_LED;
89 break;
90
91 case '2':
92 if (*flags & IPT_LED_OPT_MODE)
93 xtables_error(PARAMETER_PROBLEM,
94 "Can't specify --save twice");
95
96 ledinfo->mode = IPT_LED_SAVE;
97 *flags |= IPT_LED_OPT_MODE;
98 break;
99
100 case '3':
101 if (*flags & IPT_LED_OPT_MODE)
102 xtables_error(PARAMETER_PROBLEM,
103 "Can't specify --restore twice");
104
105 ledinfo->mode = IPT_LED_RESTORE;
106 *flags |= IPT_LED_OPT_MODE | IPT_LED_OPT_NO_LED;
107 break;
108
109 default:
110 return 0;
111 }
112
113 return 1;
114}
115
116static void
117final_check(unsigned int flags)
118{
119 if ((flags & IPT_LED_OPT_NO_LED) && (flags & IPT_LED_OPT_LED))
120 xtables_error(PARAMETER_PROBLEM,
121 "LED target: Can't specify --led with --restore");
122
123 if (!(flags & IPT_LED_OPT_NO_LED) && !(flags & IPT_LED_OPT_LED))
124 xtables_error(PARAMETER_PROBLEM,
125 "LED target: No --led specified");
126}
127
128static void
129print(const void *ip,
130 const struct xt_entry_target *target,
131 int numeric)
132{
133 const struct ipt_led_info *ledinfo
134 = (const struct ipt_led_info *)target->data;
135 unsigned int i;
136
137 printf("LED ");
138 switch (ledinfo->mode) {
139 case IPT_LED_SAVE:
140 printf("save ");
141 /* fallthrough */
142 case IPT_LED_SET:
143 for (i = 0; ipt_led_names[i].name; i++) {
144 if (ledinfo->led == ipt_led_names[i].led) {
145 printf("led %s ", ipt_led_names[i].name);
146 break;
147 }
148 }
149 if (!ipt_led_names[i].name)
150 printf("UNKNOWN led %u ", ledinfo->led);
151 break;
152 case IPT_LED_RESTORE:
153 printf("restore ");
154 break;
155 default:
156 printf("ERROR: UNKNOWN LED MODE ");
157 break;
158 }
159}
160
161static void
162save(const void *ip, const struct xt_entry_target *target)
163{
164 const struct ipt_led_info *ledinfo
165 = (const struct ipt_led_info *)target->data;
166 unsigned int i;
167
168 switch (ledinfo->mode) {
169 case IPT_LED_SAVE:
170 printf("--save ");
171 /* fallthrough */
172 case IPT_LED_SET:
173 printf("--led ");
174 for (i = 0; ipt_led_names[i].name; i++) {
175 if (ledinfo->led == ipt_led_names[i].led) {
176 printf("led %s ", ipt_led_names[i].name);
177 break;
178 }
179 }
180 if (!ipt_led_names[i].name)
181 printf("%u ", ledinfo->led);
182 break;
183 case IPT_LED_RESTORE:
184 printf("--restore ");
185 break;
186 default:
187 printf("ERROR: UNKNOWN LED MODE ");
188 break;
189 }
190}
191
192static void
193help(void)
194{
195 unsigned int i;
196
197 printf(
198"LED target options:\n"
199" --led LED LED to set\n"
200" --save Save the LED value in the connection\n"
201" --restore Use the saved LED value\n");
202
203 printf("LED names:\n");
204 for (i = 0; ipt_led_names[i].name; i++)
205 printf(" %s\n", ipt_led_names[i].name);
206}
207
208static
209struct xtables_target led
210= {
211 .name = "LED",
212 .version = XTABLES_VERSION,
213 .family = NFPROTO_IPV4,
214 .size = XT_ALIGN(sizeof(struct ipt_led_info)),
215 .userspacesize = XT_ALIGN(sizeof(struct ipt_led_info)),
216 .help = &help,
217 .init = &init,
218 .parse = &parse,
219 .final_check = &final_check,
220 .print = &print,
221 .save = &save,
222 .extra_opts = opts
223};
224
225void _init(void)
226{
227 xtables_register_target(&led);
228}