yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame] | 1 | /* 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 | |
| 12 | static 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 | |
| 19 | static void |
| 20 | init(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 | |
| 28 | struct ipt_led_names { |
| 29 | const char *name; |
| 30 | u_int32_t led; |
| 31 | }; |
| 32 | |
| 33 | static struct ipt_led_names ipt_led_names[] = { |
| 34 | #include "libipt_LED_def.c" |
| 35 | { } |
| 36 | }; |
| 37 | |
| 38 | static u_int32_t |
| 39 | parse_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 | |
| 74 | static int |
| 75 | parse(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 | |
| 116 | static void |
| 117 | final_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 | |
| 128 | static void |
| 129 | print(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 | |
| 161 | static void |
| 162 | save(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 | |
| 192 | static void |
| 193 | help(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 | |
| 208 | static |
| 209 | struct 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 | |
| 225 | void _init(void) |
| 226 | { |
| 227 | xtables_register_target(&led); |
| 228 | } |