net_del_fileroute.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /****************************************************************************
  2. * net/route/net_del_fileroute.c
  3. *
  4. * Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <stdint.h>
  40. #include <unistd.h>
  41. #include <fcntl.h>
  42. #include <string.h>
  43. #include <errno.h>
  44. #include <debug.h>
  45. #include <arpa/inet.h>
  46. #include <nuttx/fs/fs.h>
  47. #include <nuttx/net/ip.h>
  48. #include "route/fileroute.h"
  49. #include "route/cacheroute.h"
  50. #include "route/route.h"
  51. #if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE)
  52. /****************************************************************************
  53. * Private Types
  54. ****************************************************************************/
  55. #ifdef CONFIG_ROUTE_IPv4_FILEROUTE
  56. struct route_match_ipv4_s
  57. {
  58. in_addr_t target; /* The target IP address to match */
  59. in_addr_t netmask; /* The network mask to match */
  60. unsigned int index; /* Index of match */
  61. };
  62. #endif
  63. #ifdef CONFIG_ROUTE_IPv6_FILEROUTE
  64. struct route_match_ipv6_s
  65. {
  66. net_ipv6addr_t target; /* The target IP address to match */
  67. net_ipv6addr_t netmask; /* The network mask to match */
  68. unsigned int index; /* Index of match */
  69. };
  70. #endif
  71. /****************************************************************************
  72. * Private Functions
  73. ****************************************************************************/
  74. /****************************************************************************
  75. * Name: net_match_ipv4
  76. *
  77. * Description:
  78. * Return 1 if the route is available
  79. *
  80. * Input Parameters:
  81. * route - The next route to examine
  82. * arg - The match values (cast to void*)
  83. *
  84. * Returned Value:
  85. * 0 if the entry is not a match; 1 if the entry matched and was cleared.
  86. *
  87. ****************************************************************************/
  88. #ifdef CONFIG_ROUTE_IPv4_FILEROUTE
  89. static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg)
  90. {
  91. FAR struct route_match_ipv4_s *match = (FAR struct route_match_ipv4_s *)arg;
  92. /* To match, the masked target address must be the same, and the masks
  93. * must be the same.
  94. */
  95. net_ipv4_dumproute("Comparing", route);
  96. ninfo("With:\n");
  97. ninfo(" target=%08lx netmask=%08lx\n",
  98. htonl(match->target), htonl(match->netmask));
  99. if (net_ipv4addr_maskcmp(route->target, match->target, match->netmask) &&
  100. net_ipv4addr_cmp(route->netmask, match->netmask))
  101. {
  102. /* They match.. a non-zero value to terminate the traversal. The last
  103. * value of index is the index to the matching entry.
  104. */
  105. return 1;
  106. }
  107. /* Next time we are here, this will be the routing table index */
  108. match->index++;
  109. return 0;
  110. }
  111. #endif
  112. #ifdef CONFIG_ROUTE_IPv6_FILEROUTE
  113. static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg)
  114. {
  115. FAR struct route_match_ipv6_s *match = (FAR struct route_match_ipv6_s *)arg;
  116. /* To match, the masked target address must be the same, and the masks
  117. * must be the same.
  118. */
  119. net_ipv6_dumproute("Comparing", route);
  120. ninfo("With:\n");
  121. ninfo(" target: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  122. htons(match->target[0]), htons(match->target[1]),
  123. htons(match->target[2]), htons(match->target[3]),
  124. htons(match->target[4]), htons(match->target[5]),
  125. htons(match->target[6]), htons(match->target[7]));
  126. ninfo(" netmask: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  127. htons(match->netmask[0]), htons(match->netmask[1]),
  128. htons(match->netmask[2]), htons(match->netmask[3]),
  129. htons(match->netmask[4]), htons(match->netmask[5]),
  130. htons(match->netmask[6]), htons(match->netmask[7]));
  131. if (net_ipv6addr_maskcmp(route->target, match->target, match->netmask) &&
  132. net_ipv6addr_cmp(route->netmask, match->netmask))
  133. {
  134. /* They match.. a non-zero value to terminate the traversal. The last
  135. * value of index is the index to the matching entry.
  136. */
  137. return 1;
  138. }
  139. /* Next time we are here, this will be the routing table index */
  140. match->index++;
  141. return 0;
  142. }
  143. #endif
  144. /****************************************************************************
  145. * Public Functions
  146. ****************************************************************************/
  147. /****************************************************************************
  148. * Name: net_delroute_ipv4 and net_delroute_ipv6
  149. *
  150. * Description:
  151. * Remove an existing route from the routing table
  152. *
  153. * Input Parameters:
  154. *
  155. * Returned Value:
  156. * OK on success; Negated errno on failure.
  157. *
  158. ****************************************************************************/
  159. #ifdef CONFIG_ROUTE_IPv4_FILEROUTE
  160. int net_delroute_ipv4(in_addr_t target, in_addr_t netmask)
  161. {
  162. struct route_match_ipv4_s match;
  163. struct net_route_ipv4_s route;
  164. struct file fshandle;
  165. off_t filesize;
  166. ssize_t nwritten;
  167. ssize_t nread;
  168. off_t pos;
  169. int nentries;
  170. int index;
  171. int ret;
  172. /* We must lock out other accesses to the routing table while we remove
  173. * entry
  174. */
  175. ret = net_lockroute_ipv4();
  176. if (ret < 0)
  177. {
  178. nerr("ERROR: net_lockroute_ipv4 faled: %d\n", ret);
  179. return ret;
  180. }
  181. /* Get the size of the routing table (in entries) */
  182. nentries = net_routesize_ipv4();
  183. if (nentries < 0)
  184. {
  185. ret = nentries;
  186. goto errout_with_lock;
  187. }
  188. else if (nentries == 0)
  189. {
  190. ret = -ENOENT;
  191. goto errout_with_lock;
  192. }
  193. /* Set up the comparison structure */
  194. net_ipv4addr_copy(match.target, target);
  195. net_ipv4addr_copy(match.netmask, netmask);
  196. match.index = 0;
  197. /* Then find the index into the routing table where the match can be found */
  198. ret = net_foreachroute_ipv4(net_match_ipv4, &match);
  199. if (ret < 0)
  200. {
  201. /* And error occurred */
  202. goto errout_with_lock;
  203. }
  204. else if (ret == 0)
  205. {
  206. /* No match found */
  207. ret = -ENOENT;
  208. goto errout_with_lock;
  209. }
  210. /* Open the routing table for read/write access */
  211. ret = net_openroute_ipv4(O_RDWR, &fshandle);
  212. if (ret < 0)
  213. {
  214. nerr("ERROR: Could not open IPv4 routing table: %d\n", ret);
  215. goto errout_with_lock;
  216. }
  217. #ifdef CONFIG_ROUTE_IPv4_CACHEROUTE
  218. /* We are committed to modifying the routing table. Flush the in-memory
  219. * routing table cache.
  220. */
  221. net_flushcache_ipv4();
  222. #endif
  223. /* Loop, copying each entry, to the previous entry thus removing the entry
  224. * to be deleted.
  225. */
  226. for (index = match.index + 1; index < nentries; index++)
  227. {
  228. /* Seek to the current entry to be moved */
  229. pos = net_seekroute_ipv4(&fshandle, index);
  230. if (pos < 0)
  231. {
  232. nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)pos);
  233. ret = (int)pos;
  234. goto errout_with_fshandle;
  235. }
  236. /* Read the routing table entry at this position */
  237. nread = net_readroute_ipv4(&fshandle, &route);
  238. if (nread < 0)
  239. {
  240. nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)nread);
  241. ret = (int)nread;
  242. goto errout_with_fshandle;
  243. }
  244. else if (nread == 0)
  245. {
  246. nerr("ERROR: Unexpected end of file\n");
  247. ret = -EINVAL;
  248. goto errout_with_fshandle;
  249. }
  250. /* Seek to the previous entry to be replaced */
  251. pos = net_seekroute_ipv4(&fshandle, index - 1);
  252. if (pos < 0)
  253. {
  254. nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)pos);
  255. ret = (int)pos;
  256. goto errout_with_fshandle;
  257. }
  258. /* Now write the record to its new location */
  259. nwritten = net_writeroute_ipv4(&fshandle, &route);
  260. if (nwritten < 0)
  261. {
  262. nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)nwritten);
  263. ret = (int)nwritten;
  264. goto errout_with_fshandle;
  265. }
  266. }
  267. /* Now truncate the one duplicate entry at the end of the file. This may
  268. * result in a zero length file.
  269. */
  270. filesize = (nentries - 1) * sizeof(struct net_route_ipv4_s);
  271. ret = file_truncate(&fshandle, filesize);
  272. errout_with_fshandle:
  273. net_closeroute_ipv4(&fshandle);
  274. errout_with_lock:
  275. net_unlockroute_ipv4();
  276. return ret;
  277. }
  278. #endif
  279. #ifdef CONFIG_ROUTE_IPv6_FILEROUTE
  280. int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
  281. {
  282. struct route_match_ipv6_s match;
  283. struct net_route_ipv6_s route;
  284. struct file fshandle;
  285. off_t filesize;
  286. ssize_t nwritten;
  287. ssize_t nread;
  288. off_t pos;
  289. int nentries;
  290. int index;
  291. int ret;
  292. /* We must lock out other accesses to the routing table while we remove
  293. * entry
  294. */
  295. ret = net_lockroute_ipv6();
  296. if (ret < 0)
  297. {
  298. nerr("ERROR: net_lockroute_ipv6 failed: %d\n", ret);
  299. return ret;
  300. }
  301. /* Get the size of the routing table (in entries) */
  302. nentries = net_routesize_ipv6();
  303. if (nentries < 0)
  304. {
  305. ret = nentries;
  306. goto errout_with_lock;
  307. }
  308. else if (nentries == 0)
  309. {
  310. ret = -ENOENT;
  311. goto errout_with_lock;
  312. }
  313. /* Set up the comparison structure */
  314. net_ipv6addr_copy(match.target, target);
  315. net_ipv6addr_copy(match.netmask, netmask);
  316. match.index = 0;
  317. /* Then find the index into the routing table where the match can be found */
  318. ret = net_foreachroute_ipv6(net_match_ipv6, &match);
  319. if (ret < 0)
  320. {
  321. /* And error occurred */
  322. ret = ret;
  323. goto errout_with_lock;
  324. }
  325. else if (ret == 0)
  326. {
  327. /* No match found */
  328. ret = -ENOENT;
  329. goto errout_with_lock;
  330. }
  331. /* Open the routing table for read/write access */
  332. ret = net_openroute_ipv6(O_RDWR, &fshandle);
  333. if (ret < 0)
  334. {
  335. nerr("ERROR: Could not open IPv6 routing table: %d\n", ret);
  336. goto errout_with_lock;
  337. }
  338. #ifdef CONFIG_ROUTE_IPv6_CACHEROUTE
  339. /* We are committed to modifying the routing table. Flush the in-memory
  340. * routing table cache.
  341. */
  342. net_flushcache_ipv6();
  343. #endif
  344. /* Loop, copying each entry, to the previous entry thus removing the entry
  345. * to be deleted.
  346. */
  347. for (index = match.index + 1; index < nentries; index++)
  348. {
  349. /* Seek to the current entry to be moved */
  350. pos = net_seekroute_ipv6(&fshandle, index);
  351. if (pos < 0)
  352. {
  353. nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos);
  354. ret = (int)pos;
  355. goto errout_with_fshandle;
  356. }
  357. /* Read the routing table entry at this position */
  358. nread = net_readroute_ipv6(&fshandle, &route);
  359. if (nread < 0)
  360. {
  361. nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nread);
  362. ret = (int)nread;
  363. goto errout_with_fshandle;
  364. }
  365. else if (nread == 0)
  366. {
  367. nerr("ERROR: Unexpected end of file\n");
  368. ret = -EINVAL;
  369. goto errout_with_fshandle;
  370. }
  371. /* Seek to the previous entry to be replaced */
  372. pos = net_seekroute_ipv6(&fshandle, index - 1);
  373. if (pos < 0)
  374. {
  375. nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos);
  376. ret = (int)pos;
  377. goto errout_with_fshandle;
  378. }
  379. /* Now write the record to its new location */
  380. nwritten = net_writeroute_ipv6(&fshandle, &route);
  381. if (nwritten < 0)
  382. {
  383. nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nwritten);
  384. ret = (int)nwritten;
  385. goto errout_with_fshandle;
  386. }
  387. }
  388. /* Now truncate the one duplicate entry at the end of the file. This may
  389. * result in a zero length file.
  390. */
  391. filesize = (nentries - 1) * sizeof(struct net_route_ipv6_s);
  392. ret = file_truncate(&fshandle, filesize);
  393. errout_with_fshandle:
  394. net_closeroute_ipv6(&fshandle);
  395. errout_with_lock:
  396. net_unlockroute_ipv6();
  397. return ret;
  398. }
  399. #endif
  400. #endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */