isisd: fix --enable-isis-topology for 64-bit Linux
[jleu-quagga.git] / zebra / if_proc.c
blob3aec530bfa9f5716e72f93a75cce863380a3500e
1 /* Interface name and statistics get function using proc file system
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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.
22 #include <zebra.h>
24 #include "if.h"
25 #include "prefix.h"
26 #include "log.h"
28 #include "zebra/ioctl.h"
29 #include "zebra/connected.h"
30 #include "zebra/interface.h"
32 /* Proc filesystem one line buffer. */
33 #define PROCBUFSIZ 1024
35 /* Path to device proc file system. */
36 #ifndef _PATH_PROC_NET_DEV
37 #define _PATH_PROC_NET_DEV "/proc/net/dev"
38 #endif /* _PATH_PROC_NET_DEV */
40 /* Return statistics data pointer. */
41 static char *
42 interface_name_cut (char *buf, char **name)
44 char *stat;
46 /* Skip white space. Line will include header spaces. */
47 while (*buf == ' ')
48 buf++;
49 *name = buf;
51 /* Cut interface name. */
52 stat = strrchr (buf, ':');
53 *stat++ = '\0';
55 return stat;
58 /* Fetch each statistics field. */
59 static int
60 ifstat_dev_fields (int version, char *buf, struct interface *ifp)
62 switch (version)
64 case 3:
65 sscanf(buf,
66 "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
67 &ifp->stats.rx_bytes,
68 &ifp->stats.rx_packets,
69 &ifp->stats.rx_errors,
70 &ifp->stats.rx_dropped,
71 &ifp->stats.rx_fifo_errors,
72 &ifp->stats.rx_frame_errors,
73 &ifp->stats.rx_compressed,
74 &ifp->stats.rx_multicast,
76 &ifp->stats.tx_bytes,
77 &ifp->stats.tx_packets,
78 &ifp->stats.tx_errors,
79 &ifp->stats.tx_dropped,
80 &ifp->stats.tx_fifo_errors,
81 &ifp->stats.collisions,
82 &ifp->stats.tx_carrier_errors,
83 &ifp->stats.tx_compressed);
84 break;
85 case 2:
86 sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
87 &ifp->stats.rx_bytes,
88 &ifp->stats.rx_packets,
89 &ifp->stats.rx_errors,
90 &ifp->stats.rx_dropped,
91 &ifp->stats.rx_fifo_errors,
92 &ifp->stats.rx_frame_errors,
94 &ifp->stats.tx_bytes,
95 &ifp->stats.tx_packets,
96 &ifp->stats.tx_errors,
97 &ifp->stats.tx_dropped,
98 &ifp->stats.tx_fifo_errors,
99 &ifp->stats.collisions,
100 &ifp->stats.tx_carrier_errors);
101 ifp->stats.rx_multicast = 0;
102 break;
103 case 1:
104 sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
105 &ifp->stats.rx_packets,
106 &ifp->stats.rx_errors,
107 &ifp->stats.rx_dropped,
108 &ifp->stats.rx_fifo_errors,
109 &ifp->stats.rx_frame_errors,
111 &ifp->stats.tx_packets,
112 &ifp->stats.tx_errors,
113 &ifp->stats.tx_dropped,
114 &ifp->stats.tx_fifo_errors,
115 &ifp->stats.collisions,
116 &ifp->stats.tx_carrier_errors);
117 ifp->stats.rx_bytes = 0;
118 ifp->stats.tx_bytes = 0;
119 ifp->stats.rx_multicast = 0;
120 break;
122 return 0;
125 /* Update interface's statistics. */
126 void
127 ifstat_update_proc (void)
129 FILE *fp;
130 char buf[PROCBUFSIZ];
131 int version;
132 struct interface *ifp;
133 char *stat;
134 char *name;
136 /* Open /proc/net/dev. */
137 fp = fopen (_PATH_PROC_NET_DEV, "r");
138 if (fp == NULL)
140 zlog_warn ("Can't open proc file %s: %s",
141 _PATH_PROC_NET_DEV, safe_strerror (errno));
142 return;
145 /* Drop header lines. */
146 fgets (buf, PROCBUFSIZ, fp);
147 fgets (buf, PROCBUFSIZ, fp);
149 /* To detect proc format veresion, parse second line. */
150 if (strstr (buf, "compressed"))
151 version = 3;
152 else if (strstr (buf, "bytes"))
153 version = 2;
154 else
155 version = 1;
157 /* Update each interface's statistics. */
158 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
160 stat = interface_name_cut (buf, &name);
161 ifp = if_get_by_name (name);
162 ifstat_dev_fields (version, stat, ifp);
164 fclose(fp);
165 return;
168 /* Interface structure allocation by proc filesystem. */
170 interface_list_proc ()
172 FILE *fp;
173 char buf[PROCBUFSIZ];
174 struct interface *ifp;
175 char *name;
177 /* Open /proc/net/dev. */
178 fp = fopen (_PATH_PROC_NET_DEV, "r");
179 if (fp == NULL)
181 zlog_warn ("Can't open proc file %s: %s",
182 _PATH_PROC_NET_DEV, safe_strerror (errno));
183 return -1;
186 /* Drop header lines. */
187 fgets (buf, PROCBUFSIZ, fp);
188 fgets (buf, PROCBUFSIZ, fp);
190 /* Only allocate interface structure. Other jobs will be done in
191 if_ioctl.c. */
192 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
194 interface_name_cut (buf, &name);
195 ifp = if_get_by_name (name);
196 if_add_update (ifp);
198 fclose(fp);
199 return 0;
202 #if defined(HAVE_IPV6) && defined(HAVE_PROC_NET_IF_INET6)
204 #ifndef _PATH_PROC_NET_IF_INET6
205 #define _PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
206 #endif /* _PATH_PROC_NET_IF_INET6 */
209 ifaddr_proc_ipv6 ()
211 FILE *fp;
212 char buf[PROCBUFSIZ];
213 int n;
214 char addr[33];
215 char ifname[21];
216 int ifindex, plen, scope, status;
217 struct interface *ifp;
218 struct prefix_ipv6 p;
220 /* Open proc file system. */
221 fp = fopen (_PATH_PROC_NET_IF_INET6, "r");
222 if (fp == NULL)
224 zlog_warn ("Can't open proc file %s: %s",
225 _PATH_PROC_NET_IF_INET6, safe_strerror (errno));
226 return -1;
229 /* Get interface's IPv6 address. */
230 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
232 n = sscanf (buf, "%32s %02x %02x %02x %02x %20s",
233 addr, &ifindex, &plen, &scope, &status, ifname);
234 if (n != 6)
235 continue;
237 ifp = if_get_by_name (ifname);
239 /* Fetch interface's IPv6 address. */
240 str2in6_addr (addr, &p.prefix);
241 p.prefixlen = plen;
243 connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname);
245 fclose (fp);
246 return 0;
248 #endif /* HAVE_IPV6 && HAVE_PROC_NET_IF_INET6 */