libxt_udp.c revision 03d99486d8283552705b58dc55b6085dffc38792
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 11static 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 23static 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 31static 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) 39 ports[0] = ports[1] = parse_port(buffer, "udp"); 40 else { 41 *cp = '\0'; 42 cp++; 43 44 ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0; 45 ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF; 46 47 if (ports[0] > ports[1]) 48 exit_error(PARAMETER_PROBLEM, 49 "invalid portrange (min > max)"); 50 } 51 free(buffer); 52} 53 54static 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 64static int 65udp_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 exit_error(PARAMETER_PROBLEM, 74 "Only one `--source-port' allowed"); 75 check_inverse(optarg, &invert, &optind, 0); 76 parse_udp_ports(argv[optind-1], 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 exit_error(PARAMETER_PROBLEM, 85 "Only one `--destination-port' allowed"); 86 check_inverse(optarg, &invert, &optind, 0); 87 parse_udp_ports(argv[optind-1], 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 100static 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 143static void 144udp_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 160static 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 193static struct xtables_match udp_match = { 194 .family = NFPROTO_IPV4, 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 207static struct xtables_match udp_match6 = { 208 .family = NFPROTO_IPV6, 209 .name = "udp", 210 .version = XTABLES_VERSION, 211 .size = XT_ALIGN(sizeof(struct xt_udp)), 212 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)), 213 .help = udp_help, 214 .init = udp_init, 215 .parse = udp_parse, 216 .print = udp_print, 217 .save = udp_save, 218 .extra_opts = udp_opts, 219}; 220 221void 222_init(void) 223{ 224 xtables_register_match(&udp_match); 225 xtables_register_match(&udp_match6); 226} 227