blob: dd64a406007c06d595b68a18a49015d8d689c767 [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>
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +00007#include <xtables.h>
8#include <linux/netfilter/xt_tcpudp.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00009
10/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000011static void udp_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000012{
13 printf(
14"UDP v%s options:\n"
15" --source-port [!] port[:port]\n"
16" --sport ...\n"
17" match source port(s)\n"
18" --destination-port [!] port[:port]\n"
19" --dport ...\n"
20" match destination port(s)\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000021IPTABLES_VERSION);
Marc Bouchere6869a82000-03-20 06:03:29 +000022}
23
Jan Engelhardt181dead2007-10-04 16:27:07 +000024static const struct option udp_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000025 { "source-port", 1, NULL, '1' },
26 { "sport", 1, NULL, '1' }, /* synonym */
27 { "destination-port", 1, NULL, '2' },
28 { "dport", 1, NULL, '2' }, /* synonym */
29 { }
Marc Bouchere6869a82000-03-20 06:03:29 +000030};
31
Marc Bouchere6869a82000-03-20 06:03:29 +000032static void
33parse_udp_ports(const char *portstring, u_int16_t *ports)
34{
35 char *buffer;
36 char *cp;
37
38 buffer = strdup(portstring);
39 if ((cp = strchr(buffer, ':')) == NULL)
Phil Oesterdbac8ad2006-07-20 17:01:54 +000040 ports[0] = ports[1] = parse_port(buffer, "udp");
Marc Bouchere6869a82000-03-20 06:03:29 +000041 else {
42 *cp = '\0';
43 cp++;
44
Phil Oesterdbac8ad2006-07-20 17:01:54 +000045 ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
46 ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
Harald Welted15fb342002-07-26 16:27:57 +000047
48 if (ports[0] > ports[1])
49 exit_error(PARAMETER_PROBLEM,
50 "invalid portrange (min > max)");
Marc Bouchere6869a82000-03-20 06:03:29 +000051 }
52 free(buffer);
53}
54
55/* Initialize the match. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000056static void udp_init(struct xt_entry_match *m)
Marc Bouchere6869a82000-03-20 06:03:29 +000057{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000058 struct xt_udp *udpinfo = (struct xt_udp *)m->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000059
60 udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
61}
62
63#define UDP_SRC_PORTS 0x01
64#define UDP_DST_PORTS 0x02
65
66/* Function which parses command options; returns true if it
67 ate an option */
68static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000069udp_parse(int c, char **argv, int invert, unsigned int *flags,
70 const void *entry, struct xt_entry_match **match)
Marc Bouchere6869a82000-03-20 06:03:29 +000071{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000072 struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000073
74 switch (c) {
75 case '1':
76 if (*flags & UDP_SRC_PORTS)
77 exit_error(PARAMETER_PROBLEM,
78 "Only one `--source-port' allowed");
Harald Welteb77f1da2002-03-14 11:35:58 +000079 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000080 parse_udp_ports(argv[optind-1], udpinfo->spts);
81 if (invert)
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000082 udpinfo->invflags |= XT_UDP_INV_SRCPT;
Marc Bouchere6869a82000-03-20 06:03:29 +000083 *flags |= UDP_SRC_PORTS;
Marc Bouchere6869a82000-03-20 06:03:29 +000084 break;
85
86 case '2':
87 if (*flags & UDP_DST_PORTS)
88 exit_error(PARAMETER_PROBLEM,
89 "Only one `--destination-port' allowed");
Harald Welteb77f1da2002-03-14 11:35:58 +000090 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000091 parse_udp_ports(argv[optind-1], udpinfo->dpts);
92 if (invert)
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000093 udpinfo->invflags |= XT_UDP_INV_DSTPT;
Marc Bouchere6869a82000-03-20 06:03:29 +000094 *flags |= UDP_DST_PORTS;
Marc Bouchere6869a82000-03-20 06:03:29 +000095 break;
96
97 default:
98 return 0;
99 }
100
101 return 1;
102}
103
Marc Bouchere6869a82000-03-20 06:03:29 +0000104static char *
105port_to_service(int port)
106{
107 struct servent *service;
108
109 if ((service = getservbyport(htons(port), "udp")))
110 return service->s_name;
111
112 return NULL;
113}
114
115static void
116print_port(u_int16_t port, int numeric)
117{
118 char *service;
119
120 if (numeric || (service = port_to_service(port)) == NULL)
121 printf("%u", port);
122 else
123 printf("%s", service);
124}
125
126static void
127print_ports(const char *name, u_int16_t min, u_int16_t max,
128 int invert, int numeric)
129{
130 const char *inv = invert ? "!" : "";
131
132 if (min != 0 || max != 0xFFFF || invert) {
133 printf("%s", name);
134 if (min == max) {
135 printf(":%s", inv);
136 print_port(min, numeric);
137 } else {
138 printf("s:%s", inv);
139 print_port(min, numeric);
140 printf(":");
141 print_port(max, numeric);
142 }
143 printf(" ");
144 }
145}
146
147/* Prints out the union ipt_matchinfo. */
148static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000149udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000150{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000151 const struct xt_udp *udp = (struct xt_udp *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000152
153 printf("udp ");
154 print_ports("spt", udp->spts[0], udp->spts[1],
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000155 udp->invflags & XT_UDP_INV_SRCPT,
Marc Bouchere6869a82000-03-20 06:03:29 +0000156 numeric);
157 print_ports("dpt", udp->dpts[0], udp->dpts[1],
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000158 udp->invflags & XT_UDP_INV_DSTPT,
Marc Bouchere6869a82000-03-20 06:03:29 +0000159 numeric);
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000160 if (udp->invflags & ~XT_UDP_INV_MASK)
Marc Bouchere6869a82000-03-20 06:03:29 +0000161 printf("Unknown invflags: 0x%X ",
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000162 udp->invflags & ~XT_UDP_INV_MASK);
Marc Bouchere6869a82000-03-20 06:03:29 +0000163}
164
165/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000166static void udp_save(const void *ip, const struct xt_entry_match *match)
Marc Bouchere6869a82000-03-20 06:03:29 +0000167{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000168 const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000169
170 if (udpinfo->spts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000171 || udpinfo->spts[1] != 0xFFFF) {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000172 if (udpinfo->invflags & XT_UDP_INV_SRCPT)
Marc Bouchere6869a82000-03-20 06:03:29 +0000173 printf("! ");
174 if (udpinfo->spts[0]
175 != udpinfo->spts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000176 printf("--sport %u:%u ",
177 udpinfo->spts[0],
Marc Boucher2382c8c2000-04-07 17:32:49 +0000178 udpinfo->spts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000179 else
180 printf("--sport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000181 udpinfo->spts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000182 }
183
184 if (udpinfo->dpts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000185 || udpinfo->dpts[1] != 0xFFFF) {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000186 if (udpinfo->invflags & XT_UDP_INV_DSTPT)
Marc Bouchere6869a82000-03-20 06:03:29 +0000187 printf("! ");
188 if (udpinfo->dpts[0]
189 != udpinfo->dpts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000190 printf("--dport %u:%u ",
191 udpinfo->dpts[0],
192 udpinfo->dpts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000193 else
194 printf("--dport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000195 udpinfo->dpts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000196 }
197}
198
Jan Engelhardt181dead2007-10-04 16:27:07 +0000199static struct xtables_match udp_match = {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000200 .family = AF_INET,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000201 .name = "udp",
202 .version = IPTABLES_VERSION,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000203 .size = XT_ALIGN(sizeof(struct xt_udp)),
204 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000205 .help = udp_help,
206 .init = udp_init,
207 .parse = udp_parse,
208 .print = udp_print,
209 .save = udp_save,
210 .extra_opts = udp_opts,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000211};
212
Jan Engelhardt181dead2007-10-04 16:27:07 +0000213static struct xtables_match udp_match6 = {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000214 .family = AF_INET6,
215 .name = "udp",
216 .version = IPTABLES_VERSION,
217 .size = XT_ALIGN(sizeof(struct xt_udp)),
218 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000219 .help = udp_help,
220 .init = udp_init,
221 .parse = udp_parse,
222 .print = udp_print,
223 .save = udp_save,
224 .extra_opts = udp_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000225};
226
227void
228_init(void)
229{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000230 xtables_register_match(&udp_match);
231 xtables_register_match(&udp_match6);
Marc Bouchere6869a82000-03-20 06:03:29 +0000232}