libxt_udp.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <netdb.h>
  4. #include <arpa/inet.h>
  5. #include <xtables.h>
  6. #include <linux/netfilter/xt_tcpudp.h>
  7. enum {
  8. O_SOURCE_PORT = 0,
  9. O_DEST_PORT,
  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. #define s struct xt_udp
  23. static const struct xt_option_entry udp_opts[] = {
  24. {.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
  25. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
  26. {.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
  27. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
  28. {.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
  29. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
  30. {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
  31. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
  32. XTOPT_TABLEEND,
  33. };
  34. #undef s
  35. static void udp_init(struct xt_entry_match *m)
  36. {
  37. struct xt_udp *udpinfo = (struct xt_udp *)m->data;
  38. udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
  39. }
  40. static void udp_parse(struct xt_option_call *cb)
  41. {
  42. struct xt_udp *udpinfo = cb->data;
  43. xtables_option_parse(cb);
  44. switch (cb->entry->id) {
  45. case O_SOURCE_PORT:
  46. if (cb->invert)
  47. udpinfo->invflags |= XT_UDP_INV_SRCPT;
  48. break;
  49. case O_DEST_PORT:
  50. if (cb->invert)
  51. udpinfo->invflags |= XT_UDP_INV_DSTPT;
  52. break;
  53. }
  54. }
  55. static const char *
  56. port_to_service(int port)
  57. {
  58. const struct servent *service;
  59. if ((service = getservbyport(htons(port), "udp")))
  60. return service->s_name;
  61. return NULL;
  62. }
  63. static void
  64. print_port(uint16_t port, int numeric)
  65. {
  66. const char *service;
  67. if (numeric || (service = port_to_service(port)) == NULL)
  68. printf("%u", port);
  69. else
  70. printf("%s", service);
  71. }
  72. static void
  73. print_ports(const char *name, uint16_t min, uint16_t max,
  74. int invert, int numeric)
  75. {
  76. const char *inv = invert ? "!" : "";
  77. if (min != 0 || max != 0xFFFF || invert) {
  78. printf(" %s", name);
  79. if (min == max) {
  80. printf(":%s", inv);
  81. print_port(min, numeric);
  82. } else {
  83. printf("s:%s", inv);
  84. print_port(min, numeric);
  85. printf(":");
  86. print_port(max, numeric);
  87. }
  88. }
  89. }
  90. static void
  91. udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
  92. {
  93. const struct xt_udp *udp = (struct xt_udp *)match->data;
  94. printf(" udp");
  95. print_ports("spt", udp->spts[0], udp->spts[1],
  96. udp->invflags & XT_UDP_INV_SRCPT,
  97. numeric);
  98. print_ports("dpt", udp->dpts[0], udp->dpts[1],
  99. udp->invflags & XT_UDP_INV_DSTPT,
  100. numeric);
  101. if (udp->invflags & ~XT_UDP_INV_MASK)
  102. printf(" Unknown invflags: 0x%X",
  103. udp->invflags & ~XT_UDP_INV_MASK);
  104. }
  105. static void udp_save(const void *ip, const struct xt_entry_match *match)
  106. {
  107. const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
  108. if (udpinfo->spts[0] != 0
  109. || udpinfo->spts[1] != 0xFFFF) {
  110. if (udpinfo->invflags & XT_UDP_INV_SRCPT)
  111. printf(" !");
  112. if (udpinfo->spts[0]
  113. != udpinfo->spts[1])
  114. printf(" --sport %u:%u",
  115. udpinfo->spts[0],
  116. udpinfo->spts[1]);
  117. else
  118. printf(" --sport %u",
  119. udpinfo->spts[0]);
  120. }
  121. if (udpinfo->dpts[0] != 0
  122. || udpinfo->dpts[1] != 0xFFFF) {
  123. if (udpinfo->invflags & XT_UDP_INV_DSTPT)
  124. printf(" !");
  125. if (udpinfo->dpts[0]
  126. != udpinfo->dpts[1])
  127. printf(" --dport %u:%u",
  128. udpinfo->dpts[0],
  129. udpinfo->dpts[1]);
  130. else
  131. printf(" --dport %u",
  132. udpinfo->dpts[0]);
  133. }
  134. }
  135. static struct xtables_match udp_match = {
  136. .family = NFPROTO_UNSPEC,
  137. .name = "udp",
  138. .version = XTABLES_VERSION,
  139. .size = XT_ALIGN(sizeof(struct xt_udp)),
  140. .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
  141. .help = udp_help,
  142. .init = udp_init,
  143. .print = udp_print,
  144. .save = udp_save,
  145. .x6_parse = udp_parse,
  146. .x6_options = udp_opts,
  147. };
  148. void
  149. _init(void)
  150. {
  151. xtables_register_match(&udp_match);
  152. }