if_proc.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* Interface name and statistics get function using proc file system
  2. * Copyright (C) 1999 Kunihiro Ishiguro
  3. *
  4. * This file is part of GNU Zebra.
  5. *
  6. * GNU Zebra is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2, or (at your option) any
  9. * later version.
  10. *
  11. * GNU Zebra is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  18. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. * 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "if.h"
  23. #include "prefix.h"
  24. #include "log.h"
  25. #include "zebra/ioctl.h"
  26. #include "zebra/connected.h"
  27. #include "zebra/interface.h"
  28. /* Proc filesystem one line buffer. */
  29. #define PROCBUFSIZ 1024
  30. /* Path to device proc file system. */
  31. #ifndef _PATH_PROC_NET_DEV
  32. #define _PATH_PROC_NET_DEV "/proc/net/dev"
  33. #endif /* _PATH_PROC_NET_DEV */
  34. /* Return statistics data pointer. */
  35. static char *
  36. interface_name_cut (char *buf, char **name)
  37. {
  38. char *stat;
  39. /* Skip white space. Line will include header spaces. */
  40. while (*buf == ' ')
  41. buf++;
  42. *name = buf;
  43. /* Cut interface name. */
  44. stat = strrchr (buf, ':');
  45. *stat++ = '\0';
  46. return stat;
  47. }
  48. /* Fetch each statistics field. */
  49. static int
  50. ifstat_dev_fields (int version, char *buf, struct interface *ifp)
  51. {
  52. switch (version)
  53. {
  54. case 3:
  55. sscanf(buf,
  56. "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
  57. &ifp->stats.rx_bytes,
  58. &ifp->stats.rx_packets,
  59. &ifp->stats.rx_errors,
  60. &ifp->stats.rx_dropped,
  61. &ifp->stats.rx_fifo_errors,
  62. &ifp->stats.rx_frame_errors,
  63. &ifp->stats.rx_compressed,
  64. &ifp->stats.rx_multicast,
  65. &ifp->stats.tx_bytes,
  66. &ifp->stats.tx_packets,
  67. &ifp->stats.tx_errors,
  68. &ifp->stats.tx_dropped,
  69. &ifp->stats.tx_fifo_errors,
  70. &ifp->stats.collisions,
  71. &ifp->stats.tx_carrier_errors,
  72. &ifp->stats.tx_compressed);
  73. break;
  74. case 2:
  75. sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
  76. &ifp->stats.rx_bytes,
  77. &ifp->stats.rx_packets,
  78. &ifp->stats.rx_errors,
  79. &ifp->stats.rx_dropped,
  80. &ifp->stats.rx_fifo_errors,
  81. &ifp->stats.rx_frame_errors,
  82. &ifp->stats.tx_bytes,
  83. &ifp->stats.tx_packets,
  84. &ifp->stats.tx_errors,
  85. &ifp->stats.tx_dropped,
  86. &ifp->stats.tx_fifo_errors,
  87. &ifp->stats.collisions,
  88. &ifp->stats.tx_carrier_errors);
  89. ifp->stats.rx_multicast = 0;
  90. break;
  91. case 1:
  92. sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
  93. &ifp->stats.rx_packets,
  94. &ifp->stats.rx_errors,
  95. &ifp->stats.rx_dropped,
  96. &ifp->stats.rx_fifo_errors,
  97. &ifp->stats.rx_frame_errors,
  98. &ifp->stats.tx_packets,
  99. &ifp->stats.tx_errors,
  100. &ifp->stats.tx_dropped,
  101. &ifp->stats.tx_fifo_errors,
  102. &ifp->stats.collisions,
  103. &ifp->stats.tx_carrier_errors);
  104. ifp->stats.rx_bytes = 0;
  105. ifp->stats.tx_bytes = 0;
  106. ifp->stats.rx_multicast = 0;
  107. break;
  108. }
  109. return 0;
  110. }
  111. /* Update interface's statistics. */
  112. void
  113. ifstat_update_proc (void)
  114. {
  115. FILE *fp;
  116. char buf[PROCBUFSIZ];
  117. int version;
  118. struct interface *ifp;
  119. char *stat;
  120. char *name;
  121. /* Open /proc/net/dev. */
  122. fp = fopen (_PATH_PROC_NET_DEV, "r");
  123. if (fp == NULL)
  124. {
  125. zlog_warn ("Can't open proc file %s: %s",
  126. _PATH_PROC_NET_DEV, safe_strerror (errno));
  127. return;
  128. }
  129. /* Drop header lines. */
  130. fgets (buf, PROCBUFSIZ, fp);
  131. fgets (buf, PROCBUFSIZ, fp);
  132. /* To detect proc format veresion, parse second line. */
  133. if (strstr (buf, "compressed"))
  134. version = 3;
  135. else if (strstr (buf, "bytes"))
  136. version = 2;
  137. else
  138. version = 1;
  139. /* Update each interface's statistics. */
  140. while (fgets (buf, PROCBUFSIZ, fp) != NULL)
  141. {
  142. stat = interface_name_cut (buf, &name);
  143. ifp = if_get_by_name (name);
  144. ifstat_dev_fields (version, stat, ifp);
  145. }
  146. fclose(fp);
  147. return;
  148. }
  149. /* Interface structure allocation by proc filesystem. */
  150. int
  151. interface_list_proc ()
  152. {
  153. FILE *fp;
  154. char buf[PROCBUFSIZ];
  155. struct interface *ifp;
  156. char *name;
  157. /* Open /proc/net/dev. */
  158. fp = fopen (_PATH_PROC_NET_DEV, "r");
  159. if (fp == NULL)
  160. {
  161. zlog_warn ("Can't open proc file %s: %s",
  162. _PATH_PROC_NET_DEV, safe_strerror (errno));
  163. return -1;
  164. }
  165. /* Drop header lines. */
  166. fgets (buf, PROCBUFSIZ, fp);
  167. fgets (buf, PROCBUFSIZ, fp);
  168. /* Only allocate interface structure. Other jobs will be done in
  169. if_ioctl.c. */
  170. while (fgets (buf, PROCBUFSIZ, fp) != NULL)
  171. {
  172. interface_name_cut (buf, &name);
  173. ifp = if_get_by_name (name);
  174. if_add_update (ifp);
  175. }
  176. fclose(fp);
  177. return 0;
  178. }
  179. #if defined(HAVE_IPV6) && defined(HAVE_PROC_NET_IF_INET6)
  180. #ifndef _PATH_PROC_NET_IF_INET6
  181. #define _PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
  182. #endif /* _PATH_PROC_NET_IF_INET6 */
  183. int
  184. ifaddr_proc_ipv6 ()
  185. {
  186. FILE *fp;
  187. char buf[PROCBUFSIZ];
  188. int n;
  189. char addr[33];
  190. char ifname[21];
  191. int ifindex, plen, scope, status;
  192. struct interface *ifp;
  193. struct prefix_ipv6 p;
  194. /* Open proc file system. */
  195. fp = fopen (_PATH_PROC_NET_IF_INET6, "r");
  196. if (fp == NULL)
  197. {
  198. zlog_warn ("Can't open proc file %s: %s",
  199. _PATH_PROC_NET_IF_INET6, safe_strerror (errno));
  200. return -1;
  201. }
  202. /* Get interface's IPv6 address. */
  203. while (fgets (buf, PROCBUFSIZ, fp) != NULL)
  204. {
  205. n = sscanf (buf, "%32s %02x %02x %02x %02x %20s",
  206. addr, &ifindex, &plen, &scope, &status, ifname);
  207. if (n != 6)
  208. continue;
  209. ifp = if_get_by_name (ifname);
  210. /* Fetch interface's IPv6 address. */
  211. str2in6_addr (addr, &p.prefix);
  212. p.prefixlen = plen;
  213. connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname);
  214. }
  215. fclose (fp);
  216. return 0;
  217. }
  218. #endif /* HAVE_IPV6 && HAVE_PROC_NET_IF_INET6 */