libxt_udp.c revision 9ee386a1b6d7704b259460152c959ab0e79e02aa
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 <xtables.h> 8#include <linux/netfilter/xt_tcpudp.h> 9 10/* Function which prints out usage message. */ 11static void udp_help(void) 12{ 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", 21IPTABLES_VERSION); 22} 23 24static const struct option udp_opts[] = { 25 { "source-port", 1, NULL, '1' }, 26 { "sport", 1, NULL, '1' }, /* synonym */ 27 { "destination-port", 1, NULL, '2' }, 28 { "dport", 1, NULL, '2' }, /* synonym */ 29 { .name = NULL } 30}; 31 32static 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) 40 ports[0] = ports[1] = parse_port(buffer, "udp"); 41 else { 42 *cp = '\0'; 43 cp++; 44 45 ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0; 46 ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF; 47 48 if (ports[0] > ports[1]) 49 exit_error(PARAMETER_PROBLEM, 50 "invalid portrange (min > max)"); 51 } 52 free(buffer); 53} 54 55/* Initialize the match. */ 56static void udp_init(struct xt_entry_match *m) 57{ 58 struct xt_udp *udpinfo = (struct xt_udp *)m->data; 59 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 69udp_parse(int c, char **argv, int invert, unsigned int *flags, 70 const void *entry, struct xt_entry_match **match) 71{ 72 struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data; 73 74 switch (c) { 75 case '1': 76 if (*flags & UDP_SRC_PORTS) 77 exit_error(PARAMETER_PROBLEM, 78 "Only one `--source-port' allowed"); 79 check_inverse(optarg, &invert, &optind, 0); 80 parse_udp_ports(argv[optind-1], udpinfo->spts); 81 if (invert) 82 udpinfo->invflags |= XT_UDP_INV_SRCPT; 83 *flags |= UDP_SRC_PORTS; 84 break; 85 86 case '2': 87 if (*flags & UDP_DST_PORTS) 88 exit_error(PARAMETER_PROBLEM, 89 "Only one `--destination-port' allowed"); 90 check_inverse(optarg, &invert, &optind, 0); 91 parse_udp_ports(argv[optind-1], udpinfo->dpts); 92 if (invert) 93 udpinfo->invflags |= XT_UDP_INV_DSTPT; 94 *flags |= UDP_DST_PORTS; 95 break; 96 97 default: 98 return 0; 99 } 100 101 return 1; 102} 103 104static 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 149udp_print(const void *ip, const struct xt_entry_match *match, int numeric) 150{ 151 const struct xt_udp *udp = (struct xt_udp *)match->data; 152 153 printf("udp "); 154 print_ports("spt", udp->spts[0], udp->spts[1], 155 udp->invflags & XT_UDP_INV_SRCPT, 156 numeric); 157 print_ports("dpt", udp->dpts[0], udp->dpts[1], 158 udp->invflags & XT_UDP_INV_DSTPT, 159 numeric); 160 if (udp->invflags & ~XT_UDP_INV_MASK) 161 printf("Unknown invflags: 0x%X ", 162 udp->invflags & ~XT_UDP_INV_MASK); 163} 164 165/* Saves the union ipt_matchinfo in parsable form to stdout. */ 166static void udp_save(const void *ip, const struct xt_entry_match *match) 167{ 168 const struct xt_udp *udpinfo = (struct xt_udp *)match->data; 169 170 if (udpinfo->spts[0] != 0 171 || udpinfo->spts[1] != 0xFFFF) { 172 if (udpinfo->invflags & XT_UDP_INV_SRCPT) 173 printf("! "); 174 if (udpinfo->spts[0] 175 != udpinfo->spts[1]) 176 printf("--sport %u:%u ", 177 udpinfo->spts[0], 178 udpinfo->spts[1]); 179 else 180 printf("--sport %u ", 181 udpinfo->spts[0]); 182 } 183 184 if (udpinfo->dpts[0] != 0 185 || udpinfo->dpts[1] != 0xFFFF) { 186 if (udpinfo->invflags & XT_UDP_INV_DSTPT) 187 printf("! "); 188 if (udpinfo->dpts[0] 189 != udpinfo->dpts[1]) 190 printf("--dport %u:%u ", 191 udpinfo->dpts[0], 192 udpinfo->dpts[1]); 193 else 194 printf("--dport %u ", 195 udpinfo->dpts[0]); 196 } 197} 198 199static struct xtables_match udp_match = { 200 .family = AF_INET, 201 .name = "udp", 202 .version = IPTABLES_VERSION, 203 .size = XT_ALIGN(sizeof(struct xt_udp)), 204 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)), 205 .help = udp_help, 206 .init = udp_init, 207 .parse = udp_parse, 208 .print = udp_print, 209 .save = udp_save, 210 .extra_opts = udp_opts, 211}; 212 213static struct xtables_match udp_match6 = { 214 .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)), 219 .help = udp_help, 220 .init = udp_init, 221 .parse = udp_parse, 222 .print = udp_print, 223 .save = udp_save, 224 .extra_opts = udp_opts, 225}; 226 227void 228_init(void) 229{ 230 xtables_register_match(&udp_match); 231 xtables_register_match(&udp_match6); 232} 233