]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/if_ioctl.c
2 * Interface looking up by ioctl ().
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "sockunion.h"
28 #include "connected.h"
30 #include "zebra_memory.h"
35 #include "zebra/interface.h"
36 #include "zebra/rib.h"
40 /* Interface looking up using infamous SIOCGIFCONF. */
42 interface_list_ioctl (void)
50 struct interface
*ifp
;
54 /* Normally SIOCGIFCONF works with AF_INET socket. */
55 sock
= socket (AF_INET
, SOCK_DGRAM
, 0);
58 zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno
));
62 /* Set initial ifreq count. This will be double when SIOCGIFCONF
63 fail. Solaris has SIOCGIFNUM. */
65 ret
= ioctl (sock
, SIOCGIFNUM
, &ifnum
);
72 #endif /* SIOCGIFNUM */
74 ifconf
.ifc_buf
= NULL
;
77 /* Loop until SIOCGIFCONF success. */
80 ifconf
.ifc_len
= sizeof (struct ifreq
) * ifnum
;
81 ifconf
.ifc_buf
= XREALLOC(MTYPE_TMP
, ifconf
.ifc_buf
, ifconf
.ifc_len
);
83 ret
= ioctl(sock
, SIOCGIFCONF
, &ifconf
);
87 zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno
));
90 /* Repeatedly get info til buffer fails to grow. */
91 if (ifconf
.ifc_len
> lastlen
)
93 lastlen
= ifconf
.ifc_len
;
101 /* Allocate interface. */
102 ifreq
= ifconf
.ifc_req
;
105 for (n
= 0; n
< ifconf
.ifc_len
; )
109 ifreq
= (struct ifreq
*)((caddr_t
) ifconf
.ifc_req
+ n
);
110 ifp
= if_get_by_name_len(ifreq
->ifr_name
,
111 strnlen(ifreq
->ifr_name
,
112 sizeof(ifreq
->ifr_name
)),
115 size
= ifreq
->ifr_addr
.sa_len
;
116 if (size
< sizeof (ifreq
->ifr_addr
))
117 size
= sizeof (ifreq
->ifr_addr
);
118 size
+= sizeof (ifreq
->ifr_name
);
122 for (n
= 0; n
< ifconf
.ifc_len
; n
+= sizeof(struct ifreq
))
124 ifp
= if_get_by_name_len(ifreq
->ifr_name
,
125 strnlen(ifreq
->ifr_name
,
126 sizeof(ifreq
->ifr_name
)),
131 #endif /* OPEN_BSD */
135 XFREE (MTYPE_TMP
, ifconf
.ifc_buf
);
140 /* Get interface's index by ioctl. */
142 if_get_index (struct interface
*ifp
)
144 ifp
->ifindex
= if_nametoindex(ifp
->name
);
150 if_get_hwaddr (struct interface
*ifp
)
156 strncpy (ifreq
.ifr_name
, ifp
->name
, IFNAMSIZ
);
157 ifreq
.ifr_addr
.sa_family
= AF_INET
;
159 /* Fetch Hardware address if available. */
160 ret
= if_ioctl (SIOCGIFHWADDR
, (caddr_t
) &ifreq
);
162 ifp
->hw_addr_len
= 0;
165 memcpy (ifp
->hw_addr
, ifreq
.ifr_hwaddr
.sa_data
, 6);
167 for (i
= 0; i
< 6; i
++)
168 if (ifp
->hw_addr
[i
] != 0)
172 ifp
->hw_addr_len
= 0;
174 ifp
->hw_addr_len
= 6;
178 #endif /* SIOCGIFHWADDR */
184 struct ifaddrs
*ifap
;
185 struct ifaddrs
*ifapfree
;
186 struct interface
*ifp
;
189 ret
= getifaddrs (&ifap
);
192 zlog_err ("getifaddrs(): %s", safe_strerror (errno
));
196 for (ifapfree
= ifap
; ifap
; ifap
= ifap
->ifa_next
)
198 if (ifap
->ifa_addr
== NULL
)
200 zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s",
201 __func__
, (ifap
->ifa_name
? ifap
->ifa_name
: "(null)"));
205 ifp
= if_lookup_by_name (ifap
->ifa_name
, VRF_DEFAULT
);
208 zlog_err ("if_getaddrs(): Can't lookup interface %s\n",
213 if (ifap
->ifa_addr
->sa_family
== AF_INET
)
215 struct sockaddr_in
*addr
;
216 struct sockaddr_in
*mask
;
217 struct sockaddr_in
*dest
;
218 struct in_addr
*dest_pnt
;
221 addr
= (struct sockaddr_in
*) ifap
->ifa_addr
;
222 mask
= (struct sockaddr_in
*) ifap
->ifa_netmask
;
223 prefixlen
= ip_masklen (mask
->sin_addr
);
227 if (ifap
->ifa_dstaddr
&&
228 !IPV4_ADDR_SAME(&addr
->sin_addr
,
229 &((struct sockaddr_in
*)
230 ifap
->ifa_dstaddr
)->sin_addr
))
232 dest
= (struct sockaddr_in
*) ifap
->ifa_dstaddr
;
233 dest_pnt
= &dest
->sin_addr
;
234 flags
= ZEBRA_IFA_PEER
;
236 else if (ifap
->ifa_broadaddr
&&
237 !IPV4_ADDR_SAME(&addr
->sin_addr
,
238 &((struct sockaddr_in
*)
239 ifap
->ifa_broadaddr
)->sin_addr
))
241 dest
= (struct sockaddr_in
*) ifap
->ifa_broadaddr
;
242 dest_pnt
= &dest
->sin_addr
;
245 connected_add_ipv4 (ifp
, flags
, &addr
->sin_addr
,
246 prefixlen
, dest_pnt
, NULL
);
248 if (ifap
->ifa_addr
->sa_family
== AF_INET6
)
250 struct sockaddr_in6
*addr
;
251 struct sockaddr_in6
*mask
;
252 struct sockaddr_in6
*dest
;
253 struct in6_addr
*dest_pnt
;
256 addr
= (struct sockaddr_in6
*) ifap
->ifa_addr
;
257 mask
= (struct sockaddr_in6
*) ifap
->ifa_netmask
;
258 prefixlen
= ip6_masklen (mask
->sin6_addr
);
262 if (ifap
->ifa_dstaddr
&&
263 !IPV6_ADDR_SAME(&addr
->sin6_addr
,
264 &((struct sockaddr_in6
*)
265 ifap
->ifa_dstaddr
)->sin6_addr
))
267 dest
= (struct sockaddr_in6
*) ifap
->ifa_dstaddr
;
268 dest_pnt
= &dest
->sin6_addr
;
269 flags
= ZEBRA_IFA_PEER
;
271 else if (ifap
->ifa_broadaddr
&&
272 !IPV6_ADDR_SAME(&addr
->sin6_addr
,
273 &((struct sockaddr_in6
*)
274 ifap
->ifa_broadaddr
)->sin6_addr
))
276 dest
= (struct sockaddr_in6
*) ifap
->ifa_broadaddr
;
277 dest_pnt
= &dest
->sin6_addr
;
281 if (IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
))
283 addr
->sin6_scope_id
=
284 ntohs(*(u_int16_t
*)&addr
->sin6_addr
.s6_addr
[2]);
285 addr
->sin6_addr
.s6_addr
[2] = addr
->sin6_addr
.s6_addr
[3] = 0;
289 connected_add_ipv6 (ifp
, flags
, &addr
->sin6_addr
, prefixlen
,
294 freeifaddrs (ifapfree
);
299 /* Fetch interface information via ioctl(). */
301 interface_info_ioctl ()
303 struct listnode
*node
, *nnode
;
304 struct interface
*ifp
;
306 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT
), node
, nnode
, ifp
))
311 #endif /* SIOCGIFHWADDR */
318 /* Lookup all interface information. */
320 interface_list (struct zebra_ns
*zns
)
323 zlog_info ("interface_list: NS %u", zns
->ns_id
);
325 /* Linux can do both proc & ioctl, ioctl is the only way to get
326 interface aliases in 2.2 series kernels. */
327 #ifdef HAVE_PROC_NET_DEV
328 interface_list_proc ();
329 #endif /* HAVE_PROC_NET_DEV */
330 interface_list_ioctl ();
332 /* After listing is done, get index, address, flags and other
333 interface's information. */
334 interface_info_ioctl ();
338 #if defined(HAVE_PROC_NET_IF_INET6)
339 /* Linux provides interface's IPv6 address via
340 /proc/net/if_inet6. */
342 #endif /* HAVE_PROC_NET_IF_INET6 */