1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> 4 * All rights reserved 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <asm/types.h> /* Needed for 2.4 kernels */ 29 30#include <sys/types.h> 31#include <sys/socket.h> 32#include <sys/ioctl.h> 33#include <sys/param.h> 34 35#include <linux/netlink.h> 36#include <linux/rtnetlink.h> 37 38/* Support older kernels */ 39#ifndef IFLA_WIRELESS 40# define IFLA_WIRELESS (IFLA_MASTER + 1) 41#endif 42 43#include <errno.h> 44#include <ctype.h> 45#include <stddef.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <unistd.h> 50 51#include "config.h" 52#include "common.h" 53#include "configure.h" 54#include "dhcp.h" 55#include "net.h" 56 57static int sock_fd; 58static struct sockaddr_nl sock_nl; 59 60int 61if_init(struct interface *iface) 62{ 63 char path[PATH_MAX]; 64 FILE *fp; 65 int n; 66 67 /* We enable promote_secondaries so that we can do this 68 * add 192.168.1.2/24 69 * add 192.168.1.3/24 70 * del 192.168.1.2/24 71 * and the subnet mask moves onto 192.168.1.3/24 72 * This matches the behaviour of BSD which makes coding dhcpcd 73 * a little easier as there's just one behaviour. */ 74 snprintf(path, sizeof(path), 75 "/proc/sys/net/ipv4/conf/%s/promote_secondaries", 76 iface->name); 77 78 fp = fopen(path, "w"); 79 if (fp == NULL) 80 return errno == ENOENT ? 0 : -1; 81 n = fprintf(fp, "1"); 82 fclose(fp); 83 return n == -1 ? -1 : 0; 84} 85 86int 87if_conf(struct interface *iface) 88{ 89 char path[PATH_MAX], buf[1]; 90 FILE *fp; 91 92 /* Some qeth setups require the use of the broadcast flag. */ 93 snprintf(path, sizeof(path), 94 "/sys/class/net/%s/device/layer2", 95 iface->name); 96 97 fp = fopen(path, "r"); 98 if (fp == NULL) 99 return errno == ENOENT ? 0 : -1; 100 if (fgets(buf, sizeof(buf), fp) != NULL && buf[0] == '0') 101 iface->state->options->options |= DHCPCD_BROADCAST; 102 fclose(fp); 103 return 0; 104} 105 106static int 107_open_link_socket(struct sockaddr_nl *nl) 108{ 109 int fd; 110 111 if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) 112 return -1; 113 nl->nl_family = AF_NETLINK; 114 if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) 115 return -1; 116 set_cloexec(fd); 117 return fd; 118} 119 120int 121init_sockets(void) 122{ 123 if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 124 return -1; 125 set_cloexec(socket_afnet); 126 sock_fd = _open_link_socket(&sock_nl); 127 set_cloexec(sock_fd); 128 return sock_fd; 129} 130 131int 132open_link_socket(void) 133{ 134 struct sockaddr_nl snl; 135 136 memset(&snl, 0, sizeof(snl)); 137 snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; 138 return _open_link_socket(&snl); 139} 140 141static int 142get_netlink(int fd, int flags, 143 int (*callback)(struct nlmsghdr *)) 144{ 145 char *buf = NULL, *nbuf; 146 ssize_t buflen = 0, bytes; 147 struct nlmsghdr *nlm; 148 int r = -1; 149 150 for (;;) { 151 bytes = recv(fd, NULL, 0, 152 flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); 153 if (bytes == -1) { 154 if (errno == EAGAIN) { 155 r = 0; 156 goto eexit; 157 } 158 if (errno == EINTR) 159 continue; 160 goto eexit; 161 } else if (bytes == buflen) { 162 /* Support kernels older than 2.6.22 */ 163 if (bytes == 0) 164 bytes = 512; 165 else 166 bytes *= 2; 167 } 168 if (buflen < bytes) { 169 /* Alloc 1 more so we work with older kernels */ 170 buflen = bytes + 1; 171 nbuf = realloc(buf, buflen); 172 if (nbuf == NULL) 173 goto eexit; 174 buf = nbuf; 175 } 176 bytes = recv(fd, buf, buflen, flags); 177 if (bytes == -1) { 178 if (errno == EAGAIN) { 179 r = 0; 180 goto eexit; 181 } 182 if (errno == EINTR) 183 continue; 184 goto eexit; 185 } 186 for (nlm = (struct nlmsghdr *)buf; 187 NLMSG_OK(nlm, (size_t)bytes); 188 nlm = NLMSG_NEXT(nlm, bytes)) 189 { 190 r = callback(nlm); 191 if (r != 0) 192 goto eexit; 193 } 194 } 195 196eexit: 197 free(buf); 198 return r; 199} 200 201static int 202err_netlink(struct nlmsghdr *nlm) 203{ 204 struct nlmsgerr *err; 205 int l; 206 207 if (nlm->nlmsg_type != NLMSG_ERROR) 208 return 0; 209 l = nlm->nlmsg_len - sizeof(*nlm); 210 if ((size_t)l < sizeof(*err)) { 211 errno = EBADMSG; 212 return -1; 213 } 214 err = (struct nlmsgerr *)NLMSG_DATA(nlm); 215 if (err->error == 0) 216 return l; 217 errno = -err->error; 218 return -1; 219} 220 221static int 222link_route(struct nlmsghdr *nlm) 223{ 224 int len, idx, metric; 225 struct rtattr *rta; 226 struct rtmsg *rtm; 227 struct rt rt; 228 char ifn[IF_NAMESIZE + 1]; 229 230 if (nlm->nlmsg_type != RTM_DELROUTE) 231 return 0; 232 233 len = nlm->nlmsg_len - sizeof(*nlm); 234 if ((size_t)len < sizeof(*rtm)) { 235 errno = EBADMSG; 236 return -1; 237 } 238 rtm = NLMSG_DATA(nlm); 239 if (rtm->rtm_type != RTN_UNICAST || 240 rtm->rtm_table != RT_TABLE_MAIN || 241 rtm->rtm_family != AF_INET || 242 nlm->nlmsg_pid == (uint32_t)getpid()) 243 return 1; 244 rta = (struct rtattr *) ((char *)rtm + NLMSG_ALIGN(sizeof(*rtm))); 245 len = NLMSG_PAYLOAD(nlm, sizeof(*rtm)); 246 rt.iface = NULL; 247 rt.dest.s_addr = INADDR_ANY; 248 rt.net.s_addr = INADDR_ANY; 249 rt.gate.s_addr = INADDR_ANY; 250 rt.next = NULL; 251 metric = 0; 252 while (RTA_OK(rta, len)) { 253 switch (rta->rta_type) { 254 case RTA_DST: 255 memcpy(&rt.dest.s_addr, RTA_DATA(rta), 256 sizeof(rt.dest.s_addr)); 257 break; 258 case RTA_GATEWAY: 259 memcpy(&rt.gate.s_addr, RTA_DATA(rta), 260 sizeof(rt.gate.s_addr)); 261 break; 262 case RTA_OIF: 263 idx = *(int *)RTA_DATA(rta); 264 if (if_indextoname(idx, ifn)) 265 rt.iface = find_interface(ifn); 266 break; 267 case RTA_PRIORITY: 268 metric = *(int *)RTA_DATA(rta); 269 break; 270 } 271 rta = RTA_NEXT(rta, len); 272 } 273 if (rt.iface != NULL) { 274 if (metric == rt.iface->metric) { 275 inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net); 276 route_deleted(&rt); 277 } 278 } 279 return 1; 280} 281 282static int 283link_addr(struct nlmsghdr *nlm) 284{ 285 int len; 286 struct rtattr *rta; 287 struct ifaddrmsg *ifa; 288 struct in_addr addr, net, dest; 289 char ifn[IF_NAMESIZE + 1]; 290 struct interface *iface; 291 292 if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR) 293 return 0; 294 295 len = nlm->nlmsg_len - sizeof(*nlm); 296 if ((size_t)len < sizeof(*ifa)) { 297 errno = EBADMSG; 298 return -1; 299 } 300 if (nlm->nlmsg_pid == (uint32_t)getpid()) 301 return 1; 302 ifa = NLMSG_DATA(nlm); 303 if (if_indextoname(ifa->ifa_index, ifn) == NULL) 304 return -1; 305 iface = find_interface(ifn); 306 if (iface == NULL) 307 return 1; 308 rta = (struct rtattr *) IFA_RTA(ifa); 309 len = NLMSG_PAYLOAD(nlm, sizeof(*ifa)); 310 addr.s_addr = dest.s_addr = INADDR_ANY; 311 dest.s_addr = INADDR_ANY; 312 inet_cidrtoaddr(ifa->ifa_prefixlen, &net); 313 while (RTA_OK(rta, len)) { 314 switch (rta->rta_type) { 315 case IFA_ADDRESS: 316 if (iface->flags & IFF_POINTOPOINT) { 317 memcpy(&dest.s_addr, RTA_DATA(rta), 318 sizeof(addr.s_addr)); 319 } 320 break; 321 case IFA_LOCAL: 322 memcpy(&addr.s_addr, RTA_DATA(rta), 323 sizeof(addr.s_addr)); 324 break; 325 } 326 rta = RTA_NEXT(rta, len); 327 } 328 handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest); 329 return 1; 330} 331 332static int 333link_netlink(struct nlmsghdr *nlm) 334{ 335 int len; 336 struct rtattr *rta; 337 struct ifinfomsg *ifi; 338 char ifn[IF_NAMESIZE + 1]; 339 340 len = link_route(nlm); 341 if (len != 0) 342 return len; 343 len = link_addr(nlm); 344 if (len != 0) 345 return len; 346 347 if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) 348 return 0; 349 len = nlm->nlmsg_len - sizeof(*nlm); 350 if ((size_t)len < sizeof(*ifi)) { 351 errno = EBADMSG; 352 return -1; 353 } 354 ifi = NLMSG_DATA(nlm); 355 if (ifi->ifi_flags & IFF_LOOPBACK) 356 return 1; 357 rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); 358 len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 359 *ifn = '\0'; 360 while (RTA_OK(rta, len)) { 361 switch (rta->rta_type) { 362 case IFLA_WIRELESS: 363 /* Ignore wireless messages */ 364 if (nlm->nlmsg_type == RTM_NEWLINK && 365 ifi->ifi_change == 0) 366 return 1; 367 break; 368 case IFLA_IFNAME: 369 strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); 370 break; 371 } 372 rta = RTA_NEXT(rta, len); 373 } 374 if (nlm->nlmsg_type == RTM_NEWLINK) 375 len = ifi->ifi_change == ~0U ? 1 : 0; 376 else 377 len = -1; 378 handle_interface(len, ifn); 379 return 1; 380} 381 382int 383manage_link(int fd) 384{ 385 return get_netlink(fd, MSG_DONTWAIT, &link_netlink); 386} 387 388static int 389send_netlink(struct nlmsghdr *hdr) 390{ 391 int r; 392 struct iovec iov; 393 struct msghdr msg; 394 static unsigned int seq; 395 396 memset(&iov, 0, sizeof(iov)); 397 iov.iov_base = hdr; 398 iov.iov_len = hdr->nlmsg_len; 399 memset(&msg, 0, sizeof(msg)); 400 msg.msg_name = &sock_nl; 401 msg.msg_namelen = sizeof(sock_nl); 402 msg.msg_iov = &iov; 403 msg.msg_iovlen = 1; 404 /* Request a reply */ 405 hdr->nlmsg_flags |= NLM_F_ACK; 406 hdr->nlmsg_seq = ++seq; 407 408 if (sendmsg(sock_fd, &msg, 0) != -1) 409 r = get_netlink(sock_fd, 0, &err_netlink); 410 else 411 r = -1; 412 return r; 413} 414 415#define NLMSG_TAIL(nmsg) \ 416 ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) 417 418static int 419add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, 420 const void *data, int alen) 421{ 422 int len = RTA_LENGTH(alen); 423 struct rtattr *rta; 424 425 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 426 errno = ENOBUFS; 427 return -1; 428 } 429 430 rta = NLMSG_TAIL(n); 431 rta->rta_type = type; 432 rta->rta_len = len; 433 memcpy(RTA_DATA(rta), data, alen); 434 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 435 436 return 0; 437} 438 439static int 440add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data) 441{ 442 int len = RTA_LENGTH(sizeof(data)); 443 struct rtattr *rta; 444 445 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 446 errno = ENOBUFS; 447 return -1; 448 } 449 450 rta = NLMSG_TAIL(n); 451 rta->rta_type = type; 452 rta->rta_len = len; 453 memcpy(RTA_DATA(rta), &data, sizeof(data)); 454 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 455 456 return 0; 457} 458 459struct nlma 460{ 461 struct nlmsghdr hdr; 462 struct ifaddrmsg ifa; 463 char buffer[64]; 464}; 465 466struct nlmr 467{ 468 struct nlmsghdr hdr; 469 struct rtmsg rt; 470 char buffer[256]; 471}; 472 473int 474if_address(const struct interface *iface, 475 const struct in_addr *address, const struct in_addr *netmask, 476 const struct in_addr *broadcast, int action) 477{ 478 struct nlma *nlm; 479 int retval = 0; 480 481 nlm = xzalloc(sizeof(*nlm)); 482 nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 483 nlm->hdr.nlmsg_flags = NLM_F_REQUEST; 484 if (action >= 0) { 485 nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 486 nlm->hdr.nlmsg_type = RTM_NEWADDR; 487 } else 488 nlm->hdr.nlmsg_type = RTM_DELADDR; 489 if (!(nlm->ifa.ifa_index = if_nametoindex(iface->name))) { 490 free(nlm); 491 errno = ENODEV; 492 return -1; 493 } 494 nlm->ifa.ifa_family = AF_INET; 495 nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); 496 /* This creates the aliased interface */ 497 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, 498 iface->name, strlen(iface->name) + 1); 499 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, 500 &address->s_addr, sizeof(address->s_addr)); 501 if (action >= 0 && broadcast) 502 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, 503 &broadcast->s_addr, sizeof(broadcast->s_addr)); 504 505 if (send_netlink(&nlm->hdr) == -1) 506 retval = -1; 507 free(nlm); 508 return retval; 509} 510 511int 512if_route(const struct interface *iface, 513 const struct in_addr *destination, const struct in_addr *netmask, 514 const struct in_addr *gateway, int metric, int action) 515{ 516 struct nlmr *nlm; 517 unsigned int ifindex; 518 int retval = 0; 519 520 if (!(ifindex = if_nametoindex(iface->name))) { 521 errno = ENODEV; 522 return -1; 523 } 524 525 nlm = xzalloc(sizeof(*nlm)); 526 nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 527 nlm->hdr.nlmsg_type = RTM_NEWROUTE; 528 if (action == 0) 529 nlm->hdr.nlmsg_flags = NLM_F_REPLACE; 530 else if (action == 1) 531 nlm->hdr.nlmsg_flags = NLM_F_CREATE /*| NLM_F_EXCL*/; 532 else 533 nlm->hdr.nlmsg_type = RTM_DELROUTE; 534 nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; 535 nlm->rt.rtm_family = AF_INET; 536 nlm->rt.rtm_table = RT_TABLE_MAIN; 537 538 if (action == -1 || action == -2) 539 nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; 540 else { 541 nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; 542 /* We only change route metrics for kernel routes */ 543 if (destination->s_addr == 544 (iface->addr.s_addr & iface->net.s_addr) && 545 netmask->s_addr == iface->net.s_addr) 546 nlm->rt.rtm_protocol = RTPROT_KERNEL; 547 else 548 nlm->rt.rtm_protocol = RTPROT_BOOT; 549 if (gateway->s_addr == INADDR_ANY || 550 (gateway->s_addr == destination->s_addr && 551 netmask->s_addr == INADDR_BROADCAST)) 552 nlm->rt.rtm_scope = RT_SCOPE_LINK; 553 else 554 nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; 555 nlm->rt.rtm_type = RTN_UNICAST; 556 } 557 558 nlm->rt.rtm_dst_len = inet_ntocidr(*netmask); 559 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, 560 &destination->s_addr, sizeof(destination->s_addr)); 561 if (nlm->rt.rtm_protocol == RTPROT_KERNEL) { 562 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC, 563 &iface->addr.s_addr, sizeof(iface->addr.s_addr)); 564 } 565 /* If destination == gateway then don't add the gateway */ 566 if (destination->s_addr != gateway->s_addr || 567 netmask->s_addr != INADDR_BROADCAST) 568 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, 569 &gateway->s_addr, sizeof(gateway->s_addr)); 570 571 add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); 572 add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, metric); 573 574 if (send_netlink(&nlm->hdr) == -1) 575 retval = -1; 576 free(nlm); 577 return retval; 578} 579