net_procfs_route.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /****************************************************************************
  2. * net/procfs/fs_procfs_route.c
  3. *
  4. * Copyright (C) 2017 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 <sys/types.h>
  40. #include <sys/statfs.h>
  41. #include <sys/stat.h>
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include <stdarg.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <fcntl.h>
  49. #include <assert.h>
  50. #include <errno.h>
  51. #include <debug.h>
  52. #include <nuttx/kmalloc.h>
  53. #include <nuttx/fs/fs.h>
  54. #include <nuttx/fs/procfs.h>
  55. #include <nuttx/fs/dirent.h>
  56. #include "route/route.h"
  57. #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
  58. #ifndef CONFIG_FS_PROCFS_EXCLUDE_ROUTE
  59. /****************************************************************************
  60. * Pre-processor Definitions
  61. ****************************************************************************/
  62. /* Determines the size of an intermediate buffer that must be large enough
  63. * to handle the longest line generated by this logic.
  64. */
  65. #define STATUS_LINELEN 58
  66. /* Directory entry indices */
  67. #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
  68. # define IPv4_INDEX 0
  69. # define IPv6_INDEX 1
  70. #elif defined(CONFIG_NET_IPv4)
  71. # define IPv4_INDEX 0
  72. #elif defined(CONFIG_NET_IPv6)
  73. # define IPv6_INDEX 0
  74. #endif
  75. /****************************************************************************
  76. * Private Types
  77. ****************************************************************************/
  78. /* This enumeration identifies all of the nodes that can be accessed via the
  79. * procfs file system.
  80. */
  81. enum route_node_e
  82. {
  83. PROC_ROUTE = 0 /* The top-level directory */
  84. #ifdef CONFIG_NET_IPv4
  85. , PROC_ROUTE_IPv4 /* IPv4 routing table */
  86. #endif
  87. #ifdef CONFIG_NET_IPv6
  88. , PROC_ROUTE_IPv6 /* IPv6 routing table */
  89. #endif
  90. };
  91. /* This structure describes one open "file" */
  92. struct route_file_s
  93. {
  94. struct procfs_file_s base; /* Base open file structure */
  95. FAR const char *name; /* Terminal node segment name */
  96. uint8_t node; /* Type of node (see enum route_node_e) */
  97. char line[STATUS_LINELEN]; /* Pre-allocated buffer for formatted lines */
  98. };
  99. /* This structure describes one open "directory" */
  100. struct route_dir_s
  101. {
  102. struct procfs_dir_priv_s base; /* Base directory private data */
  103. FAR const char *name; /* Terminal node segment name */
  104. uint8_t node; /* Type of node (see enum route_node_e) */
  105. };
  106. /* The structure is used when traversing routing tables */
  107. struct route_info_s
  108. {
  109. FAR char *line; /* Intermediate line buffer pointer */
  110. FAR char *buffer; /* User buffer */
  111. size_t linelen; /* Size of the intermediate buffer */
  112. size_t buflen; /* Size of the user buffer */
  113. size_t remaining; /* Bytes remaining in user buffer */
  114. size_t totalsize; /* Accumulated size of the copy */
  115. off_t offset; /* Skip offset */
  116. bool header; /* True: header has been generated */
  117. int16_t index; /* Routing table index */
  118. };
  119. /****************************************************************************
  120. * Private Function Prototypes
  121. ****************************************************************************/
  122. /* Helpers */
  123. static void route_sprintf(FAR struct route_info_s *info,
  124. FAR const char *fmt, ...);
  125. #ifdef CONFIG_NET_IPv4
  126. static int route_ipv4_entry(FAR struct net_route_ipv4_s *route,
  127. FAR void *arg);
  128. #endif
  129. #ifdef CONFIG_NET_IPv6
  130. static int route_ipv6_entry(FAR struct net_route_ipv6_s *route,
  131. FAR void *arg);
  132. #endif
  133. #ifdef CONFIG_NET_IPv4
  134. static ssize_t route_ipv4_table(FAR struct route_file_s *procfile,
  135. FAR char *buffer, size_t buflen, off_t offset);
  136. #endif
  137. #ifdef CONFIG_NET_IPv6
  138. static ssize_t route_ipv6_table(FAR struct route_file_s *procfile,
  139. FAR char *buffer, size_t buflen, off_t offset);
  140. #endif
  141. /* File system methods */
  142. static int route_open(FAR struct file *filep, FAR const char *relpath,
  143. int oflags, mode_t mode);
  144. static int route_close(FAR struct file *filep);
  145. static ssize_t route_read(FAR struct file *filep, FAR char *buffer,
  146. size_t buflen);
  147. static int route_dup(FAR const struct file *oldp,
  148. FAR struct file *newp);
  149. static int route_opendir(const char *relpath,
  150. FAR struct fs_dirent_s *dir);
  151. static int route_closedir(FAR struct fs_dirent_s *dir);
  152. static int route_readdir(FAR struct fs_dirent_s *dir);
  153. static int route_rewinddir(FAR struct fs_dirent_s *dir);
  154. static int route_stat(FAR const char *relpath, FAR struct stat *buf);
  155. /****************************************************************************
  156. * Public Data
  157. ****************************************************************************/
  158. /* See fs_mount.c -- this structure is explicitly externed there.
  159. * We use the old-fashioned kind of initializers so that this will compile
  160. * with any compiler.
  161. */
  162. const struct procfs_operations net_procfs_routeoperations =
  163. {
  164. route_open, /* open */
  165. route_close, /* close */
  166. route_read, /* read */
  167. NULL, /* write */
  168. route_dup, /* dup */
  169. route_opendir, /* opendir */
  170. route_closedir, /* closedir */
  171. route_readdir, /* readdir */
  172. route_rewinddir, /* rewinddir */
  173. route_stat /* stat */
  174. };
  175. /****************************************************************************
  176. * Private Data
  177. ****************************************************************************/
  178. /* Well-known paths */
  179. static const char g_route_path[] = "net/route";
  180. #ifdef CONFIG_NET_IPv4
  181. static const char g_route_ipv4_path[] = "net/route/ipv4";
  182. #endif
  183. #ifdef CONFIG_NET_IPv6
  184. static const char g_route_ipv6_path[] = "net/route/ipv6";
  185. #endif
  186. /* Subdirectory names */
  187. #ifdef CONFIG_NET_IPv4
  188. static const char g_route_ipv4_subdir[] = "ipv4";
  189. #endif
  190. #ifdef CONFIG_NET_IPv6
  191. static const char g_route_ipv6_subdir[] = "ipv6";
  192. #endif
  193. /****************************************************************************
  194. * Private Functions
  195. ****************************************************************************/
  196. /****************************************************************************
  197. * Name: route_sprintf
  198. *
  199. * Description:
  200. * Format:
  201. *
  202. * 11111111112222222222333
  203. * 12345678901234567890123456789012
  204. * SEQ TARGET NETMASK ROUTER
  205. * nnnn. xxxxxxxx xxxxxxxx xxxxxxxx
  206. *
  207. ****************************************************************************/
  208. static void route_sprintf(FAR struct route_info_s *info,
  209. FAR const char *fmt, ...)
  210. {
  211. size_t linesize;
  212. size_t copysize;
  213. va_list ap;
  214. /* Print the format and data to a line buffer */
  215. va_start(ap, fmt);
  216. linesize = vsnprintf(info->line, info->linelen, fmt, ap);
  217. va_end(ap);
  218. /* Copy the line buffer to the user buffer */
  219. copysize = procfs_memcpy(info->line, linesize,
  220. info->buffer, info->remaining,
  221. &info->offset);
  222. /* Update counts and pointers */
  223. info->totalsize += copysize;
  224. info->buffer += copysize;
  225. info->remaining -= copysize;
  226. }
  227. /****************************************************************************
  228. * Name: route_ipv4_entry
  229. *
  230. * Description:
  231. * Format:
  232. *
  233. * 11111111112222222222333333333344444444444555
  234. * 12345678901234567890123456789012345678901234567890123
  235. * SEQ TARGET NETMASK ROUTER
  236. * nnnn. xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx
  237. *
  238. ****************************************************************************/
  239. #ifdef CONFIG_NET_IPv4
  240. static int route_ipv4_entry(FAR struct net_route_ipv4_s *route, FAR void *arg)
  241. {
  242. FAR struct route_info_s *info = (FAR struct route_info_s *)arg;
  243. char target[INET_ADDRSTRLEN];
  244. char netmask[INET_ADDRSTRLEN];
  245. char router[INET_ADDRSTRLEN];
  246. DEBUGASSERT(info != NULL);
  247. /* Generate the header before the first entry */
  248. if (info->index == 0 && !info->header)
  249. {
  250. route_sprintf(info, "%-4s %-16s%-16s%-16s\n",
  251. "SEQ", "TARGET", "NETMASK", "ROUTER");
  252. if (info->totalsize >= info->buflen)
  253. {
  254. /* Only part of the header was printed. */
  255. return 1;
  256. }
  257. /* The whole header was printed. */
  258. info->header = true;
  259. }
  260. /* Generate routing table entry on one line */
  261. (void)inet_ntop(AF_INET, &route->target, target, INET_ADDRSTRLEN);
  262. (void)inet_ntop(AF_INET, &route->netmask, netmask, INET_ADDRSTRLEN);
  263. (void)inet_ntop(AF_INET, &route->router, router, INET_ADDRSTRLEN);
  264. info->index++;
  265. route_sprintf(info, "%4u. %-16s%-16s%-16s\n",
  266. info->index, target, netmask, router);
  267. return (info->totalsize >= info->buflen) ? 1 : 0;
  268. }
  269. #endif
  270. /****************************************************************************
  271. * Name: route_ipv6_entry
  272. *
  273. * Description:
  274. * Format:
  275. *
  276. * 11111111112222222222333333333344444444445555
  277. * 12345678901234567890123456789012345678901234567890123
  278. * nnnn. target: xxxx:xxxx:xxxx:xxxxxxxx:xxxx:xxxx:xxxx
  279. * netmask: xxxx:xxxx:xxxx:xxxxxxxx:xxxx:xxxx:xxxx
  280. * router: xxxx:xxxx:xxxx:xxxxxxxx:xxxx:xxxx:xxxx
  281. *
  282. ****************************************************************************/
  283. #ifdef CONFIG_NET_IPv6
  284. static int route_ipv6_entry(FAR struct net_route_ipv6_s *route, FAR void *arg)
  285. {
  286. FAR struct route_info_s *info = (FAR struct route_info_s *)arg;
  287. char addr[INET6_ADDRSTRLEN];
  288. DEBUGASSERT(info != NULL);
  289. /* Generate routing table entry on three lines */
  290. info->index++;
  291. (void)inet_ntop(AF_INET6, route->target, addr, INET6_ADDRSTRLEN);
  292. route_sprintf(info, "%4u. TARGET %s\n", info->index, addr);
  293. if (info->totalsize >= info->buflen)
  294. {
  295. return 1;
  296. }
  297. (void)inet_ntop(AF_INET6, route->netmask, addr, INET6_ADDRSTRLEN);
  298. route_sprintf(info, " NETMASK %s\n", addr);
  299. if (info->totalsize >= info->buflen)
  300. {
  301. return 1;
  302. }
  303. (void)inet_ntop(AF_INET6, route->router, addr, INET6_ADDRSTRLEN);
  304. route_sprintf(info, " ROUTER %s\n", addr);
  305. return (info->totalsize >= info->buflen) ? 1 : 0;
  306. }
  307. #endif
  308. /****************************************************************************
  309. * Name: route_ipv4_table
  310. *
  311. * Description:
  312. * Format:
  313. *
  314. * 11111111112222222222333333333344444444444555
  315. * 12345678901234567890123456789012345678901234567890123
  316. * SEQ TARGET NETMASK ROUTER
  317. * nnnn. xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx
  318. *
  319. ****************************************************************************/
  320. #ifdef CONFIG_NET_IPv4
  321. static ssize_t route_ipv4_table(FAR struct route_file_s *procfile,
  322. FAR char *buffer, size_t buflen, off_t offset)
  323. {
  324. struct route_info_s info;
  325. memset(&info, 0, sizeof(struct route_info_s));
  326. info.line = procfile->line;
  327. info.buffer = buffer;
  328. info.linelen = STATUS_LINELEN;
  329. info.buflen = buflen;
  330. info.remaining = buflen;
  331. info.offset = offset;
  332. /* Generate each entry in the routing table */
  333. (void)net_foreachroute_ipv4(route_ipv4_entry, &info);
  334. return info.totalsize;
  335. }
  336. #endif
  337. /****************************************************************************
  338. * Name: route_ipv6_table
  339. ****************************************************************************/
  340. #ifdef CONFIG_NET_IPv6
  341. static ssize_t route_ipv6_table(FAR struct route_file_s *procfile,
  342. FAR char *buffer, size_t buflen, off_t offset)
  343. {
  344. struct route_info_s info;
  345. memset(&info, 0, sizeof(struct route_info_s));
  346. info.line = procfile->line;
  347. info.buffer = buffer;
  348. info.linelen = STATUS_LINELEN;
  349. info.buflen = buflen;
  350. info.remaining = buflen;
  351. info.offset = offset;
  352. /* Generate each entry in the routing table */
  353. (void)net_foreachroute_ipv6(route_ipv6_entry, &info);
  354. return info.totalsize;
  355. }
  356. #endif
  357. /****************************************************************************
  358. * Name: route_open
  359. ****************************************************************************/
  360. static int route_open(FAR struct file *filep, FAR const char *relpath,
  361. int oflags, mode_t mode)
  362. {
  363. FAR struct route_file_s *procfile;
  364. FAR const char *name;
  365. uint8_t node;
  366. finfo("Open '%s'\n", relpath);
  367. /* PROCFS is read-only. Any attempt to open with any kind of write
  368. * access is not permitted.
  369. *
  370. * REVISIT: Write-able proc files could be quite useful.
  371. */
  372. if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
  373. {
  374. ferr("ERROR: Only O_RDONLY supported\n");
  375. return -EACCES;
  376. }
  377. /* There are only two possibilities */
  378. #ifdef CONFIG_NET_IPv4
  379. if (strcmp(relpath, g_route_ipv4_path) == 0)
  380. {
  381. name = g_route_ipv4_subdir;
  382. node = PROC_ROUTE_IPv4;
  383. }
  384. else
  385. #endif
  386. #ifdef CONFIG_NET_IPv6
  387. if (strcmp(relpath, g_route_ipv6_path) == 0)
  388. {
  389. name = g_route_ipv6_subdir;
  390. node = PROC_ROUTE_IPv6;
  391. }
  392. else
  393. #endif
  394. {
  395. ferr("ERROR: Invalid path \"%s\"\n", relpath);
  396. return -ENOENT;
  397. }
  398. /* Allocate a container to hold the task and node selection */
  399. procfile = (FAR struct route_file_s *)
  400. kmm_zalloc(sizeof(struct route_file_s));
  401. if (!procfile)
  402. {
  403. ferr("ERROR: Failed to allocate file container\n");
  404. return -ENOMEM;
  405. }
  406. /* Initialize the file container */
  407. procfile->name = name; /* Terminal node segment name */
  408. procfile->node = node; /* Type of node (see enum route_node_e) */
  409. /* Save the index as the open-specific state in filep->f_priv */
  410. filep->f_priv = (FAR void *)procfile;
  411. return OK;
  412. }
  413. /****************************************************************************
  414. * Name: route_close
  415. ****************************************************************************/
  416. static int route_close(FAR struct file *filep)
  417. {
  418. FAR struct route_file_s *procfile;
  419. /* Recover our private data from the struct file instance */
  420. procfile = (FAR struct route_file_s *)filep->f_priv;
  421. DEBUGASSERT(procfile);
  422. /* Release the file container structure */
  423. kmm_free(procfile);
  424. filep->f_priv = NULL;
  425. return OK;
  426. }
  427. /****************************************************************************
  428. * Name: route_read
  429. ****************************************************************************/
  430. static ssize_t route_read(FAR struct file *filep, FAR char *buffer,
  431. size_t buflen)
  432. {
  433. FAR struct route_file_s *procfile;
  434. ssize_t ret;
  435. finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
  436. /* Recover our private data from the struct file instance */
  437. procfile = (FAR struct route_file_s *)filep->f_priv;
  438. DEBUGASSERT(procfile);
  439. /* Provide the requested data */
  440. switch (procfile->node)
  441. {
  442. #ifdef CONFIG_NET_IPv4
  443. case PROC_ROUTE_IPv4: /* IPv4 routing table */
  444. ret = route_ipv4_table(procfile, buffer, buflen, filep->f_pos);
  445. break;
  446. #endif
  447. #ifdef CONFIG_NET_IPv6
  448. case PROC_ROUTE_IPv6: /* IPv6 routing table */
  449. ret = route_ipv6_table(procfile, buffer, buflen, filep->f_pos);
  450. break;
  451. #endif
  452. default:
  453. ret = -EINVAL;
  454. break;
  455. }
  456. /* Update the file offset */
  457. if (ret > 0)
  458. {
  459. filep->f_pos += ret;
  460. }
  461. return ret;
  462. }
  463. /****************************************************************************
  464. * Name: route_dup
  465. *
  466. * Description:
  467. * Duplicate open file data in the new file structure.
  468. *
  469. ****************************************************************************/
  470. static int route_dup(FAR const struct file *oldp, FAR struct file *newp)
  471. {
  472. FAR struct route_file_s *oldfile;
  473. FAR struct route_file_s *newfile;
  474. finfo("Dup %p->%p\n", oldp, newp);
  475. /* Recover our private data from the old struct file instance */
  476. oldfile = (FAR struct route_file_s *)oldp->f_priv;
  477. DEBUGASSERT(oldfile);
  478. /* Allocate a new container to hold the task and node selection */
  479. newfile = (FAR struct route_file_s *)
  480. kmm_malloc(sizeof(struct route_file_s));
  481. if (!newfile)
  482. {
  483. ferr("ERROR: Failed to allocate file container\n");
  484. return -ENOMEM;
  485. }
  486. /* The copy the file information from the old container to the new */
  487. memcpy(newfile, oldfile, sizeof(struct route_file_s));
  488. /* Save the new container in the new file structure */
  489. newp->f_priv = (FAR void *)newfile;
  490. return OK;
  491. }
  492. /****************************************************************************
  493. * Name: route_opendir
  494. *
  495. * Description:
  496. * Open a directory for read access
  497. *
  498. ****************************************************************************/
  499. static int route_opendir(FAR const char *relpath,
  500. FAR struct fs_dirent_s *dir)
  501. {
  502. FAR struct route_dir_s *level2;
  503. finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  504. DEBUGASSERT(relpath && dir && !dir->u.procfs);
  505. /* Check the relative path */
  506. if (strcmp(relpath, g_route_path) != 0)
  507. {
  508. #ifdef CONFIG_NET_IPv4
  509. if (strcmp(relpath, g_route_ipv4_path) == 0)
  510. {
  511. return -ENOTDIR;
  512. }
  513. #endif
  514. #ifdef CONFIG_NET_IPv6
  515. if (strcmp(relpath, g_route_ipv6_path) == 0)
  516. {
  517. return -ENOTDIR;
  518. }
  519. #endif
  520. return -ENOENT;
  521. }
  522. level2 = (FAR struct route_dir_s *)
  523. kmm_zalloc(sizeof(struct route_dir_s));
  524. if (!level2)
  525. {
  526. ferr("ERROR: Failed to allocate the directory structure\n");
  527. return -ENOMEM;
  528. }
  529. /* This is a second level directory */
  530. level2->base.level = 2;
  531. level2->base.nentries = 2;
  532. level2->name = "";
  533. level2->node = PROC_ROUTE;
  534. dir->u.procfs = (FAR void *)level2;
  535. return OK;
  536. }
  537. /****************************************************************************
  538. * Name: route_closedir
  539. *
  540. * Description: Close the directory listing
  541. *
  542. ****************************************************************************/
  543. static int route_closedir(FAR struct fs_dirent_s *dir)
  544. {
  545. FAR struct route_dir_s *priv;
  546. DEBUGASSERT(dir && dir->u.procfs);
  547. priv = dir->u.procfs;
  548. if (priv != NULL)
  549. {
  550. kmm_free(priv);
  551. }
  552. dir->u.procfs = NULL;
  553. return OK;
  554. }
  555. /****************************************************************************
  556. * Name: route_readdir
  557. *
  558. * Description: Read the next directory entry
  559. *
  560. ****************************************************************************/
  561. static int route_readdir(struct fs_dirent_s *dir)
  562. {
  563. FAR struct route_dir_s *level2;
  564. FAR const char *dname;
  565. unsigned int index;
  566. DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
  567. level2 = dir->u.procfs;
  568. /* The index determines which entry to return */
  569. index = level2->base.index;
  570. #ifdef CONFIG_NET_IPv4
  571. if (index == IPv4_INDEX)
  572. {
  573. dname = g_route_ipv4_subdir;
  574. }
  575. else
  576. #endif
  577. #ifdef CONFIG_NET_IPv6
  578. if (index == IPv6_INDEX)
  579. {
  580. dname = g_route_ipv6_subdir;
  581. }
  582. else
  583. #endif
  584. {
  585. /* We signal the end of the directory by returning the special
  586. * error -ENOENT
  587. */
  588. finfo("Entry %d: End of directory\n", index);
  589. return -ENOENT;
  590. }
  591. /* Save the filename and file type */
  592. dir->fd_dir.d_type = DTYPE_FILE;
  593. strncpy(dir->fd_dir.d_name, dname, NAME_MAX+1);
  594. /* Set up the next directory entry offset. NOTE that we could use the
  595. * standard f_pos instead of our own private index.
  596. */
  597. level2->base.index = index + 1;
  598. return OK;
  599. }
  600. /****************************************************************************
  601. * Name: proc_rewindir
  602. *
  603. * Description: Reset directory read to the first entry
  604. *
  605. ****************************************************************************/
  606. static int route_rewinddir(struct fs_dirent_s *dir)
  607. {
  608. FAR struct route_dir_s *priv;
  609. DEBUGASSERT(dir && dir->u.procfs);
  610. priv = dir->u.procfs;
  611. priv->base.index = 0;
  612. return OK;
  613. }
  614. /****************************************************************************
  615. * Name: route_stat
  616. *
  617. * Description: Return information about a file or directory
  618. *
  619. ****************************************************************************/
  620. static int route_stat(const char *relpath, struct stat *buf)
  621. {
  622. memset(buf, 0, sizeof(struct stat));
  623. if (strcmp(relpath, g_route_path) == 0)
  624. {
  625. buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
  626. }
  627. else
  628. #ifdef CONFIG_NET_IPv4
  629. if (strcmp(relpath, g_route_ipv4_path) == 0)
  630. {
  631. buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
  632. }
  633. else
  634. #endif
  635. #ifdef CONFIG_NET_IPv6
  636. if (strcmp(relpath, g_route_ipv6_path) == 0)
  637. {
  638. buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
  639. }
  640. else
  641. #endif
  642. {
  643. return -ENOENT;
  644. }
  645. return OK;
  646. }
  647. /****************************************************************************
  648. * Public Functions
  649. ****************************************************************************/
  650. #endif /* CONFIG_FS_PROCFS_EXCLUDE_ROUTE */
  651. #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */