|  | /* Determine whether interfaces use native transport.  Linux version. | 
|  | Copyright (C) 2007 Free Software Foundation, Inc. | 
|  | This file is part of the GNU C Library. | 
|  |  | 
|  | The GNU C Library is free software; you can redistribute it and/or | 
|  | modify it under the terms of the GNU Lesser General Public | 
|  | License as published by the Free Software Foundation; either | 
|  | version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | The GNU C Library is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | Lesser General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU Lesser General Public | 
|  | License along with the GNU C Library; if not, write to the Free | 
|  | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | 
|  | 02111-1307 USA.  */ | 
|  |  | 
|  | /* AKAROS note: this is the linux version, neutered/commented out.  Needed to let | 
|  | * getaddrinfo compile */ | 
|  | #include <assert.h> | 
|  | #include <errno.h> | 
|  | #include <ifaddrs.h> | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  | #include <stdlib.h> | 
|  | #include <time.h> | 
|  | #include <unistd.h> | 
|  | #include <net/if.h> | 
|  | //#include <net/if_arp.h> | 
|  | //#include <sys/ioctl.h> | 
|  |  | 
|  | //#include <asm/types.h> | 
|  | //#include <linux/netlink.h> | 
|  | //#include <linux/rtnetlink.h> | 
|  |  | 
|  | #include <not-cancel.h> | 
|  |  | 
|  | void | 
|  | __check_native (uint32_t a1_index, int *a1_native, | 
|  | uint32_t a2_index, int *a2_native) | 
|  | { | 
|  | } | 
|  |  | 
|  | #if 0 | 
|  | void | 
|  | __check_native (uint32_t a1_index, int *a1_native, | 
|  | uint32_t a2_index, int *a2_native) | 
|  | { | 
|  | int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | 
|  |  | 
|  | struct sockaddr_nl nladdr; | 
|  | memset (&nladdr, '\0', sizeof (nladdr)); | 
|  | nladdr.nl_family = AF_NETLINK; | 
|  |  | 
|  | socklen_t addr_len = sizeof (nladdr); | 
|  |  | 
|  | if (fd < 0 | 
|  | || __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0 | 
|  | || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0) | 
|  | return; | 
|  |  | 
|  | pid_t pid = nladdr.nl_pid; | 
|  | struct req | 
|  | { | 
|  | struct nlmsghdr nlh; | 
|  | struct rtgenmsg g; | 
|  | /* struct rtgenmsg consists of a single byte.  This means there | 
|  | are three bytes of padding included in the REQ definition. | 
|  | We make them explicit here.  */ | 
|  | char pad[3]; | 
|  | } req; | 
|  |  | 
|  | req.nlh.nlmsg_len = sizeof (req); | 
|  | req.nlh.nlmsg_type = RTM_GETLINK; | 
|  | req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; | 
|  | req.nlh.nlmsg_pid = 0; | 
|  | req.nlh.nlmsg_seq = time (NULL); | 
|  | req.g.rtgen_family = AF_UNSPEC; | 
|  |  | 
|  | assert (sizeof (req) - offsetof (struct req, pad) == 3); | 
|  | memset (req.pad, '\0', sizeof (req.pad)); | 
|  |  | 
|  | memset (&nladdr, '\0', sizeof (nladdr)); | 
|  | nladdr.nl_family = AF_NETLINK; | 
|  |  | 
|  | #ifdef PAGE_SIZE | 
|  | /* Help the compiler optimize out the malloc call if PAGE_SIZE | 
|  | is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */ | 
|  | const size_t buf_size = PAGE_SIZE; | 
|  | #else | 
|  | const size_t buf_size = __getpagesize (); | 
|  | #endif | 
|  | bool use_malloc = false; | 
|  | char *buf; | 
|  |  | 
|  | if (__libc_use_alloca (buf_size)) | 
|  | buf = alloca (buf_size); | 
|  | else | 
|  | { | 
|  | buf = malloc (buf_size); | 
|  | if (buf != NULL) | 
|  | use_malloc = true; | 
|  | else | 
|  | goto out_fail; | 
|  | } | 
|  |  | 
|  | struct iovec iov = { buf, buf_size }; | 
|  |  | 
|  | if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0, | 
|  | (struct sockaddr *) &nladdr, | 
|  | sizeof (nladdr))) < 0) | 
|  | goto out_fail; | 
|  |  | 
|  | bool done = false; | 
|  | do | 
|  | { | 
|  | struct msghdr msg = | 
|  | { | 
|  | (void *) &nladdr, sizeof (nladdr), | 
|  | &iov, 1, | 
|  | NULL, 0, | 
|  | 0 | 
|  | }; | 
|  |  | 
|  | ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0)); | 
|  | if (read_len < 0) | 
|  | goto out_fail; | 
|  |  | 
|  | if (msg.msg_flags & MSG_TRUNC) | 
|  | goto out_fail; | 
|  |  | 
|  | struct nlmsghdr *nlmh; | 
|  | for (nlmh = (struct nlmsghdr *) buf; | 
|  | NLMSG_OK (nlmh, (size_t) read_len); | 
|  | nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len)) | 
|  | { | 
|  | if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != pid | 
|  | || nlmh->nlmsg_seq != req.nlh.nlmsg_seq) | 
|  | continue; | 
|  |  | 
|  | if (nlmh->nlmsg_type == RTM_NEWLINK) | 
|  | { | 
|  | struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlmh); | 
|  | int native = (ifim->ifi_type != ARPHRD_TUNNEL6 | 
|  | && ifim->ifi_type != ARPHRD_TUNNEL | 
|  | && ifim->ifi_type != ARPHRD_SIT); | 
|  |  | 
|  | if (a1_index == ifim->ifi_index) | 
|  | { | 
|  | *a1_native = native; | 
|  | a1_index = 0xffffffffu; | 
|  | } | 
|  | if (a2_index == ifim->ifi_index) | 
|  | { | 
|  | *a2_native = native; | 
|  | a2_index = 0xffffffffu; | 
|  | } | 
|  |  | 
|  | if (a1_index == 0xffffffffu | 
|  | && a2_index == 0xffffffffu) | 
|  | goto out; | 
|  | } | 
|  | else if (nlmh->nlmsg_type == NLMSG_DONE) | 
|  | /* We found the end, leave the loop.  */ | 
|  | done = true; | 
|  | } | 
|  | } | 
|  | while (! done); | 
|  |  | 
|  | out: | 
|  | close_not_cancel_no_status (fd); | 
|  |  | 
|  | return; | 
|  |  | 
|  | out_fail: | 
|  | if (use_malloc) | 
|  | free (buf); | 
|  | } | 
|  | #endif |