blob: 06c61c515d19e40688d54bd11bb12c3c1645cd79 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Shared library add-on to iptables to add UDP support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7#include <iptables.h>
8#include <linux/netfilter_ipv4/ip_tables.h>
9
10/* Function which prints out usage message. */
11static void
12help(void)
13{
14 printf(
15"UDP v%s options:\n"
16" --source-port [!] port[:port]\n"
17" --sport ...\n"
18" match source port(s)\n"
19" --destination-port [!] port[:port]\n"
20" --dport ...\n"
21" match destination port(s)\n",
22NETFILTER_VERSION);
23}
24
25static struct option opts[] = {
26 { "source-port", 1, 0, '1' },
27 { "sport", 1, 0, '1' }, /* synonym */
28 { "destination-port", 1, 0, '2' },
29 { "dport", 1, 0, '2' }, /* synonym */
30 {0}
31};
32
33static int
34service_to_port(const char *name)
35{
36 struct servent *service;
37
38 if ((service = getservbyname(name, "udp")) != NULL)
39 return ntohs((unsigned short) service->s_port);
40
41 return -1;
42}
43
44static u_int16_t
45parse_udp_port(const char *port)
46{
47 int portnum;
48
49 if ((portnum = string_to_number(port, 0, 65535)) != -1 ||
50 (portnum = service_to_port(port)) != -1)
51 return (u_int16_t)portnum;
52
53 exit_error(PARAMETER_PROBLEM,
54 "invalid UDP port/service `%s' specified", port);
55 }
56
57static void
58parse_udp_ports(const char *portstring, u_int16_t *ports)
59{
60 char *buffer;
61 char *cp;
62
63 buffer = strdup(portstring);
64 if ((cp = strchr(buffer, ':')) == NULL)
65 ports[0] = ports[1] = parse_udp_port(buffer);
66 else {
67 *cp = '\0';
68 cp++;
69
70 ports[0] = buffer[0] ? parse_udp_port(buffer) : 0;
71 ports[1] = cp[0] ? parse_udp_port(cp) : 0xFFFF;
72 }
73 free(buffer);
74}
75
76/* Initialize the match. */
77static void
78init(struct ipt_entry_match *m, unsigned int *nfcache)
79{
80 struct ipt_udp *udpinfo = (struct ipt_udp *)m->data;
81
82 udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
83}
84
85#define UDP_SRC_PORTS 0x01
86#define UDP_DST_PORTS 0x02
87
88/* Function which parses command options; returns true if it
89 ate an option */
90static int
91parse(int c, char **argv, int invert, unsigned int *flags,
92 const struct ipt_entry *entry,
93 unsigned int *nfcache,
94 struct ipt_entry_match **match)
95{
96 struct ipt_udp *udpinfo = (struct ipt_udp *)(*match)->data;
97
98 switch (c) {
99 case '1':
100 if (*flags & UDP_SRC_PORTS)
101 exit_error(PARAMETER_PROBLEM,
102 "Only one `--source-port' allowed");
103 if (check_inverse(optarg, &invert))
104 optind++;
105 parse_udp_ports(argv[optind-1], udpinfo->spts);
106 if (invert)
107 udpinfo->invflags |= IPT_UDP_INV_SRCPT;
108 *flags |= UDP_SRC_PORTS;
109 *nfcache |= NFC_IP_SRC_PT;
110 break;
111
112 case '2':
113 if (*flags & UDP_DST_PORTS)
114 exit_error(PARAMETER_PROBLEM,
115 "Only one `--destination-port' allowed");
116 if (check_inverse(optarg, &invert))
117 optind++;
118 parse_udp_ports(argv[optind-1], udpinfo->dpts);
119 if (invert)
120 udpinfo->invflags |= IPT_UDP_INV_DSTPT;
121 *flags |= UDP_DST_PORTS;
122 *nfcache |= NFC_IP_DST_PT;
123 break;
124
125 default:
126 return 0;
127 }
128
129 return 1;
130}
131
132/* Final check; we don't care. */
133static void
134final_check(unsigned int flags)
135{
136}
137
138static char *
139port_to_service(int port)
140{
141 struct servent *service;
142
143 if ((service = getservbyport(htons(port), "udp")))
144 return service->s_name;
145
146 return NULL;
147}
148
149static void
150print_port(u_int16_t port, int numeric)
151{
152 char *service;
153
154 if (numeric || (service = port_to_service(port)) == NULL)
155 printf("%u", port);
156 else
157 printf("%s", service);
158}
159
160static void
161print_ports(const char *name, u_int16_t min, u_int16_t max,
162 int invert, int numeric)
163{
164 const char *inv = invert ? "!" : "";
165
166 if (min != 0 || max != 0xFFFF || invert) {
167 printf("%s", name);
168 if (min == max) {
169 printf(":%s", inv);
170 print_port(min, numeric);
171 } else {
172 printf("s:%s", inv);
173 print_port(min, numeric);
174 printf(":");
175 print_port(max, numeric);
176 }
177 printf(" ");
178 }
179}
180
181/* Prints out the union ipt_matchinfo. */
182static void
183print(const struct ipt_ip *ip,
184 const struct ipt_entry_match *match, int numeric)
185{
186 const struct ipt_udp *udp = (struct ipt_udp *)match->data;
187
188 printf("udp ");
189 print_ports("spt", udp->spts[0], udp->spts[1],
190 udp->invflags & IPT_UDP_INV_SRCPT,
191 numeric);
192 print_ports("dpt", udp->dpts[0], udp->dpts[1],
193 udp->invflags & IPT_UDP_INV_DSTPT,
194 numeric);
195 if (udp->invflags & ~IPT_UDP_INV_MASK)
196 printf("Unknown invflags: 0x%X ",
197 udp->invflags & ~IPT_UDP_INV_MASK);
198}
199
200/* Saves the union ipt_matchinfo in parsable form to stdout. */
201static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
202{
203 const struct ipt_udp *udpinfo = (struct ipt_udp *)match->data;
204
205 if (udpinfo->spts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000206 || udpinfo->spts[1] != 0xFFFF) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000207 if (udpinfo->invflags & IPT_UDP_INV_SRCPT)
208 printf("! ");
209 if (udpinfo->spts[0]
210 != udpinfo->spts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000211 printf("--sport %u:%u ",
212 udpinfo->spts[0],
Marc Boucher2382c8c2000-04-07 17:32:49 +0000213 udpinfo->spts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000214 else
215 printf("--sport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000216 udpinfo->spts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000217 }
218
219 if (udpinfo->dpts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000220 || udpinfo->dpts[1] != 0xFFFF) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000221 if (udpinfo->invflags & IPT_UDP_INV_DSTPT)
222 printf("! ");
223 if (udpinfo->dpts[0]
224 != udpinfo->dpts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000225 printf("--dport %u:%u ",
226 udpinfo->dpts[0],
227 udpinfo->dpts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000228 else
229 printf("--dport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000230 udpinfo->dpts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000231 }
232}
233
234struct iptables_match udp
235= { NULL,
236 "udp",
237 NETFILTER_VERSION,
Rusty Russell73f72f52000-07-03 10:17:57 +0000238 IPT_ALIGN(sizeof(struct ipt_udp)),
239 IPT_ALIGN(sizeof(struct ipt_udp)),
Marc Bouchere6869a82000-03-20 06:03:29 +0000240 &help,
241 &init,
242 &parse,
243 &final_check,
244 &print,
245 &save,
246 opts
247};
248
249void
250_init(void)
251{
252 register_match(&udp);
253}