Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_udp.c
1 /* 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 <netinet/in.h>
8 #include <xtables.h>
9 #include <linux/netfilter/xt_tcpudp.h>
10
11 static void udp_help(void)
12 {
13         printf(
14 "udp match 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");
21 }
22
23 static const struct option udp_opts[] = {
24         { "source-port", 1, NULL, '1' },
25         { "sport", 1, NULL, '1' }, /* synonym */
26         { "destination-port", 1, NULL, '2' },
27         { "dport", 1, NULL, '2' }, /* synonym */
28         { .name = NULL }
29 };
30
31 static void
32 parse_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)
39                 ports[0] = ports[1] = xtables_parse_port(buffer, "udp");
40         else {
41                 *cp = '\0';
42                 cp++;
43
44                 ports[0] = buffer[0] ? xtables_parse_port(buffer, "udp") : 0;
45                 ports[1] = cp[0] ? xtables_parse_port(cp, "udp") : 0xFFFF;
46
47                 if (ports[0] > ports[1])
48                         xtables_error(PARAMETER_PROBLEM,
49                                    "invalid portrange (min > max)");
50         }
51         free(buffer);
52 }
53
54 static void udp_init(struct xt_entry_match *m)
55 {
56         struct xt_udp *udpinfo = (struct xt_udp *)m->data;
57
58         udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
59 }
60
61 #define UDP_SRC_PORTS 0x01
62 #define UDP_DST_PORTS 0x02
63
64 static int
65 udp_parse(int c, char **argv, int invert, unsigned int *flags,
66           const void *entry, struct xt_entry_match **match)
67 {
68         struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data;
69
70         switch (c) {
71         case '1':
72                 if (*flags & UDP_SRC_PORTS)
73                         xtables_error(PARAMETER_PROBLEM,
74                                    "Only one `--source-port' allowed");
75                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
76                 parse_udp_ports(optarg, udpinfo->spts);
77                 if (invert)
78                         udpinfo->invflags |= XT_UDP_INV_SRCPT;
79                 *flags |= UDP_SRC_PORTS;
80                 break;
81
82         case '2':
83                 if (*flags & UDP_DST_PORTS)
84                         xtables_error(PARAMETER_PROBLEM,
85                                    "Only one `--destination-port' allowed");
86                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
87                 parse_udp_ports(optarg, udpinfo->dpts);
88                 if (invert)
89                         udpinfo->invflags |= XT_UDP_INV_DSTPT;
90                 *flags |= UDP_DST_PORTS;
91                 break;
92
93         default:
94                 return 0;
95         }
96
97         return 1;
98 }
99
100 static char *
101 port_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
111 static void
112 print_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
122 static void
123 print_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
143 static void
144 udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
145 {
146         const struct xt_udp *udp = (struct xt_udp *)match->data;
147
148         printf("udp ");
149         print_ports("spt", udp->spts[0], udp->spts[1],
150                     udp->invflags & XT_UDP_INV_SRCPT,
151                     numeric);
152         print_ports("dpt", udp->dpts[0], udp->dpts[1],
153                     udp->invflags & XT_UDP_INV_DSTPT,
154                     numeric);
155         if (udp->invflags & ~XT_UDP_INV_MASK)
156                 printf("Unknown invflags: 0x%X ",
157                        udp->invflags & ~XT_UDP_INV_MASK);
158 }
159
160 static void udp_save(const void *ip, const struct xt_entry_match *match)
161 {
162         const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
163
164         if (udpinfo->spts[0] != 0
165             || udpinfo->spts[1] != 0xFFFF) {
166                 if (udpinfo->invflags & XT_UDP_INV_SRCPT)
167                         printf("! ");
168                 if (udpinfo->spts[0]
169                     != udpinfo->spts[1])
170                         printf("--sport %u:%u ",
171                                udpinfo->spts[0],
172                                udpinfo->spts[1]);
173                 else
174                         printf("--sport %u ",
175                                udpinfo->spts[0]);
176         }
177
178         if (udpinfo->dpts[0] != 0
179             || udpinfo->dpts[1] != 0xFFFF) {
180                 if (udpinfo->invflags & XT_UDP_INV_DSTPT)
181                         printf("! ");
182                 if (udpinfo->dpts[0]
183                     != udpinfo->dpts[1])
184                         printf("--dport %u:%u ",
185                                udpinfo->dpts[0],
186                                udpinfo->dpts[1]);
187                 else
188                         printf("--dport %u ",
189                                udpinfo->dpts[0]);
190         }
191 }
192
193 static struct xtables_match udp_match = {
194         .family         = NFPROTO_UNSPEC,
195         .name           = "udp",
196         .version        = XTABLES_VERSION,
197         .size           = XT_ALIGN(sizeof(struct xt_udp)),
198         .userspacesize  = XT_ALIGN(sizeof(struct xt_udp)),
199         .help           = udp_help,
200         .init           = udp_init,
201         .parse          = udp_parse,
202         .print          = udp_print,
203         .save           = udp_save,
204         .extra_opts     = udp_opts,
205 };
206
207 void
208 _init(void)
209 {
210         xtables_register_match(&udp_match);
211 }