]> git.proxmox.com Git - mirror_frr.git/blob - zebra/if_proc.c
Initial revision
[mirror_frr.git] / zebra / if_proc.c
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
22 #include <zebra.h>
23
24 #include "if.h"
25 #include "prefix.h"
26 #include "log.h"
27
28 #include "zebra/ioctl.h"
29 #include "zebra/connected.h"
30 #include "zebra/interface.h"
31
32 /* Proc filesystem one line buffer. */
33 #define PROCBUFSIZ 1024
34
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 */
39
40 /* Return statistics data pointer. */
41 static char *
42 interface_name_cut (char *buf, char **name)
43 {
44 char *stat;
45
46 /* Skip white space. Line will include header spaces. */
47 while (*buf == ' ')
48 buf++;
49 *name = buf;
50
51 /* Cut interface name. */
52 stat = strrchr (buf, ':');
53 *stat++ = '\0';
54
55 return stat;
56 }
57
58 /* Fetch each statistics field. */
59 static int
60 ifstat_dev_fields (int version, char *buf, struct interface *ifp)
61 {
62 switch (version)
63 {
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,
75
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,
93
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,
110
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;
121 }
122 return 0;
123 }
124
125 /* Update interface's statistics. */
126 int
127 ifstat_update_proc ()
128 {
129 FILE *fp;
130 char buf[PROCBUFSIZ];
131 int version;
132 struct interface *ifp;
133 char *stat;
134 char *name;
135
136 /* Open /proc/net/dev. */
137 fp = fopen (_PATH_PROC_NET_DEV, "r");
138 if (fp == NULL)
139 {
140 zlog_warn ("Can't open proc file %s: %s",
141 _PATH_PROC_NET_DEV, strerror (errno));
142 return -1;
143 }
144
145 /* Drop header lines. */
146 fgets (buf, PROCBUFSIZ, fp);
147 fgets (buf, PROCBUFSIZ, fp);
148
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;
156
157 /* Update each interface's statistics. */
158 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
159 {
160 stat = interface_name_cut (buf, &name);
161 ifp = if_get_by_name (name);
162 ifstat_dev_fields (version, stat, ifp);
163 }
164
165 return 0;
166 }
167
168 /* Interface structure allocation by proc filesystem. */
169 int
170 interface_list_proc ()
171 {
172 FILE *fp;
173 char buf[PROCBUFSIZ];
174 struct interface *ifp;
175 char *name;
176
177 /* Open /proc/net/dev. */
178 fp = fopen (_PATH_PROC_NET_DEV, "r");
179 if (fp == NULL)
180 {
181 zlog_warn ("Can't open proc file %s: %s",
182 _PATH_PROC_NET_DEV, strerror (errno));
183 return -1;
184 }
185
186 /* Drop header lines. */
187 fgets (buf, PROCBUFSIZ, fp);
188 fgets (buf, PROCBUFSIZ, fp);
189
190 /* Only allocate interface structure. Other jobs will be done in
191 if_ioctl.c. */
192 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
193 {
194 interface_name_cut (buf, &name);
195 ifp = if_get_by_name (name);
196 if_add_update (ifp);
197 }
198 return 0;
199 }
200 \f
201 #if defined(HAVE_IPV6) && defined(HAVE_PROC_NET_IF_INET6)
202
203 #ifndef _PATH_PROC_NET_IF_INET6
204 #define _PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
205 #endif /* _PATH_PROC_NET_IF_INET6 */
206
207 int
208 ifaddr_proc_ipv6 ()
209 {
210 FILE *fp;
211 char buf[PROCBUFSIZ];
212 int n;
213 char addr[33];
214 char ifname[20];
215 int ifindex, plen, scope, status;
216 struct interface *ifp;
217 struct prefix_ipv6 p;
218
219 /* Open proc file system. */
220 fp = fopen (_PATH_PROC_NET_IF_INET6, "r");
221 if (fp == NULL)
222 {
223 zlog_warn ("Can't open proc file %s: %s",
224 _PATH_PROC_NET_IF_INET6, strerror (errno));
225 return -1;
226 }
227
228 /* Get interface's IPv6 address. */
229 while (fgets (buf, PROCBUFSIZ, fp) != NULL)
230 {
231 n = sscanf (buf, "%32s %02x %02x %02x %02x %20s",
232 addr, &ifindex, &plen, &scope, &status, ifname);
233 if (n != 6)
234 continue;
235
236 ifp = if_get_by_name (ifname);
237
238 /* Fetch interface's IPv6 address. */
239 str2in6_addr (addr, &p.prefix);
240 p.prefixlen = plen;
241
242 connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL);
243 }
244 return 0;
245 }
246 #endif /* HAVE_IPV6 && HAVE_PROC_NET_IF_INET6 */