Upgrade to gcc-4.9.2
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-ros / sysdeps / akaros / check_native.c
1 /* Determine whether interfaces use native transport.  Linux version.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 /* AKAROS note: this is the linux version, neutered/commented out.  Needed to let
21  * getaddrinfo compile */
22 #include <assert.h>
23 #include <errno.h>
24 #include <ifaddrs.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <net/if.h>
31 //#include <net/if_arp.h>
32 //#include <sys/ioctl.h>
33
34 //#include <asm/types.h>
35 //#include <linux/netlink.h>
36 //#include <linux/rtnetlink.h>
37
38 #include <not-cancel.h>
39
40 void
41 __check_native (uint32_t a1_index, int *a1_native,
42                 uint32_t a2_index, int *a2_native)
43 {
44 }
45
46 #if 0
47 void
48 __check_native (uint32_t a1_index, int *a1_native,
49                 uint32_t a2_index, int *a2_native)
50 {
51   int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
52
53   struct sockaddr_nl nladdr;
54   memset (&nladdr, '\0', sizeof (nladdr));
55   nladdr.nl_family = AF_NETLINK;
56
57   socklen_t addr_len = sizeof (nladdr);
58
59   if (fd < 0
60       || __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0
61       || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0)
62     return;
63
64   pid_t pid = nladdr.nl_pid;
65   struct req
66   {
67     struct nlmsghdr nlh;
68     struct rtgenmsg g;
69     /* struct rtgenmsg consists of a single byte.  This means there
70        are three bytes of padding included in the REQ definition.
71        We make them explicit here.  */
72     char pad[3];
73   } req;
74
75   req.nlh.nlmsg_len = sizeof (req);
76   req.nlh.nlmsg_type = RTM_GETLINK;
77   req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
78   req.nlh.nlmsg_pid = 0;
79   req.nlh.nlmsg_seq = time (NULL);
80   req.g.rtgen_family = AF_UNSPEC;
81
82   assert (sizeof (req) - offsetof (struct req, pad) == 3);
83   memset (req.pad, '\0', sizeof (req.pad));
84
85   memset (&nladdr, '\0', sizeof (nladdr));
86   nladdr.nl_family = AF_NETLINK;
87
88 #ifdef PAGE_SIZE
89   /* Help the compiler optimize out the malloc call if PAGE_SIZE
90      is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
91   const size_t buf_size = PAGE_SIZE;
92 #else
93   const size_t buf_size = __getpagesize ();
94 #endif
95   bool use_malloc = false;
96   char *buf;
97
98   if (__libc_use_alloca (buf_size))
99     buf = alloca (buf_size);
100   else
101     {
102       buf = malloc (buf_size);
103       if (buf != NULL)
104         use_malloc = true;
105       else
106         goto out_fail;
107     }
108
109   struct iovec iov = { buf, buf_size };
110
111   if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
112                                     (struct sockaddr *) &nladdr,
113                                     sizeof (nladdr))) < 0)
114     goto out_fail;
115
116   bool done = false;
117   do
118     {
119       struct msghdr msg =
120         {
121           (void *) &nladdr, sizeof (nladdr),
122           &iov, 1,
123           NULL, 0,
124           0
125         };
126
127       ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
128       if (read_len < 0)
129         goto out_fail;
130
131       if (msg.msg_flags & MSG_TRUNC)
132         goto out_fail;
133
134       struct nlmsghdr *nlmh;
135       for (nlmh = (struct nlmsghdr *) buf;
136            NLMSG_OK (nlmh, (size_t) read_len);
137            nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
138         {
139           if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != pid
140               || nlmh->nlmsg_seq != req.nlh.nlmsg_seq)
141             continue;
142
143           if (nlmh->nlmsg_type == RTM_NEWLINK)
144             {
145               struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlmh);
146               int native = (ifim->ifi_type != ARPHRD_TUNNEL6
147                             && ifim->ifi_type != ARPHRD_TUNNEL
148                             && ifim->ifi_type != ARPHRD_SIT);
149
150               if (a1_index == ifim->ifi_index)
151                 {
152                   *a1_native = native;
153                   a1_index = 0xffffffffu;
154                 }
155               if (a2_index == ifim->ifi_index)
156                 {
157                   *a2_native = native;
158                   a2_index = 0xffffffffu;
159                 }
160
161               if (a1_index == 0xffffffffu
162                   && a2_index == 0xffffffffu)
163                 goto out;
164             }
165           else if (nlmh->nlmsg_type == NLMSG_DONE)
166             /* We found the end, leave the loop.  */
167             done = true;
168         }
169     }
170   while (! done);
171
172  out:
173   close_not_cancel_no_status (fd);
174
175   return;
176
177 out_fail:
178   if (use_malloc)
179     free (buf);
180 }
181 #endif