blob: f64fd1cf8d913a4e89e9ed7d4e86bb8f07567c0b [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>
Thomas Jaroschecae0c32008-10-23 15:41:27 +02007#include <netinet/in.h>
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +00008#include <xtables.h>
9#include <linux/netfilter/xt_tcpudp.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000010
Jan Engelhardt181dead2007-10-04 16:27:07 +000011static void udp_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000012{
13 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020014"udp match options:\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020015"[!] --source-port port[:port]\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000016" --sport ...\n"
17" match source port(s)\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020018"[!] --destination-port port[:port]\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000019" --dport ...\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020020" match destination port(s)\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000021}
22
Jan Engelhardt181dead2007-10-04 16:27:07 +000023static const struct option udp_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000024 { "source-port", 1, NULL, '1' },
25 { "sport", 1, NULL, '1' }, /* synonym */
26 { "destination-port", 1, NULL, '2' },
27 { "dport", 1, NULL, '2' }, /* synonym */
Max Kellermann9ee386a2008-01-29 13:48:05 +000028 { .name = NULL }
Marc Bouchere6869a82000-03-20 06:03:29 +000029};
30
Marc Bouchere6869a82000-03-20 06:03:29 +000031static void
32parse_udp_ports(const char *portstring, u_int16_t *ports)
33{
34 char *buffer;
35 char *cp;
36
37 buffer = strdup(portstring);
38 if ((cp = strchr(buffer, ':')) == NULL)
Phil Oesterdbac8ad2006-07-20 17:01:54 +000039 ports[0] = ports[1] = parse_port(buffer, "udp");
Marc Bouchere6869a82000-03-20 06:03:29 +000040 else {
41 *cp = '\0';
42 cp++;
43
Phil Oesterdbac8ad2006-07-20 17:01:54 +000044 ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
45 ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
Harald Welted15fb342002-07-26 16:27:57 +000046
47 if (ports[0] > ports[1])
48 exit_error(PARAMETER_PROBLEM,
49 "invalid portrange (min > max)");
Marc Bouchere6869a82000-03-20 06:03:29 +000050 }
51 free(buffer);
52}
53
Jan Engelhardt181dead2007-10-04 16:27:07 +000054static void udp_init(struct xt_entry_match *m)
Marc Bouchere6869a82000-03-20 06:03:29 +000055{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000056 struct xt_udp *udpinfo = (struct xt_udp *)m->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000057
58 udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
59}
60
61#define UDP_SRC_PORTS 0x01
62#define UDP_DST_PORTS 0x02
63
Marc Bouchere6869a82000-03-20 06:03:29 +000064static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000065udp_parse(int c, char **argv, int invert, unsigned int *flags,
66 const void *entry, struct xt_entry_match **match)
Marc Bouchere6869a82000-03-20 06:03:29 +000067{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000068 struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000069
70 switch (c) {
71 case '1':
72 if (*flags & UDP_SRC_PORTS)
73 exit_error(PARAMETER_PROBLEM,
74 "Only one `--source-port' allowed");
Harald Welteb77f1da2002-03-14 11:35:58 +000075 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000076 parse_udp_ports(argv[optind-1], udpinfo->spts);
77 if (invert)
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000078 udpinfo->invflags |= XT_UDP_INV_SRCPT;
Marc Bouchere6869a82000-03-20 06:03:29 +000079 *flags |= UDP_SRC_PORTS;
Marc Bouchere6869a82000-03-20 06:03:29 +000080 break;
81
82 case '2':
83 if (*flags & UDP_DST_PORTS)
84 exit_error(PARAMETER_PROBLEM,
85 "Only one `--destination-port' allowed");
Harald Welteb77f1da2002-03-14 11:35:58 +000086 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000087 parse_udp_ports(argv[optind-1], udpinfo->dpts);
88 if (invert)
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +000089 udpinfo->invflags |= XT_UDP_INV_DSTPT;
Marc Bouchere6869a82000-03-20 06:03:29 +000090 *flags |= UDP_DST_PORTS;
Marc Bouchere6869a82000-03-20 06:03:29 +000091 break;
92
93 default:
94 return 0;
95 }
96
97 return 1;
98}
99
Marc Bouchere6869a82000-03-20 06:03:29 +0000100static char *
101port_to_service(int port)
102{
103 struct servent *service;
104
105 if ((service = getservbyport(htons(port), "udp")))
106 return service->s_name;
107
108 return NULL;
109}
110
111static void
112print_port(u_int16_t port, int numeric)
113{
114 char *service;
115
116 if (numeric || (service = port_to_service(port)) == NULL)
117 printf("%u", port);
118 else
119 printf("%s", service);
120}
121
122static void
123print_ports(const char *name, u_int16_t min, u_int16_t max,
124 int invert, int numeric)
125{
126 const char *inv = invert ? "!" : "";
127
128 if (min != 0 || max != 0xFFFF || invert) {
129 printf("%s", name);
130 if (min == max) {
131 printf(":%s", inv);
132 print_port(min, numeric);
133 } else {
134 printf("s:%s", inv);
135 print_port(min, numeric);
136 printf(":");
137 print_port(max, numeric);
138 }
139 printf(" ");
140 }
141}
142
Marc Bouchere6869a82000-03-20 06:03:29 +0000143static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000144udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000145{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000146 const struct xt_udp *udp = (struct xt_udp *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000147
148 printf("udp ");
149 print_ports("spt", udp->spts[0], udp->spts[1],
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000150 udp->invflags & XT_UDP_INV_SRCPT,
Marc Bouchere6869a82000-03-20 06:03:29 +0000151 numeric);
152 print_ports("dpt", udp->dpts[0], udp->dpts[1],
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000153 udp->invflags & XT_UDP_INV_DSTPT,
Marc Bouchere6869a82000-03-20 06:03:29 +0000154 numeric);
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000155 if (udp->invflags & ~XT_UDP_INV_MASK)
Marc Bouchere6869a82000-03-20 06:03:29 +0000156 printf("Unknown invflags: 0x%X ",
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000157 udp->invflags & ~XT_UDP_INV_MASK);
Marc Bouchere6869a82000-03-20 06:03:29 +0000158}
159
Jan Engelhardt181dead2007-10-04 16:27:07 +0000160static void udp_save(const void *ip, const struct xt_entry_match *match)
Marc Bouchere6869a82000-03-20 06:03:29 +0000161{
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000162 const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000163
164 if (udpinfo->spts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000165 || udpinfo->spts[1] != 0xFFFF) {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000166 if (udpinfo->invflags & XT_UDP_INV_SRCPT)
Marc Bouchere6869a82000-03-20 06:03:29 +0000167 printf("! ");
168 if (udpinfo->spts[0]
169 != udpinfo->spts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000170 printf("--sport %u:%u ",
171 udpinfo->spts[0],
Marc Boucher2382c8c2000-04-07 17:32:49 +0000172 udpinfo->spts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000173 else
174 printf("--sport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000175 udpinfo->spts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000176 }
177
178 if (udpinfo->dpts[0] != 0
Rusty Russell73f72f52000-07-03 10:17:57 +0000179 || udpinfo->dpts[1] != 0xFFFF) {
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000180 if (udpinfo->invflags & XT_UDP_INV_DSTPT)
Marc Bouchere6869a82000-03-20 06:03:29 +0000181 printf("! ");
182 if (udpinfo->dpts[0]
183 != udpinfo->dpts[1])
Marc Boucher9f2009c2000-04-07 17:30:28 +0000184 printf("--dport %u:%u ",
185 udpinfo->dpts[0],
186 udpinfo->dpts[1]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000187 else
188 printf("--dport %u ",
Marc Boucher9f2009c2000-04-07 17:30:28 +0000189 udpinfo->dpts[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +0000190 }
191}
192
Jan Engelhardt181dead2007-10-04 16:27:07 +0000193static struct xtables_match udp_match = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100194 .family = NFPROTO_IPV4,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000195 .name = "udp",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200196 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000197 .size = XT_ALIGN(sizeof(struct xt_udp)),
198 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000199 .help = udp_help,
200 .init = udp_init,
201 .parse = udp_parse,
202 .print = udp_print,
203 .save = udp_save,
204 .extra_opts = udp_opts,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000205};
206
Jan Engelhardt181dead2007-10-04 16:27:07 +0000207static struct xtables_match udp_match6 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100208 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000209 .name = "udp",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200210 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI17908e42007-07-24 06:56:21 +0000211 .size = XT_ALIGN(sizeof(struct xt_udp)),
212 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000213 .help = udp_help,
214 .init = udp_init,
215 .parse = udp_parse,
216 .print = udp_print,
217 .save = udp_save,
218 .extra_opts = udp_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000219};
220
221void
222_init(void)
223{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000224 xtables_register_match(&udp_match);
225 xtables_register_match(&udp_match6);
Marc Bouchere6869a82000-03-20 06:03:29 +0000226}