portmap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /* $Id: portmap.c 2430 2010-03-27 21:05:46Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /*
  32. * This file contains routines to manipulate port maps, in which
  33. * one port number is mapped to another.
  34. */
  35. #include "config.h"
  36. #include "defines.h"
  37. #include "common.h"
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <errno.h>
  41. #include "tcpreplay.h"
  42. #include "tcpedit-int.h"
  43. #include "portmap.h"
  44. /**
  45. * mallocs a new tcpedit_portmap_t structure
  46. */
  47. tcpedit_portmap_t *
  48. new_portmap()
  49. {
  50. tcpedit_portmap_t *newportmap;
  51. newportmap = (tcpedit_portmap_t *)safe_malloc(sizeof(tcpedit_portmap_t));
  52. return (newportmap);
  53. }
  54. /**
  55. * \brief parses a string <port>:<port> and returns a new tcpedit_portmap_t struct
  56. *
  57. * We support the following formats:
  58. * <port>:<port> - map a single port to a new port
  59. * <port>-<port>:<port> - map a range of ports to a new port
  60. * <port>+<port>+...:<port> - map a list of ports to a single ports
  61. *
  62. * In the case of port ranges or port lists, we actually return a
  63. * chain of tcpedit_portmap_t's
  64. */
  65. static tcpedit_portmap_t *
  66. ports2PORT(char *ports)
  67. {
  68. tcpedit_portmap_t *portmap = NULL, *portmap_head = NULL, *portmap_last = NULL;
  69. char *from_s, *to_s, *from_begin, *from_end, *badchar;
  70. long from_l, to_l, from_b, from_e, i;
  71. char *token = NULL, *token2 = NULL;
  72. assert(ports);
  73. from_begin = NULL;
  74. from_end = NULL;
  75. /* first split the port numbers */
  76. from_s = strtok_r(ports, ":", &token);
  77. to_s = strtok_r(NULL, ":", &token);
  78. /* if there's anything left, it's a syntax error */
  79. if (strtok_r(NULL, ":", &token) != NULL)
  80. return NULL;
  81. /* if either of the parsed strings is NULL, we have a problem */
  82. if (from_s == NULL || to_s == NULL)
  83. return NULL;
  84. /* source map can have - (range) or , (and), but not both */
  85. if (strchr(from_s, '-') && strchr(from_s, '+'))
  86. return NULL;
  87. /* process to the to port */
  88. to_l = strtol(to_s, &badchar, 10);
  89. if (strlen(badchar) != 0)
  90. return NULL;
  91. if (to_l > 65535 || to_l < 0)
  92. return NULL;
  93. /*
  94. * put the new portmap info into the new node
  95. * while we convert to network-byte order, b/c its better
  96. * to do it once now, rather then each time we have to do a lookup
  97. */
  98. portmap_head = new_portmap();
  99. portmap = portmap_head;
  100. /* process a range, setting from_begin & from_end */
  101. if (strchr(from_s, '-')) {
  102. from_begin = strtok_r(from_s, "-", &token2);
  103. from_end = strtok_r(NULL, "-", &token2);
  104. from_b = strtol(from_begin, &badchar, 10);
  105. if (strlen(badchar) != 0)
  106. return NULL;
  107. from_e = strtol(from_end, &badchar, 10);
  108. if (strlen(badchar) != 0)
  109. return NULL;
  110. if (from_b > 65535 || from_b < 0 || from_e > 65535 || from_e < 0)
  111. return NULL;
  112. for (i = from_b; i <= from_e; i++) {
  113. portmap->from = htons(i);
  114. portmap->to = htons(to_l);
  115. portmap->next = new_portmap();
  116. portmap_last = portmap;
  117. portmap = portmap->next;
  118. }
  119. portmap_last = NULL;
  120. free(portmap);
  121. }
  122. /* process a list via +, filling in list[] */
  123. else if (strchr(from_s, '+')) {
  124. from_begin = strtok_r(from_s, "+", &token2);
  125. from_l = strtol(from_begin, &badchar, 10);
  126. if (strlen(badchar) != 0)
  127. return NULL;
  128. portmap->to = htons(to_l);
  129. portmap->from = htons(from_l);
  130. while ((from_begin = strtok_r(NULL, "+", &token2)) != NULL) {
  131. from_l = strtol(from_begin, &badchar, 10);
  132. if (strlen(badchar) != 0)
  133. return NULL;
  134. if (from_l > 65535 || from_l < 0)
  135. return NULL;
  136. portmap->next = new_portmap();
  137. portmap = portmap->next;
  138. portmap->to = htons(to_l);
  139. portmap->from = htons(from_l);
  140. }
  141. }
  142. /* this is just the old port:port format */
  143. else {
  144. /*
  145. * convert the strings to longs: if badchar points to anything
  146. * after, then it was a bad string
  147. */
  148. from_l = strtol(from_s, &badchar, 10);
  149. if (strlen(badchar) != 0)
  150. return NULL;
  151. if (from_l > 65535 || from_l < 0)
  152. return NULL;
  153. portmap->to = htons(to_l);
  154. portmap->from = htons(from_l);
  155. }
  156. /* return 1 for success */
  157. return portmap_head;
  158. }
  159. /**
  160. * Processes a string (ourstr) containing the portmap ("2000:4000" for
  161. * example) and places the data in **portmapdata and finally returns 1 for
  162. * success, 0 for fail.
  163. */
  164. int
  165. parse_portmap(tcpedit_portmap_t ** portmap, const char *ourstr)
  166. {
  167. tcpedit_portmap_t *portmap_ptr;
  168. char *substr = NULL, *ourstrcpy = NULL, *token = NULL;
  169. assert(ourstr);
  170. ourstrcpy = safe_strdup(ourstr);
  171. /* first iteration of input */
  172. substr = strtok_r(ourstrcpy, ",", &token);
  173. if ((*portmap = ports2PORT(substr)) == NULL)
  174. return 0;
  175. portmap_ptr = *portmap;
  176. /* ports2PORT may return a chain, so find the end of it */
  177. while (portmap_ptr->next != NULL)
  178. portmap_ptr = portmap_ptr->next;
  179. while (1) {
  180. substr = strtok_r(NULL, ",", &token);
  181. /* if that was the last one, kick out */
  182. if (substr == NULL)
  183. break;
  184. /* process next record */
  185. portmap_ptr->next = ports2PORT(substr);
  186. /* ports2PORT may return a chain, so find the end of it */
  187. while (portmap_ptr->next != NULL)
  188. portmap_ptr = portmap_ptr->next;
  189. }
  190. return 1;
  191. }
  192. /**
  193. * Free's all the memory associated with the given portmap chain
  194. */
  195. void
  196. free_portmap(tcpedit_portmap_t * portmap)
  197. {
  198. assert(portmap);
  199. /* recursively go down the portmaps */
  200. if (portmap->next != NULL)
  201. free_portmap(portmap->next);
  202. safe_free(portmap);
  203. }
  204. /**
  205. * This function takes a pointer to a portmap list and prints each node
  206. */
  207. void
  208. print_portmap(tcpedit_portmap_t *portmap_data)
  209. {
  210. tcpedit_portmap_t *portmap_ptr;
  211. assert(portmap_data);
  212. portmap_ptr = portmap_data;
  213. while (portmap_ptr != NULL) {
  214. printf("from: %ld to: %ld\n", portmap_ptr->from, portmap_ptr->to);
  215. portmap_ptr = portmap_ptr->next;
  216. }
  217. printf("\n");
  218. }
  219. /**
  220. * This function takes a portmap and a port, and returns the mapped port,
  221. * or the original port if it isn't mapped to anything.
  222. */
  223. long
  224. map_port(tcpedit_portmap_t *portmap_data, long port)
  225. {
  226. tcpedit_portmap_t *portmap_ptr;
  227. long newport;
  228. assert(portmap_data);
  229. portmap_ptr = portmap_data;
  230. newport = port;
  231. /* step through the nodes, resetting newport if a match is found */
  232. while (portmap_ptr != NULL) {
  233. if (portmap_ptr->from == port)
  234. newport = portmap_ptr->to;
  235. portmap_ptr = portmap_ptr->next;
  236. }
  237. return(newport);
  238. }
  239. /**
  240. * rewrites the TCP or UDP ports based on a portmap
  241. * returns 1 for changes made or 0 for none
  242. */
  243. static int
  244. rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4)
  245. {
  246. tcp_hdr_t *tcp_hdr = NULL;
  247. udp_hdr_t *udp_hdr = NULL;
  248. int changes = 0;
  249. u_int16_t newport;
  250. tcpedit_portmap_t *portmap;
  251. assert(tcpedit);
  252. assert(tcpedit->portmap);
  253. portmap = tcpedit->portmap;
  254. if (protocol == IPPROTO_TCP) {
  255. tcp_hdr = (tcp_hdr_t *)layer4;
  256. /* check if we need to remap the destination port */
  257. newport = map_port(portmap, tcp_hdr->th_dport);
  258. if (newport != tcp_hdr->th_dport) {
  259. tcp_hdr->th_dport = newport;
  260. changes ++;
  261. }
  262. /* check if we need to remap the source port */
  263. newport = map_port(portmap, tcp_hdr->th_sport);
  264. if (newport != tcp_hdr->th_sport) {
  265. tcp_hdr->th_sport = newport;
  266. changes ++;
  267. }
  268. } else if (protocol == IPPROTO_UDP) {
  269. udp_hdr = (udp_hdr_t *)layer4;
  270. /* check if we need to remap the destination port */
  271. newport = map_port(portmap, udp_hdr->uh_dport);
  272. if (newport != udp_hdr->uh_dport) {
  273. udp_hdr->uh_dport = newport;
  274. changes ++;
  275. }
  276. /* check if we need to remap the source port */
  277. newport = map_port(portmap, udp_hdr->uh_sport);
  278. if (newport != udp_hdr->uh_sport) {
  279. udp_hdr->uh_sport = newport;
  280. changes ++;
  281. }
  282. }
  283. return changes;
  284. }
  285. int
  286. rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr)
  287. {
  288. assert(tcpedit);
  289. if (*ip_hdr == NULL) {
  290. return 0;
  291. } else if ((*ip_hdr)->ip_p == IPPROTO_TCP || (*ip_hdr)->ip_p == IPPROTO_UDP) {
  292. return rewrite_ports(tcpedit, (*ip_hdr)->ip_p, get_layer4_v4(*ip_hdr));
  293. }
  294. return 0;
  295. }
  296. int
  297. rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr)
  298. {
  299. assert(tcpedit);
  300. if (*ip6_hdr == NULL) {
  301. return 0;
  302. } else if ((*ip6_hdr)->ip_nh == IPPROTO_TCP || (*ip6_hdr)->ip_nh == IPPROTO_UDP) {
  303. return rewrite_ports(tcpedit, (*ip6_hdr)->ip_nh, ((u_char*)*ip6_hdr) + TCPR_IPV6_H);
  304. }
  305. return 0;
  306. }
  307. /*
  308. Local Variables:
  309. mode:c
  310. indent-tabs-mode:nil
  311. c-basic-offset:4
  312. End:
  313. */