libxt_udp.c revision 8b7c64d6ba156a99008fcd810cba874c73294333
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 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 54/* Initialize the match. */ 55static void udp_init(struct xt_entry_match *m) 56{ 57 struct xt_udp *udpinfo = (struct xt_udp *)m->data; 58 59 udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF; 60} 61 62#define UDP_SRC_PORTS 0x01 63#define UDP_DST_PORTS 0x02 64 65/* Function which parses command options; returns true if it 66 ate an option */ 67static int 68udp_parse(int c, char **argv, int invert, unsigned int *flags, 69 const void *entry, struct xt_entry_match **match) 70{ 71 struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data; 72 73 switch (c) { 74 case '1': 75 if (*flags & UDP_SRC_PORTS) 76 exit_error(PARAMETER_PROBLEM, 77 "Only one `--source-port' allowed"); 78 check_inverse(optarg, &invert, &optind, 0); 79 parse_udp_ports(argv[optind-1], udpinfo->spts); 80 if (invert) 81 udpinfo->invflags |= XT_UDP_INV_SRCPT; 82 *flags |= UDP_SRC_PORTS; 83 break; 84 85 case '2': 86 if (*flags & UDP_DST_PORTS) 87 exit_error(PARAMETER_PROBLEM, 88 "Only one `--destination-port' allowed"); 89 check_inverse(optarg, &invert, &optind, 0); 90 parse_udp_ports(argv[optind-1], udpinfo->dpts); 91 if (invert) 92 udpinfo->invflags |= XT_UDP_INV_DSTPT; 93 *flags |= UDP_DST_PORTS; 94 break; 95 96 default: 97 return 0; 98 } 99 100 return 1; 101} 102 103static char * 104port_to_service(int port) 105{ 106 struct servent *service; 107 108 if ((service = getservbyport(htons(port), "udp"))) 109 return service->s_name; 110 111 return NULL; 112} 113 114static void 115print_port(u_int16_t port, int numeric) 116{ 117 char *service; 118 119 if (numeric || (service = port_to_service(port)) == NULL) 120 printf("%u", port); 121 else 122 printf("%s", service); 123} 124 125static void 126print_ports(const char *name, u_int16_t min, u_int16_t max, 127 int invert, int numeric) 128{ 129 const char *inv = invert ? "!" : ""; 130 131 if (min != 0 || max != 0xFFFF || invert) { 132 printf("%s", name); 133 if (min == max) { 134 printf(":%s", inv); 135 print_port(min, numeric); 136 } else { 137 printf("s:%s", inv); 138 print_port(min, numeric); 139 printf(":"); 140 print_port(max, numeric); 141 } 142 printf(" "); 143 } 144} 145 146/* Prints out the union ipt_matchinfo. */ 147static void 148udp_print(const void *ip, const struct xt_entry_match *match, int numeric) 149{ 150 const struct xt_udp *udp = (struct xt_udp *)match->data; 151 152 printf("udp "); 153 print_ports("spt", udp->spts[0], udp->spts[1], 154 udp->invflags & XT_UDP_INV_SRCPT, 155 numeric); 156 print_ports("dpt", udp->dpts[0], udp->dpts[1], 157 udp->invflags & XT_UDP_INV_DSTPT, 158 numeric); 159 if (udp->invflags & ~XT_UDP_INV_MASK) 160 printf("Unknown invflags: 0x%X ", 161 udp->invflags & ~XT_UDP_INV_MASK); 162} 163 164/* Saves the union ipt_matchinfo in parsable form to stdout. */ 165static void udp_save(const void *ip, const struct xt_entry_match *match) 166{ 167 const struct xt_udp *udpinfo = (struct xt_udp *)match->data; 168 169 if (udpinfo->spts[0] != 0 170 || udpinfo->spts[1] != 0xFFFF) { 171 if (udpinfo->invflags & XT_UDP_INV_SRCPT) 172 printf("! "); 173 if (udpinfo->spts[0] 174 != udpinfo->spts[1]) 175 printf("--sport %u:%u ", 176 udpinfo->spts[0], 177 udpinfo->spts[1]); 178 else 179 printf("--sport %u ", 180 udpinfo->spts[0]); 181 } 182 183 if (udpinfo->dpts[0] != 0 184 || udpinfo->dpts[1] != 0xFFFF) { 185 if (udpinfo->invflags & XT_UDP_INV_DSTPT) 186 printf("! "); 187 if (udpinfo->dpts[0] 188 != udpinfo->dpts[1]) 189 printf("--dport %u:%u ", 190 udpinfo->dpts[0], 191 udpinfo->dpts[1]); 192 else 193 printf("--dport %u ", 194 udpinfo->dpts[0]); 195 } 196} 197 198static struct xtables_match udp_match = { 199 .family = AF_INET, 200 .name = "udp", 201 .version = XTABLES_VERSION, 202 .size = XT_ALIGN(sizeof(struct xt_udp)), 203 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)), 204 .help = udp_help, 205 .init = udp_init, 206 .parse = udp_parse, 207 .print = udp_print, 208 .save = udp_save, 209 .extra_opts = udp_opts, 210}; 211 212static struct xtables_match udp_match6 = { 213 .family = AF_INET6, 214 .name = "udp", 215 .version = XTABLES_VERSION, 216 .size = XT_ALIGN(sizeof(struct xt_udp)), 217 .userspacesize = XT_ALIGN(sizeof(struct xt_udp)), 218 .help = udp_help, 219 .init = udp_init, 220 .parse = udp_parse, 221 .print = udp_print, 222 .save = udp_save, 223 .extra_opts = udp_opts, 224}; 225 226void 227_init(void) 228{ 229 xtables_register_match(&udp_match); 230 xtables_register_match(&udp_match6); 231} 232