portmap.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /* $Id: portmap.c 1895 2007-08-22 04:24:33Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2007 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. * parses a string <port>:<port> and returns a new
  56. * tcpedit_portmap_t datastruct
  57. */
  58. static tcpedit_portmap_t *
  59. ports2PORT(char *ports)
  60. {
  61. tcpedit_portmap_t *portmap = NULL;
  62. char *from_s, *to_s, *badchar;
  63. long from_l, to_l;
  64. char *token = NULL;
  65. assert(ports);
  66. /* first split the port numbers */
  67. from_s = strtok_r(ports, ":", &token);
  68. to_s = strtok_r(NULL, ":", &token);
  69. /* if there's anything left, it's a syntax error */
  70. if (strtok_r(NULL, ":", &token) != NULL)
  71. return NULL;
  72. /* if either of the parsed strings is NULL, we have a problem */
  73. if (from_s == NULL || to_s == NULL)
  74. return NULL;
  75. /* convert the strings to longs: if badchar points to anything
  76. * after, then it was a bad string
  77. */
  78. from_l = strtol(from_s, &badchar, 10);
  79. if (strlen(badchar) != 0)
  80. return NULL;
  81. to_l = strtol(to_s, &badchar, 10);
  82. if (strlen(badchar) != 0)
  83. return NULL;
  84. portmap = new_portmap();
  85. /* put the new portmap info into the new node
  86. * while we convert to network-byte order, b/c its better
  87. * to do it once now, rather then each time we have to do a lookup
  88. */
  89. portmap->from = htons(from_l);
  90. portmap->to = htons(to_l);
  91. /* return 1 for success */
  92. return portmap;
  93. }
  94. /**
  95. * Processes a string (ourstr) containing the portmap ("2000:4000" for
  96. * example) and places the data in **portmapdata and finally returns 1 for
  97. * success, 0 for fail.
  98. */
  99. int
  100. parse_portmap(tcpedit_portmap_t ** portmap, const char *ourstr)
  101. {
  102. tcpedit_portmap_t *portmap_ptr;
  103. char *substr = NULL, *ourstrcpy = NULL, *token = NULL;
  104. assert(ourstr);
  105. ourstrcpy = safe_strdup(ourstr);
  106. /* first iteration of input */
  107. substr = strtok_r(ourstrcpy, ",", &token);
  108. if ((*portmap = ports2PORT(substr)) == NULL)
  109. return 0;
  110. portmap_ptr = *portmap;
  111. while (1) {
  112. substr = strtok_r(NULL, ",", &token);
  113. /* if that was the last one, kick out */
  114. if (substr == NULL)
  115. break;
  116. /* next record */
  117. portmap_ptr->next = ports2PORT(substr);
  118. portmap_ptr = portmap_ptr->next;
  119. }
  120. return 1;
  121. }
  122. /**
  123. * Free's all the memory associated with the given portmap chain
  124. */
  125. void
  126. free_portmap(tcpedit_portmap_t * portmap)
  127. {
  128. assert(portmap);
  129. /* recursively go down the portmaps */
  130. if (portmap->next != NULL)
  131. free_portmap(portmap->next);
  132. safe_free(portmap);
  133. }
  134. /**
  135. * This function takes a pointer to a portmap list and prints each node
  136. */
  137. void
  138. print_portmap(tcpedit_portmap_t *portmap_data)
  139. {
  140. tcpedit_portmap_t *portmap_ptr;
  141. assert(portmap_data);
  142. portmap_ptr = portmap_data;
  143. while (portmap_ptr != NULL) {
  144. printf("from: %ld to: %ld\n", portmap_ptr->from, portmap_ptr->to);
  145. portmap_ptr = portmap_ptr->next;
  146. }
  147. printf("\n");
  148. }
  149. /**
  150. * This function takes a portmap and a port, and returns the mapped port,
  151. * or the original port if it isn't mapped to anything.
  152. */
  153. long
  154. map_port(tcpedit_portmap_t *portmap_data, long port)
  155. {
  156. tcpedit_portmap_t *portmap_ptr;
  157. long newport;
  158. assert(portmap_data);
  159. portmap_ptr = portmap_data;
  160. newport = port;
  161. /* step through the nodes, resetting newport if a match is found */
  162. while (portmap_ptr != NULL) {
  163. if (portmap_ptr->from == port)
  164. newport = portmap_ptr->to;
  165. portmap_ptr = portmap_ptr->next;
  166. }
  167. return(newport);
  168. }
  169. /**
  170. * rewrites the TCP or UDP ports based on a portmap
  171. * returns 1 for changes made or 0 for none
  172. */
  173. int
  174. rewrite_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr)
  175. {
  176. tcp_hdr_t *tcp_hdr = NULL;
  177. udp_hdr_t *udp_hdr = NULL;
  178. int changes = 0;
  179. u_int16_t newport;
  180. tcpedit_portmap_t *portmap;
  181. assert(tcpedit);
  182. assert(tcpedit->portmap);
  183. portmap = tcpedit->portmap;
  184. if (*ip_hdr == NULL) {
  185. return 0;
  186. } else if ((*ip_hdr)->ip_p == IPPROTO_TCP) {
  187. tcp_hdr = (tcp_hdr_t *)get_layer4(*ip_hdr);
  188. /* check if we need to remap the destination port */
  189. newport = map_port(portmap, tcp_hdr->th_dport);
  190. if (newport != tcp_hdr->th_dport) {
  191. tcp_hdr->th_dport = newport;
  192. changes ++;
  193. }
  194. /* check if we need to remap the source port */
  195. newport = map_port(portmap, tcp_hdr->th_sport);
  196. if (newport != tcp_hdr->th_sport) {
  197. tcp_hdr->th_sport = newport;
  198. changes ++;
  199. }
  200. } else if ((*ip_hdr)->ip_p == IPPROTO_UDP) {
  201. udp_hdr = (udp_hdr_t *)get_layer4(*ip_hdr);
  202. /* check if we need to remap the destination port */
  203. newport = map_port(portmap, udp_hdr->uh_dport);
  204. if (newport != udp_hdr->uh_dport) {
  205. udp_hdr->uh_dport = newport;
  206. changes ++;
  207. }
  208. /* check if we need to remap the source port */
  209. newport = map_port(portmap, udp_hdr->uh_sport);
  210. if (newport != udp_hdr->uh_sport) {
  211. udp_hdr->uh_sport = newport;
  212. changes ++;
  213. }
  214. }
  215. return changes;
  216. }
  217. /*
  218. Local Variables:
  219. mode:c
  220. indent-tabs-mode:nil
  221. c-basic-offset:4
  222. End:
  223. */