and added files
[bcm963xx.git] / userapps / opensource / zebra / 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 #ifdef BRCM_LIST_SUPPORT
23
24 #include <zebra.h>
25
26 #include "if.h"
27 #include "prefix.h"
28 #include "log.h"
29
30 #include "zebra/ioctl.h"
31 #include "zebra/connected.h"
32 #include "zebra/interface.h"
33
34 /* Proc filesystem one line buffer. */
35 #define PROCBUFSIZ                  1024
36
37 /* Path to device proc file system. */
38 #ifndef _PATH_PROC_NET_DEV
39 #define _PATH_PROC_NET_DEV        "/proc/net/dev"
40 #endif /* _PATH_PROC_NET_DEV */
41
42 /* Return statistics data pointer. */
43 static char *
44 interface_name_cut (char *buf, char **name)
45 {
46   char *stat;
47
48   /* Skip white space.  Line will include header spaces. */
49   while (*buf == ' ')
50     buf++;
51   *name = buf;
52
53   /* Cut interface name. */
54   stat = strrchr (buf, ':');
55   *stat++ = '\0';
56
57   return stat;
58 }
59
60 /* Fetch each statistics field. */
61 static int
62 ifstat_dev_fields (int version, char *buf, struct interface *ifp)
63 {
64   switch (version) 
65     {
66     case 3:
67       sscanf(buf,
68              "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
69              &ifp->stats.rx_bytes,
70              &ifp->stats.rx_packets,
71              &ifp->stats.rx_errors,
72              &ifp->stats.rx_dropped,
73              &ifp->stats.rx_fifo_errors,
74              &ifp->stats.rx_frame_errors,
75              &ifp->stats.rx_compressed,
76              &ifp->stats.rx_multicast,
77
78              &ifp->stats.tx_bytes,
79              &ifp->stats.tx_packets,
80              &ifp->stats.tx_errors,
81              &ifp->stats.tx_dropped,
82              &ifp->stats.tx_fifo_errors,
83              &ifp->stats.collisions,
84              &ifp->stats.tx_carrier_errors,
85              &ifp->stats.tx_compressed);
86       break;
87     case 2:
88       sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
89              &ifp->stats.rx_bytes,
90              &ifp->stats.rx_packets,
91              &ifp->stats.rx_errors,
92              &ifp->stats.rx_dropped,
93              &ifp->stats.rx_fifo_errors,
94              &ifp->stats.rx_frame_errors,
95
96              &ifp->stats.tx_bytes,
97              &ifp->stats.tx_packets,
98              &ifp->stats.tx_errors,
99              &ifp->stats.tx_dropped,
100              &ifp->stats.tx_fifo_errors,
101              &ifp->stats.collisions,
102              &ifp->stats.tx_carrier_errors);
103       ifp->stats.rx_multicast = 0;
104       break;
105     case 1:
106       sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
107              &ifp->stats.rx_packets,
108              &ifp->stats.rx_errors,
109              &ifp->stats.rx_dropped,
110              &ifp->stats.rx_fifo_errors,
111              &ifp->stats.rx_frame_errors,
112
113              &ifp->stats.tx_packets,
114              &ifp->stats.tx_errors,
115              &ifp->stats.tx_dropped,
116              &ifp->stats.tx_fifo_errors,
117              &ifp->stats.collisions,
118              &ifp->stats.tx_carrier_errors);
119       ifp->stats.rx_bytes = 0;
120       ifp->stats.tx_bytes = 0;
121       ifp->stats.rx_multicast = 0;
122       break;
123     }
124   return 0;
125 }
126
127 /* Update interface's statistics. */
128 int
129 ifstat_update_proc ()
130 {
131   FILE *fp;
132   char buf[PROCBUFSIZ];
133   int version;
134   struct interface *ifp;
135   char *stat;
136   char *name;
137
138   /* Open /proc/net/dev. */
139   fp = fopen (_PATH_PROC_NET_DEV, "r");
140   if (fp == NULL)
141     {
142       zlog_warn ("Can't open proc file %s: %s",
143                  _PATH_PROC_NET_DEV, strerror (errno));
144       return -1;
145     }
146
147   /* Drop header lines. */
148   fgets (buf, PROCBUFSIZ, fp);
149   fgets (buf, PROCBUFSIZ, fp);
150
151   /* To detect proc format veresion, parse second line. */
152   if (strstr (buf, "compressed"))
153     version = 3;
154   else if (strstr (buf, "bytes"))
155     version = 2;
156   else
157     version = 1;
158
159   /* Update each interface's statistics. */
160   while (fgets (buf, PROCBUFSIZ, fp) != NULL)
161     {
162       stat = interface_name_cut (buf, &name);
163       ifp = if_get_by_name (name);
164       ifstat_dev_fields (version, stat, ifp);
165     }
166
167   return 0;
168 }
169
170 /* Interface structure allocation by proc filesystem. */
171 int
172 interface_list_proc ()
173 {
174   FILE *fp;
175   char buf[PROCBUFSIZ];
176   struct interface *ifp;
177   char *name;
178
179   /* Open /proc/net/dev. */
180   fp = fopen (_PATH_PROC_NET_DEV, "r");
181   if (fp == NULL)
182     {
183       zlog_warn ("Can't open proc file %s: %s",
184                  _PATH_PROC_NET_DEV, strerror (errno));
185       return -1;
186     }
187
188   /* Drop header lines. */
189   fgets (buf, PROCBUFSIZ, fp);
190   fgets (buf, PROCBUFSIZ, fp);
191
192   /* Only allocate interface structure.  Other jobs will be done in
193      if_ioctl.c. */
194   while (fgets (buf, PROCBUFSIZ, fp) != NULL)
195     {
196       interface_name_cut (buf, &name);
197       ifp = if_get_by_name (name);
198       if_add_update (ifp);
199     }
200   return 0;
201 }
202 \f
203 #if defined(HAVE_IPV6) && defined(HAVE_PROC_NET_IF_INET6)
204
205 #ifndef _PATH_PROC_NET_IF_INET6
206 #define _PATH_PROC_NET_IF_INET6          "/proc/net/if_inet6"
207 #endif /* _PATH_PROC_NET_IF_INET6 */
208
209 int
210 ifaddr_proc_ipv6 ()
211 {
212   FILE *fp;
213   char buf[PROCBUFSIZ];
214   int n;
215   char addr[33];
216   char ifname[20];
217   int ifindex, plen, scope, status;
218   struct interface *ifp;
219   struct prefix_ipv6 p;
220
221   /* Open proc file system. */
222   fp = fopen (_PATH_PROC_NET_IF_INET6, "r");
223   if (fp == NULL)
224     {
225       zlog_warn ("Can't open proc file %s: %s",
226                  _PATH_PROC_NET_IF_INET6, strerror (errno));
227       return -1;
228     }
229   
230   /* Get interface's IPv6 address. */
231   while (fgets (buf, PROCBUFSIZ, fp) != NULL)
232     {
233       n = sscanf (buf, "%32s %02x %02x %02x %02x %20s", 
234                   addr, &ifindex, &plen, &scope, &status, ifname);
235       if (n != 6)
236         continue;
237
238       ifp = if_get_by_name (ifname);
239
240       /* Fetch interface's IPv6 address. */
241       str2in6_addr (addr, &p.prefix);
242       p.prefixlen = plen;
243
244       connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL);
245     }
246   return 0;
247 }
248 #endif /* HAVE_IPV6 && HAVE_PROC_NET_IF_INET6 */
249
250 #endif /* BRCM_LIST_SUPPORT */