1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2011 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 57 /* ANDROID change, moved this below all includes. */ 58 /* For some reason, glibc doesn't include newer flags from linux/if.h 59 * However, we cannot include linux/if.h directly as it conflicts 60 * with the glibc version. D'oh! */ 61 #ifndef IFF_LOWER_UP 62 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ 63 #endif 64 /* End of ANDROID change */ 65 66 static int sock_fd; 67 static struct sockaddr_nl sock_nl; 68 69 int if_init(struct interface * iface)70 if_init(struct interface *iface) 71 { 72 char path[PATH_MAX]; 73 FILE *fp; 74 int n; 75 76 /* We enable promote_secondaries so that we can do this 77 * add 192.168.1.2/24 78 * add 192.168.1.3/24 79 * del 192.168.1.2/24 80 * and the subnet mask moves onto 192.168.1.3/24 81 * This matches the behaviour of BSD which makes coding dhcpcd 82 * a little easier as there's just one behaviour. */ 83 snprintf(path, sizeof(path), 84 "/proc/sys/net/ipv4/conf/%s/promote_secondaries", 85 iface->name); 86 87 fp = fopen(path, "w"); 88 if (fp == NULL) 89 return errno == ENOENT ? 0 : -1; 90 n = fprintf(fp, "1"); 91 fclose(fp); 92 return n == -1 ? -1 : 0; 93 } 94 95 int if_conf(struct interface * iface)96 if_conf(struct interface *iface) 97 { 98 char path[PATH_MAX], buf[1]; 99 FILE *fp; 100 101 /* Some qeth setups require the use of the broadcast flag. */ 102 snprintf(path, sizeof(path), 103 "/sys/class/net/%s/device/layer2", 104 iface->name); 105 106 fp = fopen(path, "r"); 107 if (fp == NULL) 108 return errno == ENOENT ? 0 : -1; 109 if (fgets(buf, sizeof(buf), fp) != NULL && buf[0] == '0') 110 iface->state->options->options |= DHCPCD_BROADCAST; 111 fclose(fp); 112 return 0; 113 } 114 115 static int _open_link_socket(struct sockaddr_nl * nl)116 _open_link_socket(struct sockaddr_nl *nl) 117 { 118 int fd; 119 120 if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) 121 return -1; 122 nl->nl_family = AF_NETLINK; 123 if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) 124 return -1; 125 set_cloexec(fd); 126 return fd; 127 } 128 129 int init_sockets(void)130 init_sockets(void) 131 { 132 if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 133 return -1; 134 set_cloexec(socket_afnet); 135 sock_fd = _open_link_socket(&sock_nl); 136 set_cloexec(sock_fd); 137 return sock_fd; 138 } 139 140 int open_link_socket(void)141 open_link_socket(void) 142 { 143 struct sockaddr_nl snl; 144 145 memset(&snl, 0, sizeof(snl)); 146 snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; 147 return _open_link_socket(&snl); 148 } 149 150 static int get_netlink(int fd,int flags,int (* callback)(struct nlmsghdr *))151 get_netlink(int fd, int flags, 152 int (*callback)(struct nlmsghdr *)) 153 { 154 char *buf = NULL, *nbuf; 155 ssize_t buflen = 0, bytes; 156 struct nlmsghdr *nlm; 157 int r = -1; 158 159 for (;;) { 160 bytes = recv(fd, NULL, 0, 161 flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); 162 if (bytes == -1) { 163 if (errno == EAGAIN) { 164 r = 0; 165 goto eexit; 166 } 167 if (errno == EINTR) 168 continue; 169 goto eexit; 170 } else if (bytes == buflen) { 171 /* Support kernels older than 2.6.22 */ 172 if (bytes == 0) 173 bytes = 512; 174 else 175 bytes *= 2; 176 } 177 if (buflen < bytes) { 178 /* Alloc 1 more so we work with older kernels */ 179 buflen = bytes + 1; 180 nbuf = realloc(buf, buflen); 181 if (nbuf == NULL) 182 goto eexit; 183 buf = nbuf; 184 } 185 bytes = recv(fd, buf, buflen, flags); 186 if (bytes == -1) { 187 if (errno == EAGAIN) { 188 r = 0; 189 goto eexit; 190 } 191 if (errno == EINTR) 192 continue; 193 goto eexit; 194 } 195 for (nlm = (struct nlmsghdr *)buf; 196 NLMSG_OK(nlm, (size_t)bytes); 197 nlm = NLMSG_NEXT(nlm, bytes)) 198 { 199 r = callback(nlm); 200 if (r != 0) 201 goto eexit; 202 } 203 } 204 205 eexit: 206 free(buf); 207 return r; 208 } 209 210 static int err_netlink(struct nlmsghdr * nlm)211 err_netlink(struct nlmsghdr *nlm) 212 { 213 struct nlmsgerr *err; 214 int l; 215 216 if (nlm->nlmsg_type != NLMSG_ERROR) 217 return 0; 218 l = nlm->nlmsg_len - sizeof(*nlm); 219 if ((size_t)l < sizeof(*err)) { 220 errno = EBADMSG; 221 return -1; 222 } 223 err = (struct nlmsgerr *)NLMSG_DATA(nlm); 224 if (err->error == 0) 225 return l; 226 errno = -err->error; 227 return -1; 228 } 229 230 static int link_route(struct nlmsghdr * nlm)231 link_route(struct nlmsghdr *nlm) 232 { 233 int len, idx, metric; 234 struct rtattr *rta; 235 struct rtmsg *rtm; 236 struct rt rt; 237 char ifn[IF_NAMESIZE + 1]; 238 239 if (nlm->nlmsg_type != RTM_DELROUTE) 240 return 0; 241 242 len = nlm->nlmsg_len - sizeof(*nlm); 243 if ((size_t)len < sizeof(*rtm)) { 244 errno = EBADMSG; 245 return -1; 246 } 247 rtm = NLMSG_DATA(nlm); 248 if (rtm->rtm_type != RTN_UNICAST || 249 rtm->rtm_table != RT_TABLE_MAIN || 250 rtm->rtm_family != AF_INET || 251 nlm->nlmsg_pid == (uint32_t)getpid()) 252 return 1; 253 rta = (struct rtattr *) ((char *)rtm + NLMSG_ALIGN(sizeof(*rtm))); 254 len = NLMSG_PAYLOAD(nlm, sizeof(*rtm)); 255 rt.iface = NULL; 256 rt.dest.s_addr = INADDR_ANY; 257 rt.net.s_addr = INADDR_ANY; 258 rt.gate.s_addr = INADDR_ANY; 259 rt.next = NULL; 260 metric = 0; 261 while (RTA_OK(rta, len)) { 262 switch (rta->rta_type) { 263 case RTA_DST: 264 memcpy(&rt.dest.s_addr, RTA_DATA(rta), 265 sizeof(rt.dest.s_addr)); 266 break; 267 case RTA_GATEWAY: 268 memcpy(&rt.gate.s_addr, RTA_DATA(rta), 269 sizeof(rt.gate.s_addr)); 270 break; 271 case RTA_OIF: 272 idx = *(int *)RTA_DATA(rta); 273 if (if_indextoname(idx, ifn)) 274 rt.iface = find_interface(ifn); 275 break; 276 case RTA_PRIORITY: 277 metric = *(int *)RTA_DATA(rta); 278 break; 279 } 280 rta = RTA_NEXT(rta, len); 281 } 282 if (rt.iface != NULL) { 283 if (metric == rt.iface->metric) { 284 inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net); 285 route_deleted(&rt); 286 } 287 } 288 return 1; 289 } 290 291 static int link_addr(struct nlmsghdr * nlm)292 link_addr(struct nlmsghdr *nlm) 293 { 294 int len; 295 struct rtattr *rta; 296 struct ifaddrmsg *ifa; 297 struct in_addr addr, net, dest; 298 char ifn[IF_NAMESIZE + 1]; 299 struct interface *iface; 300 301 if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR) 302 return 0; 303 304 len = nlm->nlmsg_len - sizeof(*nlm); 305 if ((size_t)len < sizeof(*ifa)) { 306 errno = EBADMSG; 307 return -1; 308 } 309 if (nlm->nlmsg_pid == (uint32_t)getpid()) 310 return 1; 311 ifa = NLMSG_DATA(nlm); 312 if (if_indextoname(ifa->ifa_index, ifn) == NULL) 313 return -1; 314 iface = find_interface(ifn); 315 if (iface == NULL) 316 return 1; 317 rta = (struct rtattr *) IFA_RTA(ifa); 318 len = NLMSG_PAYLOAD(nlm, sizeof(*ifa)); 319 addr.s_addr = dest.s_addr = INADDR_ANY; 320 dest.s_addr = INADDR_ANY; 321 inet_cidrtoaddr(ifa->ifa_prefixlen, &net); 322 while (RTA_OK(rta, len)) { 323 switch (rta->rta_type) { 324 case IFA_ADDRESS: 325 if (iface->flags & IFF_POINTOPOINT) { 326 memcpy(&dest.s_addr, RTA_DATA(rta), 327 sizeof(addr.s_addr)); 328 } 329 break; 330 case IFA_LOCAL: 331 memcpy(&addr.s_addr, RTA_DATA(rta), 332 sizeof(addr.s_addr)); 333 break; 334 } 335 rta = RTA_NEXT(rta, len); 336 } 337 handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest); 338 return 1; 339 } 340 341 static int link_netlink(struct nlmsghdr * nlm)342 link_netlink(struct nlmsghdr *nlm) 343 { 344 int len; 345 struct rtattr *rta; 346 struct ifinfomsg *ifi; 347 char ifn[IF_NAMESIZE + 1]; 348 349 len = link_route(nlm); 350 if (len != 0) 351 return len; 352 len = link_addr(nlm); 353 if (len != 0) 354 return len; 355 356 if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) 357 return 0; 358 len = nlm->nlmsg_len - sizeof(*nlm); 359 if ((size_t)len < sizeof(*ifi)) { 360 errno = EBADMSG; 361 return -1; 362 } 363 ifi = NLMSG_DATA(nlm); 364 if (ifi->ifi_flags & IFF_LOOPBACK) 365 return 1; 366 rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); 367 len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 368 *ifn = '\0'; 369 while (RTA_OK(rta, len)) { 370 switch (rta->rta_type) { 371 case IFLA_WIRELESS: 372 /* Ignore wireless messages */ 373 if (nlm->nlmsg_type == RTM_NEWLINK && 374 ifi->ifi_change == 0) 375 return 1; 376 break; 377 case IFLA_IFNAME: 378 strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); 379 break; 380 } 381 rta = RTA_NEXT(rta, len); 382 } 383 384 if (nlm->nlmsg_type == RTM_DELLINK) { 385 handle_interface(-1, ifn); 386 return 1; 387 } 388 389 /* Bridge interfaces set IFF_LOWER_UP when they have a valid 390 * hardware address. To trigger a valid hardware address pickup 391 * we need to pretend that that don't exist until they have 392 * IFF_LOWER_UP set. */ 393 if (ifi->ifi_flags & IFF_MASTER && !(ifi->ifi_flags & IFF_LOWER_UP)) { 394 handle_interface(-1, ifn); 395 return 1; 396 } 397 398 handle_carrier(ifi->ifi_flags & IFF_RUNNING ? 1 : -1, 399 ifi->ifi_flags, ifn); 400 return 1; 401 } 402 403 int manage_link(int fd)404 manage_link(int fd) 405 { 406 return get_netlink(fd, MSG_DONTWAIT, &link_netlink); 407 } 408 409 static int send_netlink(struct nlmsghdr * hdr)410 send_netlink(struct nlmsghdr *hdr) 411 { 412 int r; 413 struct iovec iov; 414 struct msghdr msg; 415 static unsigned int seq; 416 417 memset(&iov, 0, sizeof(iov)); 418 iov.iov_base = hdr; 419 iov.iov_len = hdr->nlmsg_len; 420 memset(&msg, 0, sizeof(msg)); 421 msg.msg_name = &sock_nl; 422 msg.msg_namelen = sizeof(sock_nl); 423 msg.msg_iov = &iov; 424 msg.msg_iovlen = 1; 425 /* Request a reply */ 426 hdr->nlmsg_flags |= NLM_F_ACK; 427 hdr->nlmsg_seq = ++seq; 428 429 if (sendmsg(sock_fd, &msg, 0) != -1) 430 r = get_netlink(sock_fd, 0, &err_netlink); 431 else 432 r = -1; 433 return r; 434 } 435 436 #define NLMSG_TAIL(nmsg) \ 437 ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) 438 439 static int add_attr_l(struct nlmsghdr * n,unsigned int maxlen,int type,const void * data,int alen)440 add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, 441 const void *data, int alen) 442 { 443 int len = RTA_LENGTH(alen); 444 struct rtattr *rta; 445 446 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 447 errno = ENOBUFS; 448 return -1; 449 } 450 451 rta = NLMSG_TAIL(n); 452 rta->rta_type = type; 453 rta->rta_len = len; 454 memcpy(RTA_DATA(rta), data, alen); 455 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 456 457 return 0; 458 } 459 460 static int add_attr_32(struct nlmsghdr * n,unsigned int maxlen,int type,uint32_t data)461 add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data) 462 { 463 int len = RTA_LENGTH(sizeof(data)); 464 struct rtattr *rta; 465 466 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 467 errno = ENOBUFS; 468 return -1; 469 } 470 471 rta = NLMSG_TAIL(n); 472 rta->rta_type = type; 473 rta->rta_len = len; 474 memcpy(RTA_DATA(rta), &data, sizeof(data)); 475 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 476 477 return 0; 478 } 479 480 struct nlma 481 { 482 struct nlmsghdr hdr; 483 struct ifaddrmsg ifa; 484 char buffer[64]; 485 }; 486 487 struct nlmr 488 { 489 struct nlmsghdr hdr; 490 struct rtmsg rt; 491 char buffer[256]; 492 }; 493 494 int if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)495 if_address(const struct interface *iface, 496 const struct in_addr *address, const struct in_addr *netmask, 497 const struct in_addr *broadcast, int action) 498 { 499 struct nlma *nlm; 500 int retval = 0; 501 502 nlm = xzalloc(sizeof(*nlm)); 503 nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 504 nlm->hdr.nlmsg_flags = NLM_F_REQUEST; 505 if (action >= 0) { 506 nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 507 nlm->hdr.nlmsg_type = RTM_NEWADDR; 508 } else 509 nlm->hdr.nlmsg_type = RTM_DELADDR; 510 if (!(nlm->ifa.ifa_index = if_nametoindex(iface->name))) { 511 free(nlm); 512 errno = ENODEV; 513 return -1; 514 } 515 nlm->ifa.ifa_family = AF_INET; 516 nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); 517 /* This creates the aliased interface */ 518 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, 519 iface->name, strlen(iface->name) + 1); 520 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, 521 &address->s_addr, sizeof(address->s_addr)); 522 if (action >= 0 && broadcast) 523 add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, 524 &broadcast->s_addr, sizeof(broadcast->s_addr)); 525 526 if (send_netlink(&nlm->hdr) == -1) 527 retval = -1; 528 free(nlm); 529 return retval; 530 } 531 532 int if_route(const struct rt * rt,int action)533 if_route(const struct rt *rt, int action) 534 { 535 struct nlmr *nlm; 536 unsigned int ifindex; 537 int retval = 0; 538 539 if (!(ifindex = if_nametoindex(rt->iface->name))) { 540 errno = ENODEV; 541 return -1; 542 } 543 544 nlm = xzalloc(sizeof(*nlm)); 545 nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 546 nlm->hdr.nlmsg_type = RTM_NEWROUTE; 547 if (action == 0) 548 nlm->hdr.nlmsg_flags = NLM_F_REPLACE; 549 else if (action == 1) 550 nlm->hdr.nlmsg_flags = NLM_F_CREATE /*| NLM_F_EXCL*/; 551 else 552 nlm->hdr.nlmsg_type = RTM_DELROUTE; 553 nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; 554 nlm->rt.rtm_family = AF_INET; 555 nlm->rt.rtm_table = RT_TABLE_MAIN; 556 557 if (action == -1 || action == -2) 558 nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; 559 else { 560 nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; 561 /* We only change route metrics for kernel routes */ 562 if (rt->dest.s_addr == 563 (rt->iface->addr.s_addr & rt->iface->net.s_addr) && 564 rt->net.s_addr == rt->iface->net.s_addr) 565 nlm->rt.rtm_protocol = RTPROT_KERNEL; 566 else 567 nlm->rt.rtm_protocol = RTPROT_BOOT; 568 if (rt->gate.s_addr == INADDR_ANY || 569 (rt->gate.s_addr == rt->dest.s_addr && 570 rt->net.s_addr == INADDR_BROADCAST)) 571 nlm->rt.rtm_scope = RT_SCOPE_LINK; 572 else 573 nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; 574 nlm->rt.rtm_type = RTN_UNICAST; 575 } 576 577 nlm->rt.rtm_dst_len = inet_ntocidr(rt->net); 578 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, 579 &rt->dest.s_addr, sizeof(rt->dest.s_addr)); 580 if (nlm->rt.rtm_protocol == RTPROT_KERNEL) { 581 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC, 582 &rt->iface->addr.s_addr, sizeof(rt->iface->addr.s_addr)); 583 } 584 /* If destination == gateway then don't add the gateway */ 585 if (rt->dest.s_addr != rt->gate.s_addr || 586 rt->net.s_addr != INADDR_BROADCAST) 587 add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, 588 &rt->gate.s_addr, sizeof(rt->gate.s_addr)); 589 590 add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); 591 add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric); 592 593 if (send_netlink(&nlm->hdr) == -1) 594 retval = -1; 595 free(nlm); 596 return retval; 597 } 598