1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <stdlib.h> 17 #include <string.h> 18 19 #define LOG_TAG "NetlinkEvent" 20 #include <cutils/log.h> 21 22 #include <sysutils/NetlinkEvent.h> 23 24 #include <sys/types.h> 25 #include <sys/socket.h> 26 #include <netinet/in.h> 27 #include <netinet/icmp6.h> 28 #include <arpa/inet.h> 29 #include <net/if.h> 30 31 #include <linux/if.h> 32 #include <linux/if_addr.h> 33 #include <linux/if_link.h> 34 #include <linux/netfilter/nfnetlink.h> 35 #include <linux/netfilter_ipv4/ipt_ULOG.h> 36 /* From kernel's net/netfilter/xt_quota2.c */ 37 const int QLOG_NL_EVENT = 112; 38 39 #include <linux/netlink.h> 40 #include <linux/rtnetlink.h> 41 42 const int NetlinkEvent::NlActionUnknown = 0; 43 const int NetlinkEvent::NlActionAdd = 1; 44 const int NetlinkEvent::NlActionRemove = 2; 45 const int NetlinkEvent::NlActionChange = 3; 46 const int NetlinkEvent::NlActionLinkUp = 4; 47 const int NetlinkEvent::NlActionLinkDown = 5; 48 const int NetlinkEvent::NlActionAddressUpdated = 6; 49 const int NetlinkEvent::NlActionAddressRemoved = 7; 50 const int NetlinkEvent::NlActionRdnss = 8; 51 const int NetlinkEvent::NlActionRouteUpdated = 9; 52 const int NetlinkEvent::NlActionRouteRemoved = 10; 53 54 NetlinkEvent::NetlinkEvent() { 55 mAction = NlActionUnknown; 56 memset(mParams, 0, sizeof(mParams)); 57 mPath = NULL; 58 mSubsystem = NULL; 59 } 60 61 NetlinkEvent::~NetlinkEvent() { 62 int i; 63 if (mPath) 64 free(mPath); 65 if (mSubsystem) 66 free(mSubsystem); 67 for (i = 0; i < NL_PARAMS_MAX; i++) { 68 if (!mParams[i]) 69 break; 70 free(mParams[i]); 71 } 72 } 73 74 void NetlinkEvent::dump() { 75 int i; 76 77 for (i = 0; i < NL_PARAMS_MAX; i++) { 78 if (!mParams[i]) 79 break; 80 SLOGD("NL param '%s'\n", mParams[i]); 81 } 82 } 83 84 /* 85 * Returns the message name for a message in the NETLINK_ROUTE family, or NULL 86 * if parsing that message is not supported. 87 */ 88 static const char *rtMessageName(int type) { 89 #define NL_EVENT_RTM_NAME(rtm) case rtm: return #rtm; 90 switch (type) { 91 NL_EVENT_RTM_NAME(RTM_NEWLINK); 92 NL_EVENT_RTM_NAME(RTM_DELLINK); 93 NL_EVENT_RTM_NAME(RTM_NEWADDR); 94 NL_EVENT_RTM_NAME(RTM_DELADDR); 95 NL_EVENT_RTM_NAME(RTM_NEWROUTE); 96 NL_EVENT_RTM_NAME(RTM_DELROUTE); 97 NL_EVENT_RTM_NAME(RTM_NEWNDUSEROPT); 98 NL_EVENT_RTM_NAME(QLOG_NL_EVENT); 99 default: 100 return NULL; 101 } 102 #undef NL_EVENT_RTM_NAME 103 } 104 105 /* 106 * Checks that a binary NETLINK_ROUTE message is long enough for a payload of 107 * size bytes. 108 */ 109 static bool checkRtNetlinkLength(const struct nlmsghdr *nh, size_t size) { 110 if (nh->nlmsg_len < NLMSG_LENGTH(size)) { 111 SLOGE("Got a short %s message\n", rtMessageName(nh->nlmsg_type)); 112 return false; 113 } 114 return true; 115 } 116 117 /* 118 * Utility function to log errors. 119 */ 120 static bool maybeLogDuplicateAttribute(bool isDup, 121 const char *attributeName, 122 const char *messageName) { 123 if (isDup) { 124 SLOGE("Multiple %s attributes in %s, ignoring\n", attributeName, messageName); 125 return true; 126 } 127 return false; 128 } 129 130 /* 131 * Parse a RTM_NEWLINK message. 132 */ 133 bool NetlinkEvent::parseIfInfoMessage(const struct nlmsghdr *nh) { 134 struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(nh); 135 if (!checkRtNetlinkLength(nh, sizeof(*ifi))) 136 return false; 137 138 if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) { 139 return false; 140 } 141 142 int len = IFLA_PAYLOAD(nh); 143 struct rtattr *rta; 144 for (rta = IFLA_RTA(ifi); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { 145 switch(rta->rta_type) { 146 case IFLA_IFNAME: 147 asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta)); 148 mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? NlActionLinkUp : 149 NlActionLinkDown; 150 mSubsystem = strdup("net"); 151 return true; 152 } 153 } 154 155 return false; 156 } 157 158 /* 159 * Parse a RTM_NEWADDR or RTM_DELADDR message. 160 */ 161 bool NetlinkEvent::parseIfAddrMessage(const struct nlmsghdr *nh) { 162 struct ifaddrmsg *ifaddr = (struct ifaddrmsg *) NLMSG_DATA(nh); 163 struct ifa_cacheinfo *cacheinfo = NULL; 164 char addrstr[INET6_ADDRSTRLEN] = ""; 165 char ifname[IFNAMSIZ]; 166 167 if (!checkRtNetlinkLength(nh, sizeof(*ifaddr))) 168 return false; 169 170 // Sanity check. 171 int type = nh->nlmsg_type; 172 if (type != RTM_NEWADDR && type != RTM_DELADDR) { 173 SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type); 174 return false; 175 } 176 177 // For log messages. 178 const char *msgtype = rtMessageName(type); 179 180 struct rtattr *rta; 181 int len = IFA_PAYLOAD(nh); 182 for (rta = IFA_RTA(ifaddr); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { 183 if (rta->rta_type == IFA_ADDRESS) { 184 // Only look at the first address, because we only support notifying 185 // one change at a time. 186 if (maybeLogDuplicateAttribute(*addrstr != '\0', "IFA_ADDRESS", msgtype)) 187 continue; 188 189 // Convert the IP address to a string. 190 if (ifaddr->ifa_family == AF_INET) { 191 struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta); 192 if (RTA_PAYLOAD(rta) < sizeof(*addr4)) { 193 SLOGE("Short IPv4 address (%zu bytes) in %s", 194 RTA_PAYLOAD(rta), msgtype); 195 continue; 196 } 197 inet_ntop(AF_INET, addr4, addrstr, sizeof(addrstr)); 198 } else if (ifaddr->ifa_family == AF_INET6) { 199 struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta); 200 if (RTA_PAYLOAD(rta) < sizeof(*addr6)) { 201 SLOGE("Short IPv6 address (%zu bytes) in %s", 202 RTA_PAYLOAD(rta), msgtype); 203 continue; 204 } 205 inet_ntop(AF_INET6, addr6, addrstr, sizeof(addrstr)); 206 } else { 207 SLOGE("Unknown address family %d\n", ifaddr->ifa_family); 208 continue; 209 } 210 211 // Find the interface name. 212 if (!if_indextoname(ifaddr->ifa_index, ifname)) { 213 SLOGE("Unknown ifindex %d in %s", ifaddr->ifa_index, msgtype); 214 return false; 215 } 216 217 } else if (rta->rta_type == IFA_CACHEINFO) { 218 // Address lifetime information. 219 if (maybeLogDuplicateAttribute(cacheinfo, "IFA_CACHEINFO", msgtype)) 220 continue; 221 222 if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) { 223 SLOGE("Short IFA_CACHEINFO (%zu vs. %zu bytes) in %s", 224 RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype); 225 continue; 226 } 227 228 cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta); 229 } 230 } 231 232 if (addrstr[0] == '\0') { 233 SLOGE("No IFA_ADDRESS in %s\n", msgtype); 234 return false; 235 } 236 237 // Fill in netlink event information. 238 mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : 239 NlActionAddressRemoved; 240 mSubsystem = strdup("net"); 241 asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, 242 ifaddr->ifa_prefixlen); 243 asprintf(&mParams[1], "INTERFACE=%s", ifname); 244 asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags); 245 asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope); 246 247 if (cacheinfo) { 248 asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered); 249 asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid); 250 asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp); 251 asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp); 252 } 253 254 return true; 255 } 256 257 /* 258 * Parse a QLOG_NL_EVENT message. 259 */ 260 bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { 261 const char *devname; 262 ulog_packet_msg_t *pm = (ulog_packet_msg_t *) NLMSG_DATA(nh); 263 if (!checkRtNetlinkLength(nh, sizeof(*pm))) 264 return false; 265 266 devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; 267 asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix); 268 asprintf(&mParams[1], "INTERFACE=%s", devname); 269 mSubsystem = strdup("qlog"); 270 mAction = NlActionChange; 271 return true; 272 } 273 274 /* 275 * Parse a RTM_NEWROUTE or RTM_DELROUTE message. 276 */ 277 bool NetlinkEvent::parseRtMessage(const struct nlmsghdr *nh) { 278 uint8_t type = nh->nlmsg_type; 279 const char *msgname = rtMessageName(type); 280 281 // Sanity check. 282 if (type != RTM_NEWROUTE && type != RTM_DELROUTE) { 283 SLOGE("%s: incorrect message type %d (%s)\n", __func__, type, msgname); 284 return false; 285 } 286 287 struct rtmsg *rtm = (struct rtmsg *) NLMSG_DATA(nh); 288 if (!checkRtNetlinkLength(nh, sizeof(*rtm))) 289 return false; 290 291 if (// Ignore static routes we've set up ourselves. 292 (rtm->rtm_protocol != RTPROT_KERNEL && 293 rtm->rtm_protocol != RTPROT_RA) || 294 // We're only interested in global unicast routes. 295 (rtm->rtm_scope != RT_SCOPE_UNIVERSE) || 296 (rtm->rtm_type != RTN_UNICAST) || 297 // We don't support source routing. 298 (rtm->rtm_src_len != 0) || 299 // Cloned routes aren't real routes. 300 (rtm->rtm_flags & RTM_F_CLONED)) { 301 return false; 302 } 303 304 int family = rtm->rtm_family; 305 int prefixLength = rtm->rtm_dst_len; 306 307 // Currently we only support: destination, (one) next hop, ifindex. 308 char dst[INET6_ADDRSTRLEN] = ""; 309 char gw[INET6_ADDRSTRLEN] = ""; 310 char dev[IFNAMSIZ] = ""; 311 312 size_t len = RTM_PAYLOAD(nh); 313 struct rtattr *rta; 314 for (rta = RTM_RTA(rtm); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { 315 switch (rta->rta_type) { 316 case RTA_DST: 317 if (maybeLogDuplicateAttribute(*dst, "RTA_DST", msgname)) 318 continue; 319 if (!inet_ntop(family, RTA_DATA(rta), dst, sizeof(dst))) 320 return false; 321 continue; 322 case RTA_GATEWAY: 323 if (maybeLogDuplicateAttribute(*gw, "RTA_GATEWAY", msgname)) 324 continue; 325 if (!inet_ntop(family, RTA_DATA(rta), gw, sizeof(gw))) 326 return false; 327 continue; 328 case RTA_OIF: 329 if (maybeLogDuplicateAttribute(*dev, "RTA_OIF", msgname)) 330 continue; 331 if (!if_indextoname(* (int *) RTA_DATA(rta), dev)) 332 return false; 333 default: 334 continue; 335 } 336 } 337 338 // If there's no RTA_DST attribute, then: 339 // - If the prefix length is zero, it's the default route. 340 // - If the prefix length is nonzero, there's something we don't understand. 341 // Ignore the event. 342 if (!*dst && !prefixLength) { 343 if (family == AF_INET) { 344 strncpy(dst, "0.0.0.0", sizeof(dst)); 345 } else if (family == AF_INET6) { 346 strncpy(dst, "::", sizeof(dst)); 347 } 348 } 349 350 // A useful route must have a destination and at least either a gateway or 351 // an interface. 352 if (!*dst || (!*gw && !*dev)) 353 return false; 354 355 // Fill in netlink event information. 356 mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated : 357 NlActionRouteRemoved; 358 mSubsystem = strdup("net"); 359 asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength); 360 asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : ""); 361 asprintf(&mParams[2], "INTERFACE=%s", (*dev) ? dev : ""); 362 363 return true; 364 } 365 366 /* 367 * Parse a RTM_NEWNDUSEROPT message. 368 */ 369 bool NetlinkEvent::parseNdUserOptMessage(const struct nlmsghdr *nh) { 370 struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(nh); 371 if (!checkRtNetlinkLength(nh, sizeof(*msg))) 372 return false; 373 374 // Check the length is valid. 375 int len = NLMSG_PAYLOAD(nh, sizeof(*msg)); 376 if (msg->nduseropt_opts_len > len) { 377 SLOGE("RTM_NEWNDUSEROPT invalid length %d > %d\n", 378 msg->nduseropt_opts_len, len); 379 return false; 380 } 381 len = msg->nduseropt_opts_len; 382 383 // Check address family and packet type. 384 if (msg->nduseropt_family != AF_INET6) { 385 SLOGE("RTM_NEWNDUSEROPT message for unknown family %d\n", 386 msg->nduseropt_family); 387 return false; 388 } 389 390 if (msg->nduseropt_icmp_type != ND_ROUTER_ADVERT || 391 msg->nduseropt_icmp_code != 0) { 392 SLOGE("RTM_NEWNDUSEROPT message for unknown ICMPv6 type/code %d/%d\n", 393 msg->nduseropt_icmp_type, msg->nduseropt_icmp_code); 394 return false; 395 } 396 397 // Find the interface name. 398 char ifname[IFNAMSIZ]; 399 if (!if_indextoname(msg->nduseropt_ifindex, ifname)) { 400 SLOGE("RTM_NEWNDUSEROPT on unknown ifindex %d\n", 401 msg->nduseropt_ifindex); 402 return false; 403 } 404 405 // The kernel sends a separate netlink message for each ND option in the RA. 406 // So only parse the first ND option in the message. 407 struct nd_opt_hdr *opthdr = (struct nd_opt_hdr *) (msg + 1); 408 409 // The length is in multiples of 8 octets. 410 uint16_t optlen = opthdr->nd_opt_len; 411 if (optlen * 8 > len) { 412 SLOGE("Invalid option length %d > %d for ND option %d\n", 413 optlen * 8, len, opthdr->nd_opt_type); 414 return false; 415 } 416 417 if (opthdr->nd_opt_type == ND_OPT_RDNSS) { 418 // DNS Servers (RFC 6106). 419 // Each address takes up 2*8 octets, and the header takes up 8 octets. 420 // So for a valid option with one or more addresses, optlen must be 421 // odd and greater than 1. 422 if ((optlen < 3) || !(optlen & 0x1)) { 423 SLOGE("Invalid optlen %d for RDNSS option\n", optlen); 424 return false; 425 } 426 int numaddrs = (optlen - 1) / 2; 427 428 // Find the lifetime. 429 struct nd_opt_rdnss *rndss_opt = (struct nd_opt_rdnss *) opthdr; 430 uint32_t lifetime = ntohl(rndss_opt->nd_opt_rdnss_lifetime); 431 432 // Construct "SERVERS=<comma-separated string of DNS addresses>". 433 // Reserve (INET6_ADDRSTRLEN + 1) chars for each address: all but the 434 // the last address are followed by ','; the last is followed by '\0'. 435 static const char kServerTag[] = "SERVERS="; 436 static const int kTagLength = sizeof(kServerTag) - 1; 437 int bufsize = kTagLength + numaddrs * (INET6_ADDRSTRLEN + 1); 438 char *buf = (char *) malloc(bufsize); 439 if (!buf) { 440 SLOGE("RDNSS option: out of memory\n"); 441 return false; 442 } 443 strcpy(buf, kServerTag); 444 int pos = kTagLength; 445 446 struct in6_addr *addrs = (struct in6_addr *) (rndss_opt + 1); 447 for (int i = 0; i < numaddrs; i++) { 448 if (i > 0) { 449 buf[pos++] = ','; 450 } 451 inet_ntop(AF_INET6, addrs + i, buf + pos, bufsize - pos); 452 pos += strlen(buf + pos); 453 } 454 buf[pos] = '\0'; 455 456 mAction = NlActionRdnss; 457 mSubsystem = strdup("net"); 458 asprintf(&mParams[0], "INTERFACE=%s", ifname); 459 asprintf(&mParams[1], "LIFETIME=%u", lifetime); 460 mParams[2] = buf; 461 } else { 462 SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type); 463 return false; 464 } 465 466 return true; 467 } 468 469 /* 470 * Parse a binary message from a NETLINK_ROUTE netlink socket. 471 * 472 * Note that this function can only parse one message, because the message's 473 * content has to be stored in the class's member variables (mAction, 474 * mSubsystem, etc.). Invalid or unrecognized messages are skipped, but if 475 * there are multiple valid messages in the buffer, only the first one will be 476 * returned. 477 * 478 * TODO: consider only ever looking at the first message. 479 */ 480 bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { 481 const struct nlmsghdr *nh; 482 483 for (nh = (struct nlmsghdr *) buffer; 484 NLMSG_OK(nh, (unsigned) size) && (nh->nlmsg_type != NLMSG_DONE); 485 nh = NLMSG_NEXT(nh, size)) { 486 487 if (!rtMessageName(nh->nlmsg_type)) { 488 SLOGD("Unexpected netlink message type %d\n", nh->nlmsg_type); 489 continue; 490 } 491 492 if (nh->nlmsg_type == RTM_NEWLINK) { 493 if (parseIfInfoMessage(nh)) 494 return true; 495 496 } else if (nh->nlmsg_type == QLOG_NL_EVENT) { 497 if (parseUlogPacketMessage(nh)) 498 return true; 499 500 } else if (nh->nlmsg_type == RTM_NEWADDR || 501 nh->nlmsg_type == RTM_DELADDR) { 502 if (parseIfAddrMessage(nh)) 503 return true; 504 505 } else if (nh->nlmsg_type == RTM_NEWROUTE || 506 nh->nlmsg_type == RTM_DELROUTE) { 507 if (parseRtMessage(nh)) 508 return true; 509 510 } else if (nh->nlmsg_type == RTM_NEWNDUSEROPT) { 511 if (parseNdUserOptMessage(nh)) 512 return true; 513 514 } 515 } 516 517 return false; 518 } 519 520 /* If the string between 'str' and 'end' begins with 'prefixlen' characters 521 * from the 'prefix' array, then return 'str + prefixlen', otherwise return 522 * NULL. 523 */ 524 static const char* 525 has_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen) 526 { 527 if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen)) 528 return str + prefixlen; 529 else 530 return NULL; 531 } 532 533 /* Same as strlen(x) for constant string literals ONLY */ 534 #define CONST_STRLEN(x) (sizeof(x)-1) 535 536 /* Convenience macro to call has_prefix with a constant string literal */ 537 #define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix)) 538 539 540 /* 541 * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT 542 * netlink socket. 543 */ 544 bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) { 545 const char *s = buffer; 546 const char *end; 547 int param_idx = 0; 548 int first = 1; 549 550 if (size == 0) 551 return false; 552 553 /* Ensure the buffer is zero-terminated, the code below depends on this */ 554 buffer[size-1] = '\0'; 555 556 end = s + size; 557 while (s < end) { 558 if (first) { 559 const char *p; 560 /* buffer is 0-terminated, no need to check p < end */ 561 for (p = s; *p != '@'; p++) { 562 if (!*p) { /* no '@', should not happen */ 563 return false; 564 } 565 } 566 mPath = strdup(p+1); 567 first = 0; 568 } else { 569 const char* a; 570 if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) { 571 if (!strcmp(a, "add")) 572 mAction = NlActionAdd; 573 else if (!strcmp(a, "remove")) 574 mAction = NlActionRemove; 575 else if (!strcmp(a, "change")) 576 mAction = NlActionChange; 577 } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) { 578 mSeq = atoi(a); 579 } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) { 580 mSubsystem = strdup(a); 581 } else if (param_idx < NL_PARAMS_MAX) { 582 mParams[param_idx++] = strdup(s); 583 } 584 } 585 s += strlen(s) + 1; 586 } 587 return true; 588 } 589 590 bool NetlinkEvent::decode(char *buffer, int size, int format) { 591 if (format == NetlinkListener::NETLINK_FORMAT_BINARY) { 592 return parseBinaryNetlinkMessage(buffer, size); 593 } else { 594 return parseAsciiNetlinkMessage(buffer, size); 595 } 596 } 597 598 const char *NetlinkEvent::findParam(const char *paramName) { 599 size_t len = strlen(paramName); 600 for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) { 601 const char *ptr = mParams[i] + len; 602 if (!strncmp(mParams[i], paramName, len) && *ptr == '=') 603 return ++ptr; 604 } 605 606 SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName); 607 return NULL; 608 } 609