12e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt#include <stdint.h> 2e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <stdio.h> 3e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <netdb.h> 42e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt#include <arpa/inet.h> 517908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI#include <xtables.h> 617908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI#include <linux/netfilter/xt_tcpudp.h> 7e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 82e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardtenum { 92e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt O_SOURCE_PORT = 0, 102e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt O_DEST_PORT, 112e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt}; 122e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt 13181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void udp_help(void) 14e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 15e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf( 168b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"udp match options:\n" 17967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --source-port port[:port]\n" 18e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher" --sport ...\n" 19e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher" match source port(s)\n" 20967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --destination-port port[:port]\n" 21e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher" --dport ...\n" 228b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" match destination port(s)\n"); 23e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 24e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 252e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt#define s struct xt_udp 262e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardtstatic const struct xt_option_entry udp_opts[] = { 272e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt {.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC, 282e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)}, 292e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt {.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC, 302e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)}, 312e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt {.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC, 322e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)}, 332e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC, 342e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)}, 352e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt XTOPT_TABLEEND, 36e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 372e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt#undef s 38e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 39181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void udp_init(struct xt_entry_match *m) 40e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 4117908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI struct xt_udp *udpinfo = (struct xt_udp *)m->data; 42e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 43e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF; 44e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 45e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 462e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardtstatic void udp_parse(struct xt_option_call *cb) 47e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 482e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt struct xt_udp *udpinfo = cb->data; 492e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt 502e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt xtables_option_parse(cb); 512e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt switch (cb->entry->id) { 522e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt case O_SOURCE_PORT: 532e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt if (cb->invert) 5417908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI udpinfo->invflags |= XT_UDP_INV_SRCPT; 55e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 562e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt case O_DEST_PORT: 572e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt if (cb->invert) 5817908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI udpinfo->invflags |= XT_UDP_INV_DSTPT; 59e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 60e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 62e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 63dd6e4b90b5b2dbc2bbaac5008e26949a18478197Jan Engelhardtstatic const char * 64e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherport_to_service(int port) 65e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 66dd6e4b90b5b2dbc2bbaac5008e26949a18478197Jan Engelhardt const struct servent *service; 67e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((service = getservbyport(htons(port), "udp"))) 69e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return service->s_name; 70e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 71e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 72e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 757ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtprint_port(uint16_t port, int numeric) 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 77dd6e4b90b5b2dbc2bbaac5008e26949a18478197Jan Engelhardt const char *service; 78e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (numeric || (service = port_to_service(port)) == NULL) 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%u", port); 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%s", service); 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 84e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 85e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 867ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtprint_ports(const char *name, uint16_t min, uint16_t max, 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int invert, int numeric) 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *inv = invert ? "!" : ""; 90e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 91e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (min != 0 || max != 0xFFFF || invert) { 9273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" %s", name); 93e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (min == max) { 94e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf(":%s", inv); 95e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_port(min, numeric); 96e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 97e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("s:%s", inv); 98e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_port(min, numeric); 99e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf(":"); 100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_port(max, numeric); 101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 106181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtudp_print(const void *ip, const struct xt_entry_match *match, int numeric) 107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 10817908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI const struct xt_udp *udp = (struct xt_udp *)match->data; 109e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" udp"); 111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_ports("spt", udp->spts[0], udp->spts[1], 11217908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI udp->invflags & XT_UDP_INV_SRCPT, 113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher numeric); 114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_ports("dpt", udp->dpts[0], udp->dpts[1], 11517908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI udp->invflags & XT_UDP_INV_DSTPT, 116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher numeric); 11717908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI if (udp->invflags & ~XT_UDP_INV_MASK) 11873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" Unknown invflags: 0x%X", 11917908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI udp->invflags & ~XT_UDP_INV_MASK); 120e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 122181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void udp_save(const void *ip, const struct xt_entry_match *match) 123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 12417908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI const struct xt_udp *udpinfo = (struct xt_udp *)match->data; 125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 126e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (udpinfo->spts[0] != 0 12773f72f541ac4dab538d4d418b9bbf1707b31342bRusty Russell || udpinfo->spts[1] != 0xFFFF) { 12817908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI if (udpinfo->invflags & XT_UDP_INV_SRCPT) 12973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" !"); 130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (udpinfo->spts[0] 131e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher != udpinfo->spts[1]) 13273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --sport %u:%u", 1339f2009cbfda7a4e341258322a7c8b462605990afMarc Boucher udpinfo->spts[0], 1342382c8c3a126ba82e6da03f79a88f44e7f3caa54Marc Boucher udpinfo->spts[1]); 135e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else 13673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --sport %u", 1379f2009cbfda7a4e341258322a7c8b462605990afMarc Boucher udpinfo->spts[0]); 138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (udpinfo->dpts[0] != 0 14173f72f541ac4dab538d4d418b9bbf1707b31342bRusty Russell || udpinfo->dpts[1] != 0xFFFF) { 14217908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI if (udpinfo->invflags & XT_UDP_INV_DSTPT) 14373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" !"); 144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (udpinfo->dpts[0] 145e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher != udpinfo->dpts[1]) 14673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --dport %u:%u", 1479f2009cbfda7a4e341258322a7c8b462605990afMarc Boucher udpinfo->dpts[0], 1489f2009cbfda7a4e341258322a7c8b462605990afMarc Boucher udpinfo->dpts[1]); 149e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else 15073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --dport %u", 1519f2009cbfda7a4e341258322a7c8b462605990afMarc Boucher udpinfo->dpts[0]); 152e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 153e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 154e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 155181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match udp_match = { 156c5e85736c207f211d82d2878a5781f512327dfceJan Engelhardt .family = NFPROTO_UNSPEC, 15717908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI .name = "udp", 1588b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 15917908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_udp)), 16017908e4bd0bc8ddb7a85bda316864ad8e1e56a29Yasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_udp)), 161181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = udp_help, 162181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .init = udp_init, 163181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = udp_print, 164181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = udp_save, 1652e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .x6_parse = udp_parse, 1662e73af96178f0ed7ebbd99478f1bc05ec5c86dc7Jan Engelhardt .x6_options = udp_opts, 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 170e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher_init(void) 171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 172181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&udp_match); 173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 174