]>
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
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include "sockunion.h"
29 #include "connected.h"
31 #include "zebra_memory.h"
36 #include "zebra/interface.h"
37 #include "zebra/rib.h"
41 /* Interface looking up using infamous SIOCGIFCONF. */
43 interface_list_ioctl (void)
51 struct interface
*ifp
;
55 /* Normally SIOCGIFCONF works with AF_INET socket. */
56 sock
= socket (AF_INET
, SOCK_DGRAM
, 0);
59 zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno
));
63 /* Set initial ifreq count. This will be double when SIOCGIFCONF
64 fail. Solaris has SIOCGIFNUM. */
66 ret
= ioctl (sock
, SIOCGIFNUM
, &ifnum
);
73 #endif /* SIOCGIFNUM */
75 ifconf
.ifc_buf
= NULL
;
78 /* Loop until SIOCGIFCONF success. */
81 ifconf
.ifc_len
= sizeof (struct ifreq
) * ifnum
;
82 ifconf
.ifc_buf
= XREALLOC(MTYPE_TMP
, ifconf
.ifc_buf
, ifconf
.ifc_len
);
84 ret
= ioctl(sock
, SIOCGIFCONF
, &ifconf
);
88 zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno
));
91 /* Repeatedly get info til buffer fails to grow. */
92 if (ifconf
.ifc_len
> lastlen
)
94 lastlen
= ifconf
.ifc_len
;
102 /* Allocate interface. */
103 ifreq
= ifconf
.ifc_req
;
106 for (n
= 0; n
< ifconf
.ifc_len
; )
110 ifreq
= (struct ifreq
*)((caddr_t
) ifconf
.ifc_req
+ n
);
111 ifp
= if_get_by_name_len(ifreq
->ifr_name
,
112 strnlen(ifreq
->ifr_name
,
113 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
)));
130 #endif /* OPEN_BSD */
134 XFREE (MTYPE_TMP
, ifconf
.ifc_buf
);
139 /* Get interface's index by ioctl. */
141 if_get_index (struct interface
*ifp
)
143 ifp
->ifindex
= if_nametoindex(ifp
->name
);
149 if_get_hwaddr (struct interface
*ifp
)
155 strncpy (ifreq
.ifr_name
, ifp
->name
, IFNAMSIZ
);
156 ifreq
.ifr_addr
.sa_family
= AF_INET
;
158 /* Fetch Hardware address if available. */
159 ret
= if_ioctl (SIOCGIFHWADDR
, (caddr_t
) &ifreq
);
161 ifp
->hw_addr_len
= 0;
164 memcpy (ifp
->hw_addr
, ifreq
.ifr_hwaddr
.sa_data
, 6);
166 for (i
= 0; i
< 6; i
++)
167 if (ifp
->hw_addr
[i
] != 0)
171 ifp
->hw_addr_len
= 0;
173 ifp
->hw_addr_len
= 6;
177 #endif /* SIOCGIFHWADDR */
183 struct ifaddrs
*ifap
;
184 struct ifaddrs
*ifapfree
;
185 struct interface
*ifp
;
188 ret
= getifaddrs (&ifap
);
191 zlog_err ("getifaddrs(): %s", safe_strerror (errno
));
195 for (ifapfree
= ifap
; ifap
; ifap
= ifap
->ifa_next
)
197 if (ifap
->ifa_addr
== NULL
)
199 zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s",
200 __func__
, (ifap
->ifa_name
? ifap
->ifa_name
: "(null)"));
204 ifp
= if_lookup_by_name (ifap
->ifa_name
);
207 zlog_err ("if_getaddrs(): Can't lookup interface %s\n",
212 if (ifap
->ifa_addr
->sa_family
== AF_INET
)
214 struct sockaddr_in
*addr
;
215 struct sockaddr_in
*mask
;
216 struct sockaddr_in
*dest
;
217 struct in_addr
*dest_pnt
;
220 addr
= (struct sockaddr_in
*) ifap
->ifa_addr
;
221 mask
= (struct sockaddr_in
*) ifap
->ifa_netmask
;
222 prefixlen
= ip_masklen (mask
->sin_addr
);
226 if (ifap
->ifa_dstaddr
&&
227 !IPV4_ADDR_SAME(&addr
->sin_addr
,
228 &((struct sockaddr_in
*)
229 ifap
->ifa_dstaddr
)->sin_addr
))
231 dest
= (struct sockaddr_in
*) ifap
->ifa_dstaddr
;
232 dest_pnt
= &dest
->sin_addr
;
233 flags
= ZEBRA_IFA_PEER
;
235 else if (ifap
->ifa_broadaddr
&&
236 !IPV4_ADDR_SAME(&addr
->sin_addr
,
237 &((struct sockaddr_in
*)
238 ifap
->ifa_broadaddr
)->sin_addr
))
240 dest
= (struct sockaddr_in
*) ifap
->ifa_broadaddr
;
241 dest_pnt
= &dest
->sin_addr
;
244 connected_add_ipv4 (ifp
, flags
, &addr
->sin_addr
,
245 prefixlen
, dest_pnt
, NULL
);
247 if (ifap
->ifa_addr
->sa_family
== AF_INET6
)
249 struct sockaddr_in6
*addr
;
250 struct sockaddr_in6
*mask
;
251 struct sockaddr_in6
*dest
;
252 struct in6_addr
*dest_pnt
;
255 addr
= (struct sockaddr_in6
*) ifap
->ifa_addr
;
256 mask
= (struct sockaddr_in6
*) ifap
->ifa_netmask
;
257 prefixlen
= ip6_masklen (mask
->sin6_addr
);
261 if (ifap
->ifa_dstaddr
&&
262 !IPV6_ADDR_SAME(&addr
->sin6_addr
,
263 &((struct sockaddr_in6
*)
264 ifap
->ifa_dstaddr
)->sin6_addr
))
266 dest
= (struct sockaddr_in6
*) ifap
->ifa_dstaddr
;
267 dest_pnt
= &dest
->sin6_addr
;
268 flags
= ZEBRA_IFA_PEER
;
270 else if (ifap
->ifa_broadaddr
&&
271 !IPV6_ADDR_SAME(&addr
->sin6_addr
,
272 &((struct sockaddr_in6
*)
273 ifap
->ifa_broadaddr
)->sin6_addr
))
275 dest
= (struct sockaddr_in6
*) ifap
->ifa_broadaddr
;
276 dest_pnt
= &dest
->sin6_addr
;
280 if (IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
))
282 addr
->sin6_scope_id
=
283 ntohs(*(u_int16_t
*)&addr
->sin6_addr
.s6_addr
[2]);
284 addr
->sin6_addr
.s6_addr
[2] = addr
->sin6_addr
.s6_addr
[3] = 0;
288 connected_add_ipv6 (ifp
, flags
, &addr
->sin6_addr
, prefixlen
,
293 freeifaddrs (ifapfree
);
298 /* Fetch interface information via ioctl(). */
300 interface_info_ioctl ()
302 struct listnode
*node
, *nnode
;
303 struct interface
*ifp
;
305 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT
), node
, nnode
, ifp
))
310 #endif /* SIOCGIFHWADDR */
317 /* Lookup all interface information. */
319 interface_list (struct zebra_ns
*zns
)
322 zlog_info ("interface_list: NS %u", zns
->ns_id
);
324 /* Linux can do both proc & ioctl, ioctl is the only way to get
325 interface aliases in 2.2 series kernels. */
326 #ifdef HAVE_PROC_NET_DEV
327 interface_list_proc ();
328 #endif /* HAVE_PROC_NET_DEV */
329 interface_list_ioctl ();
331 /* After listing is done, get index, address, flags and other
332 interface's information. */
333 interface_info_ioctl ();
337 #if defined(HAVE_PROC_NET_IF_INET6)
338 /* Linux provides interface's IPv6 address via
339 /proc/net/if_inet6. */
341 #endif /* HAVE_PROC_NET_IF_INET6 */