Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_TRIGGER.c
blob0a56a4fa64328b7ed57df5fe7d137633e2a4956f
1 /* Port-triggering target.
3 * Copyright (C) 2003, CyberTAN Corporation
4 * All Rights Reserved.
5 */
7 /* Shared library add-on to iptables to add port-trigger support. */
9 #include <stdio.h>
10 #include <netdb.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <getopt.h>
14 #include <iptables.h>
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ip_nat_rule.h>
17 #include <linux/netfilter_ipv4/ipt_TRIGGER.h>
19 /* Function which prints out usage message. */
20 static void
21 help(void)
23 printf(
24 "TRIGGER v%s options:\n"
25 " --trigger-type (dnat|in|out)\n"
26 " Trigger type\n"
27 " --trigger-proto proto\n"
28 " Trigger protocol\n"
29 " --trigger-match port[-port]\n"
30 " Trigger destination port range\n"
31 " --trigger-relate port[-port]\n"
32 " Port range to map related destination port range to.\n\n",
33 IPTABLES_VERSION);
36 static struct option opts[] = {
37 { "trigger-type", 1, 0, '1' },
38 { "trigger-proto", 1, 0, '2' },
39 { "trigger-match", 1, 0, '3' },
40 { "trigger-relate", 1, 0, '4' },
41 { 0 }
44 /* Initialize the target. */
45 static void
46 init(struct ipt_entry_target *t, unsigned int *nfcache)
48 /* Can't cache this */
49 *nfcache |= NFC_UNKNOWN;
52 /* Parses ports */
53 static void
54 parse_ports(const char *arg, u_int16_t *ports)
56 const char *dash;
57 int port;
59 port = atoi(arg);
60 if (port == 0 || port > 65535)
61 exit_error(PARAMETER_PROBLEM, "Port range `%s' invalid\n", arg);
63 dash = strchr(arg, '-');
64 if (!dash)
65 ports[0] = ports[1] = port;
66 else {
67 int maxport;
69 maxport = atoi(dash + 1);
70 if (maxport == 0 || maxport > 65535)
71 exit_error(PARAMETER_PROBLEM,
72 "Port range `%s' invalid\n", dash+1);
73 if (maxport < port)
74 exit_error(PARAMETER_PROBLEM,
75 "Port range `%s' invalid\n", arg);
76 ports[0] = port;
77 ports[1] = maxport;
82 /* Function which parses command options; returns true if it
83 ate an option */
84 static int
85 parse(int c, char **argv, int invert, unsigned int *flags,
86 const struct ipt_entry *entry,
87 struct ipt_entry_target **target)
89 struct ipt_trigger_info *info = (struct ipt_trigger_info *)(*target)->data;
91 switch (c) {
92 case '1':
93 if (!strcasecmp(optarg, "dnat"))
94 info->type = IPT_TRIGGER_DNAT;
95 else if (!strcasecmp(optarg, "in"))
96 info->type = IPT_TRIGGER_IN;
97 else if (!strcasecmp(optarg, "out"))
98 info->type = IPT_TRIGGER_OUT;
99 else
100 exit_error(PARAMETER_PROBLEM,
101 "unknown type `%s' specified", optarg);
102 return 1;
104 case '2':
105 if (!strcasecmp(optarg, "tcp"))
106 info->proto = IPPROTO_TCP;
107 else if (!strcasecmp(optarg, "udp"))
108 info->proto = IPPROTO_UDP;
109 else if (!strcasecmp(optarg, "all"))
110 info->proto = 0;
111 else
112 exit_error(PARAMETER_PROBLEM,
113 "unknown protocol `%s' specified", optarg);
114 return 1;
116 case '3':
117 if (check_inverse(optarg, &invert, &optind, 0))
118 exit_error(PARAMETER_PROBLEM,
119 "Unexpected `!' after --trigger-match");
121 parse_ports(optarg, info->ports.mport);
122 return 1;
124 case '4':
125 if (check_inverse(optarg, &invert, &optind, 0))
126 exit_error(PARAMETER_PROBLEM,
127 "Unexpected `!' after --trigger-relate");
129 parse_ports(optarg, info->ports.rport);
130 *flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
131 return 1;
133 default:
134 return 0;
138 /* Final check; don't care. */
139 static void final_check(unsigned int flags)
143 /* Prints out the targinfo. */
144 static void
145 print(const struct ipt_ip *ip,
146 const struct ipt_entry_target *target,
147 int numeric)
149 struct ipt_trigger_info *info = (struct ipt_trigger_info *)target->data;
151 printf("TRIGGER ");
152 if (info->type == IPT_TRIGGER_DNAT)
153 printf("type:dnat ");
154 else if (info->type == IPT_TRIGGER_IN)
155 printf("type:in ");
156 else if (info->type == IPT_TRIGGER_OUT)
157 printf("type:out ");
159 if (info->proto == IPPROTO_TCP)
160 printf("tcp ");
161 else if (info->proto == IPPROTO_UDP)
162 printf("udp ");
164 printf("match:%hu", info->ports.mport[0]);
165 if (info->ports.mport[1] > info->ports.mport[0])
166 printf("-%hu", info->ports.mport[1]);
167 printf(" ");
169 printf("relate:%hu", info->ports.rport[0]);
170 if (info->ports.rport[1] > info->ports.rport[0])
171 printf("-%hu", info->ports.rport[1]);
172 printf(" ");
175 /* Saves the union ipt_targinfo in parsable form to stdout. */
176 static void
177 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
179 struct ipt_trigger_info *info = (struct ipt_trigger_info *)target->data;
181 printf("--trigger-proto ");
182 if (info->proto == IPPROTO_TCP)
183 printf("tcp ");
184 else if (info->proto == IPPROTO_UDP)
185 printf("udp ");
186 printf("--trigger-match %hu-%hu ", info->ports.mport[0], info->ports.mport[1]);
187 printf("--trigger-relate %hu-%hu ", info->ports.rport[0], info->ports.rport[1]);
190 static struct iptables_target trigger = {
191 .next = NULL,
192 .name = "TRIGGER",
193 .version = IPTABLES_VERSION,
194 .size = IPT_ALIGN(sizeof(struct ipt_trigger_info)),
195 .userspacesize = IPT_ALIGN(sizeof(struct ipt_trigger_info)),
196 .help = &help,
197 .init = &init,
198 .parse = &parse,
199 .final_check = &final_check,
200 .print = &print,
201 .save = &save,
202 .extra_opts = opts
205 void _init(void)
207 register_target(&trigger);