]>
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. */
42 static int interface_list_ioctl(void)
50 struct interface
*ifp
;
54 /* Normally SIOCGIFCONF works with AF_INET socket. */
55 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
57 zlog_warn("Can't make AF_INET socket stream: %s",
58 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. */
79 ifconf
.ifc_len
= sizeof(struct ifreq
) * ifnum
;
81 XREALLOC(MTYPE_TMP
, ifconf
.ifc_buf
, ifconf
.ifc_len
);
83 ret
= ioctl(sock
, SIOCGIFCONF
, &ifconf
);
86 zlog_warn("SIOCGIFCONF: %s", safe_strerror(errno
));
89 /* Repeatedly get info til buffer fails to grow. */
90 if (ifconf
.ifc_len
> lastlen
) {
91 lastlen
= ifconf
.ifc_len
;
99 /* Allocate interface. */
100 ifreq
= ifconf
.ifc_req
;
103 for (n
= 0; n
< ifconf
.ifc_len
;) {
106 ifreq
= (struct ifreq
*)((caddr_t
)ifconf
.ifc_req
+ n
);
107 ifp
= if_get_by_name_len(
109 strnlen(ifreq
->ifr_name
, sizeof(ifreq
->ifr_name
)),
112 size
= ifreq
->ifr_addr
.sa_len
;
113 if (size
< sizeof(ifreq
->ifr_addr
))
114 size
= sizeof(ifreq
->ifr_addr
);
115 size
+= sizeof(ifreq
->ifr_name
);
119 for (n
= 0; n
< ifconf
.ifc_len
; n
+= sizeof(struct ifreq
)) {
120 ifp
= if_get_by_name_len(
122 strnlen(ifreq
->ifr_name
, sizeof(ifreq
->ifr_name
)),
127 #endif /* OPEN_BSD */
131 XFREE(MTYPE_TMP
, ifconf
.ifc_buf
);
136 /* Get interface's index by ioctl. */
137 static int if_get_index(struct interface
*ifp
)
139 ifp
->ifindex
= if_nametoindex(ifp
->name
);
144 static int if_get_hwaddr(struct interface
*ifp
)
150 strncpy(ifreq
.ifr_name
, ifp
->name
, IFNAMSIZ
);
151 ifreq
.ifr_addr
.sa_family
= AF_INET
;
153 /* Fetch Hardware address if available. */
154 ret
= if_ioctl(SIOCGIFHWADDR
, (caddr_t
)&ifreq
);
156 ifp
->hw_addr_len
= 0;
158 memcpy(ifp
->hw_addr
, ifreq
.ifr_hwaddr
.sa_data
, 6);
160 for (i
= 0; i
< 6; i
++)
161 if (ifp
->hw_addr
[i
] != 0)
165 ifp
->hw_addr_len
= 0;
167 ifp
->hw_addr_len
= 6;
171 #endif /* SIOCGIFHWADDR */
173 static int if_getaddrs(void)
176 struct ifaddrs
*ifap
;
177 struct ifaddrs
*ifapfree
;
178 struct interface
*ifp
;
181 ret
= getifaddrs(&ifap
);
183 zlog_err("getifaddrs(): %s", safe_strerror(errno
));
187 for (ifapfree
= ifap
; ifap
; ifap
= ifap
->ifa_next
) {
188 if (ifap
->ifa_addr
== NULL
) {
190 "%s: nonsensical ifaddr with NULL ifa_addr, ifname %s",
192 (ifap
->ifa_name
? ifap
->ifa_name
: "(null)"));
196 ifp
= if_lookup_by_name(ifap
->ifa_name
, VRF_DEFAULT
);
198 zlog_err("if_getaddrs(): Can't lookup interface %s\n",
203 if (ifap
->ifa_addr
->sa_family
== AF_INET
) {
204 struct sockaddr_in
*addr
;
205 struct sockaddr_in
*mask
;
206 struct sockaddr_in
*dest
;
207 struct in_addr
*dest_pnt
;
210 addr
= (struct sockaddr_in
*)ifap
->ifa_addr
;
211 mask
= (struct sockaddr_in
*)ifap
->ifa_netmask
;
212 prefixlen
= ip_masklen(mask
->sin_addr
);
216 if (ifap
->ifa_dstaddr
217 && !IPV4_ADDR_SAME(&addr
->sin_addr
,
218 &((struct sockaddr_in
*)
221 dest
= (struct sockaddr_in
*)ifap
->ifa_dstaddr
;
222 dest_pnt
= &dest
->sin_addr
;
223 flags
= ZEBRA_IFA_PEER
;
224 } else if (ifap
->ifa_broadaddr
227 &((struct sockaddr_in
*)
230 dest
= (struct sockaddr_in
*)
232 dest_pnt
= &dest
->sin_addr
;
235 connected_add_ipv4(ifp
, flags
, &addr
->sin_addr
,
236 prefixlen
, dest_pnt
, NULL
);
238 if (ifap
->ifa_addr
->sa_family
== AF_INET6
) {
239 struct sockaddr_in6
*addr
;
240 struct sockaddr_in6
*mask
;
241 struct sockaddr_in6
*dest
;
242 struct in6_addr
*dest_pnt
;
245 addr
= (struct sockaddr_in6
*)ifap
->ifa_addr
;
246 mask
= (struct sockaddr_in6
*)ifap
->ifa_netmask
;
247 prefixlen
= ip6_masklen(mask
->sin6_addr
);
251 if (ifap
->ifa_dstaddr
252 && !IPV6_ADDR_SAME(&addr
->sin6_addr
,
253 &((struct sockaddr_in6
*)
256 dest
= (struct sockaddr_in6
*)ifap
->ifa_dstaddr
;
257 dest_pnt
= &dest
->sin6_addr
;
258 flags
= ZEBRA_IFA_PEER
;
259 } else if (ifap
->ifa_broadaddr
262 &((struct sockaddr_in6
*)
265 dest
= (struct sockaddr_in6
*)
267 dest_pnt
= &dest
->sin6_addr
;
271 if (IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
272 addr
->sin6_scope_id
=
273 ntohs(*(u_int16_t
*)&addr
->sin6_addr
275 addr
->sin6_addr
.s6_addr
[2] =
276 addr
->sin6_addr
.s6_addr
[3] = 0;
280 connected_add_ipv6(ifp
, flags
, &addr
->sin6_addr
,
281 prefixlen
, dest_pnt
, NULL
);
285 freeifaddrs(ifapfree
);
290 /* Fetch interface information via ioctl(). */
291 static void interface_info_ioctl()
293 struct listnode
*node
, *nnode
;
294 struct interface
*ifp
;
296 for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT
), node
, nnode
, ifp
)) {
300 #endif /* SIOCGIFHWADDR */
307 /* Lookup all interface information. */
308 void interface_list(struct zebra_ns
*zns
)
311 zlog_info("interface_list: NS %u", zns
->ns_id
);
313 /* Linux can do both proc & ioctl, ioctl is the only way to get
314 interface aliases in 2.2 series kernels. */
315 #ifdef HAVE_PROC_NET_DEV
316 interface_list_proc();
317 #endif /* HAVE_PROC_NET_DEV */
318 interface_list_ioctl();
320 /* After listing is done, get index, address, flags and other
321 interface's information. */
322 interface_info_ioctl();
326 #if defined(HAVE_PROC_NET_IF_INET6)
327 /* Linux provides interface's IPv6 address via
328 /proc/net/if_inet6. */
330 #endif /* HAVE_PROC_NET_IF_INET6 */