1/* 2 * This file is free software: you may copy, redistribute and/or modify it 3 * under the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 2 of the License, or (at your 5 * option) any later version. 6 * 7 * This file is distributed in the hope that it will be useful, but 8 * WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 * General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * 15 * This file incorporates work covered by the following copyright and 16 * permission notice: 17 * 18 19Copyright 2007, 2008 by Gr��goire Henry, Julien Cristau and Juliusz Chroboczek 20Copyright 2011, 2012 by Matthieu Boutier and Juliusz Chroboczek 21 22Permission is hereby granted, free of charge, to any person obtaining a copy 23of this software and associated documentation files (the "Software"), to deal 24in the Software without restriction, including without limitation the rights 25to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26copies of the Software, and to permit persons to whom the Software is 27furnished to do so, subject to the following conditions: 28 29The above copyright notice and this permission notice shall be included in 30all copies or substantial portions of the Software. 31 32THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 38THE SOFTWARE. 39*/ 40 41#include <sys/time.h> 42#include <sys/param.h> 43#include <time.h> 44 45#include "babeld.h" 46 47 48#include <sys/types.h> 49#include <sys/socket.h> 50#include <netinet/in.h> 51#include <netdb.h> 52#include <arpa/inet.h> 53 54#include <zebra.h> 55#include "prefix.h" 56#include "zclient.h" 57#include "kernel.h" 58#include "privs.h" 59#include "command.h" 60#include "vty.h" 61#include "memory.h" 62#include "thread.h" 63 64#include "util.h" 65#include "babel_interface.h" 66#include "babel_zebra.h" 67 68 69static int 70kernel_route_v4(int add, const unsigned char *pref, unsigned short plen, 71 const unsigned char *gate, int ifindex, 72 unsigned int metric); 73static int 74kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, 75 const unsigned char *gate, int ifindex, 76 unsigned int metric); 77 78int 79kernel_interface_operational(struct interface *interface) 80{ 81 return if_is_operative(interface); 82} 83 84int 85kernel_interface_mtu(struct interface *interface) 86{ 87 return MIN(interface->mtu, interface->mtu6); 88} 89 90int 91kernel_interface_wireless(struct interface *interface) 92{ 93 return 0; 94} 95 96int 97kernel_route(int operation, const unsigned char *pref, unsigned short plen, 98 const unsigned char *gate, int ifindex, unsigned int metric, 99 const unsigned char *newgate, int newifindex, 100 unsigned int newmetric) 101{ 102 int rc; 103 int ipv4; 104 105 /* Check that the protocol family is consistent. */ 106 if(plen >= 96 && v4mapped(pref)) { 107 if(!v4mapped(gate)) { 108 errno = EINVAL; 109 return -1; 110 } 111 ipv4 = 1; 112 } else { 113 if(v4mapped(gate)) { 114 errno = EINVAL; 115 return -1; 116 } 117 ipv4 = 0; 118 } 119 120 switch (operation) { 121 case ROUTE_ADD: 122 return ipv4 ? 123 kernel_route_v4(1, pref, plen, gate, ifindex, metric): 124 kernel_route_v6(1, pref, plen, gate, ifindex, metric); 125 break; 126 case ROUTE_FLUSH: 127 return ipv4 ? 128 kernel_route_v4(0, pref, plen, gate, ifindex, metric): 129 kernel_route_v6(0, pref, plen, gate, ifindex, metric); 130 break; 131 case ROUTE_MODIFY: 132 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 && 133 newifindex == ifindex) 134 return 0; 135 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new."); 136 rc = ipv4 ? 137 kernel_route_v4(0, pref, plen, gate, ifindex, metric): 138 kernel_route_v6(0, pref, plen, gate, ifindex, metric); 139 140 if (rc < 0) 141 return -1; 142 143 rc = ipv4 ? 144 kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric): 145 kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric); 146 147 return rc; 148 break; 149 default: 150 zlog_err("this should never appens (false value - kernel_route)"); 151 assert(0); 152 exit(1); 153 break; 154 } 155} 156 157static int 158kernel_route_v4(int add, 159 const unsigned char *pref, unsigned short plen, 160 const unsigned char *gate, int ifindex, unsigned int metric) 161{ 162 struct zapi_ipv4 api; /* quagga's communication system */ 163 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */ 164 struct in_addr babel_prefix_addr; /* babeld's prefix addr */ 165 struct in_addr nexthop; /* next router to go */ 166 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */ 167 168 /* convert to be understandable by quagga */ 169 /* convert given addresses */ 170 uchar_to_inaddr(&babel_prefix_addr, pref); 171 uchar_to_inaddr(&nexthop, gate); 172 173 /* make prefix structure */ 174 memset (&quagga_prefix, 0, sizeof(quagga_prefix)); 175 quagga_prefix.family = AF_INET; 176 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr); 177 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */ 178 apply_mask_ipv4(&quagga_prefix); 179 180 api.type = ZEBRA_ROUTE_BABEL; 181 api.flags = 0; 182 api.message = 0; 183 api.safi = SAFI_UNICAST; 184 185 /* Unlike the native Linux and BSD interfaces, Quagga doesn't like 186 there to be both and IPv4 nexthop and an ifindex. Omit the 187 ifindex, and assume that the connected prefixes be set up 188 correctly. */ 189 190 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); 191 api.ifindex_num = 0; 192 if(metric >= KERNEL_INFINITY) { 193 api.flags = ZEBRA_FLAG_BLACKHOLE; 194 api.nexthop_num = 0; 195 } else { 196 api.nexthop_num = 1; 197 api.nexthop = &nexthop_pointer; 198 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); 199 api.metric = metric; 200 } 201 202 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", 203 add ? "adding" : "removing" ); 204 return zapi_ipv4_route (add ? ZEBRA_IPV4_ROUTE_ADD : 205 ZEBRA_IPV4_ROUTE_DELETE, 206 zclient, &quagga_prefix, &api); 207} 208 209static int 210kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, 211 const unsigned char *gate, int ifindex, unsigned int metric) 212{ 213 unsigned int tmp_ifindex = ifindex; /* (for typing) */ 214 struct zapi_ipv6 api; /* quagga's communication system */ 215 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */ 216 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */ 217 struct in6_addr nexthop; /* next router to go */ 218 struct in6_addr *nexthop_pointer = &nexthop; 219 220 /* convert to be understandable by quagga */ 221 /* convert given addresses */ 222 uchar_to_in6addr(&babel_prefix_addr, pref); 223 uchar_to_in6addr(&nexthop, gate); 224 225 /* make prefix structure */ 226 memset (&quagga_prefix, 0, sizeof(quagga_prefix)); 227 quagga_prefix.family = AF_INET6; 228 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr); 229 quagga_prefix.prefixlen = plen; 230 apply_mask_ipv6(&quagga_prefix); 231 232 api.type = ZEBRA_ROUTE_BABEL; 233 api.flags = 0; 234 api.message = 0; 235 api.safi = SAFI_UNICAST; 236 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); 237 if(metric >= KERNEL_INFINITY) { 238 api.flags = ZEBRA_FLAG_BLACKHOLE; 239 api.nexthop_num = 0; 240 api.ifindex_num = 0; 241 } else { 242 api.nexthop_num = 1; 243 api.nexthop = &nexthop_pointer; 244 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); 245 api.ifindex_num = 1; 246 api.ifindex = &tmp_ifindex; 247 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); 248 api.metric = metric; 249 } 250 251 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra", 252 add ? "adding" : "removing" ); 253 return zapi_ipv6_route (add ? ZEBRA_IPV6_ROUTE_ADD : 254 ZEBRA_IPV6_ROUTE_DELETE, 255 zclient, &quagga_prefix, &api); 256} 257 258int 259if_eui64(char *ifname, int ifindex, unsigned char *eui) 260{ 261 struct interface *ifp = if_lookup_by_index(ifindex); 262 if (ifp == NULL) { 263 return -1; 264 } 265#ifdef HAVE_STRUCT_SOCKADDR_DL 266 u_char len = ifp->sdl.sdl_alen; 267 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen; 268#else 269 u_char len = (u_char) ifp->hw_addr_len; 270 char *tmp = (void*) ifp->hw_addr; 271#endif 272 if (len == 8) { 273 memcpy(eui, tmp, 8); 274 eui[0] ^= 2; 275 } else if (len == 6) { 276 memcpy(eui, tmp, 3); 277 eui[3] = 0xFF; 278 eui[4] = 0xFE; 279 memcpy(eui+5, tmp+3, 3); 280 } else { 281 return -1; 282 } 283 return 0; 284} 285 286/* Like gettimeofday, but returns monotonic time. If POSIX clocks are not 287 available, falls back to gettimeofday but enforces monotonicity. */ 288int 289gettime(struct timeval *tv) 290{ 291 return quagga_gettime(QUAGGA_CLK_MONOTONIC, tv); 292} 293 294/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the 295 caller will deal with gracefully. */ 296 297int 298read_random_bytes(void *buf, size_t len) 299{ 300 int fd; 301 int rc; 302 303 fd = open("/dev/urandom", O_RDONLY); 304 if(fd < 0) { 305 rc = -1; 306 } else { 307 rc = read(fd, buf, len); 308 if(rc < 0 || (unsigned) rc < len) 309 rc = -1; 310 close(fd); 311 } 312 return rc; 313} 314 315