1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/* 2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Copyright (C) 2008 The Android Open Source Project 3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * you may not use this file except in compliance with the License. 6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * You may obtain a copy of the License at 7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Unless required by applicable law or agreed to in writing, software 11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * See the License for the specific language governing permissions and 14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * limitations under the License. 15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat */ 16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdlib.h> 173d40729054803fae1c4d4bb5ac7554665a132b26San Mehat#include <string.h> 18168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 19168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "NetlinkEvent" 20168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/log.h> 21168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 22168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/NetlinkEvent.h> 23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 24ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen#include <sys/types.h> 25ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen#include <sys/socket.h> 26a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti#include <netinet/in.h> 27a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti#include <arpa/inet.h> 28a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti#include <net/if.h> 29a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 30ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen#include <linux/if.h> 31e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall#include <linux/netfilter/nfnetlink.h> 32e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall#include <linux/netfilter_ipv4/ipt_ULOG.h> 33e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall/* From kernel's net/netfilter/xt_quota2.c */ 34e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrallconst int QLOG_NL_EVENT = 112; 35e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 36e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall#include <linux/netlink.h> 37e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall#include <linux/rtnetlink.h> 38ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 39168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionUnknown = 0; 40168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionAdd = 1; 41168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionRemove = 2; 42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionChange = 3; 43ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chenconst int NetlinkEvent::NlActionLinkUp = 4; 44ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chenconst int NetlinkEvent::NlActionLinkDown = 5; 45f34861346d5c207912075fba9874090e4c947869Lorenzo Colitticonst int NetlinkEvent::NlActionAddressUpdated = 6; 46f34861346d5c207912075fba9874090e4c947869Lorenzo Colitticonst int NetlinkEvent::NlActionAddressRemoved = 7; 47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 48168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatNetlinkEvent::NetlinkEvent() { 49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mAction = NlActionUnknown; 50ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat memset(mParams, 0, sizeof(mParams)); 51ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat mPath = NULL; 52ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat mSubsystem = NULL; 53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 55168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatNetlinkEvent::~NetlinkEvent() { 56168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int i; 57168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (mPath) 58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat free(mPath); 59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (mSubsystem) 60168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat free(mSubsystem); 61168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat for (i = 0; i < NL_PARAMS_MAX; i++) { 62168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (!mParams[i]) 63168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat break; 64168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat free(mParams[i]); 65168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 66168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 67168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 68d674413ff460afe1da049e54bb7a489132799749San Mehatvoid NetlinkEvent::dump() { 69d674413ff460afe1da049e54bb7a489132799749San Mehat int i; 70d674413ff460afe1da049e54bb7a489132799749San Mehat 71d674413ff460afe1da049e54bb7a489132799749San Mehat for (i = 0; i < NL_PARAMS_MAX; i++) { 72d674413ff460afe1da049e54bb7a489132799749San Mehat if (!mParams[i]) 73d674413ff460afe1da049e54bb7a489132799749San Mehat break; 747e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGD("NL param '%s'\n", mParams[i]); 75d674413ff460afe1da049e54bb7a489132799749San Mehat } 76d674413ff460afe1da049e54bb7a489132799749San Mehat} 77d674413ff460afe1da049e54bb7a489132799749San Mehat 78ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen/* 79a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti * Decode a RTM_NEWADDR or RTM_DELADDR message. 80a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti */ 81a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colittibool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, 82a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti int rtasize) { 833984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti struct rtattr *rta; 84a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti struct ifa_cacheinfo *cacheinfo = NULL; 85a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti char addrstr[INET6_ADDRSTRLEN] = ""; 86a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 87a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Sanity check. 88a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (type != RTM_NEWADDR && type != RTM_DELADDR) { 89a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type); 90a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti return false; 91a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 92a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 93a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // For log messages. 94a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti const char *msgtype = (type == RTM_NEWADDR) ? "RTM_NEWADDR" : "RTM_DELADDR"; 95a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 963984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti for (rta = IFA_RTA(ifaddr); RTA_OK(rta, rtasize); 973984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti rta = RTA_NEXT(rta, rtasize)) { 98a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (rta->rta_type == IFA_ADDRESS) { 99a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Only look at the first address, because we only support notifying 100a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // one change at a time. 101a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (*addrstr != '\0') { 102a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Multiple IFA_ADDRESSes in %s, ignoring\n", msgtype); 103a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 104a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 105a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 106a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Convert the IP address to a string. 107a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (ifaddr->ifa_family == AF_INET) { 108a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta); 109a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (RTA_PAYLOAD(rta) < sizeof(*addr4)) { 110a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Short IPv4 address (%d bytes) in %s", 111a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti RTA_PAYLOAD(rta), msgtype); 112a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 113a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 114a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti inet_ntop(AF_INET, addr4, addrstr, sizeof(addrstr)); 115a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } else if (ifaddr->ifa_family == AF_INET6) { 116a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta); 117a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (RTA_PAYLOAD(rta) < sizeof(*addr6)) { 118a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Short IPv6 address (%d bytes) in %s", 119a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti RTA_PAYLOAD(rta), msgtype); 120a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 121a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 122a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti inet_ntop(AF_INET6, addr6, addrstr, sizeof(addrstr)); 123a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } else { 124a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Unknown address family %d\n", ifaddr->ifa_family); 125a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 126a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 127a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 128a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Find the interface name. 129a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti char ifname[IFNAMSIZ + 1]; 130a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (!if_indextoname(ifaddr->ifa_index, ifname)) { 131a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Unknown ifindex %d in %s", ifaddr->ifa_index, msgtype); 132a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti return false; 133a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 134a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 135a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Fill in interface information. 136f34861346d5c207912075fba9874090e4c947869Lorenzo Colitti mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : 137f34861346d5c207912075fba9874090e4c947869Lorenzo Colitti NlActionAddressRemoved; 138f34861346d5c207912075fba9874090e4c947869Lorenzo Colitti mSubsystem = strdup("net"); 139a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, 140a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti ifaddr->ifa_prefixlen); 141f34861346d5c207912075fba9874090e4c947869Lorenzo Colitti asprintf(&mParams[1], "INTERFACE=%s", ifname); 142a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags); 143a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope); 144a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } else if (rta->rta_type == IFA_CACHEINFO) { 145a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // Address lifetime information. 146a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (cacheinfo) { 147a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti // We only support one address. 148a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Multiple IFA_CACHEINFOs in %s, ignoring\n", msgtype); 149a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 150a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 151a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 152a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) { 153a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Short IFA_CACHEINFO (%d vs. %d bytes) in %s", 154a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype); 155a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 156a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 157a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 158a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta); 159a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered); 160a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid); 161a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp); 162a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp); 163a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 164a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 165a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 166a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (addrstr[0] == '\0') { 167a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("No IFA_ADDRESS in %s\n", msgtype); 168a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti return false; 169a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 170a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 171a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti return true; 172a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti} 173a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 174a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti/* 175b982bce73b7e2c824ffb50115ea382fe45c751a4JP Abgrall * Parse an binary message from a NETLINK_ROUTE netlink socket. 176ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen */ 177ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chenbool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { 1783984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti const struct nlmsghdr *nh; 179ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 1803984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti for (nh = (struct nlmsghdr *) buffer; 1813984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti NLMSG_OK(nh, size) && (nh->nlmsg_type != NLMSG_DONE); 1823984276ce47c965ad02a522280a139e0a0c7e5cfLorenzo Colitti nh = NLMSG_NEXT(nh, size)) { 183e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 184ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen if (nh->nlmsg_type == RTM_NEWLINK) { 185ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen int len = nh->nlmsg_len - sizeof(*nh); 186ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen struct ifinfomsg *ifi; 187ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 188e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall if (sizeof(*ifi) > (size_t) len) { 189e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall SLOGE("Got a short RTM_NEWLINK message\n"); 190e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall continue; 191e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } 192e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 193e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall ifi = (ifinfomsg *)NLMSG_DATA(nh); 194e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) { 195e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall continue; 196e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } 197e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 198e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall struct rtattr *rta = (struct rtattr *) 199e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi))); 200e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall len = NLMSG_PAYLOAD(nh, sizeof(*ifi)); 201e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 202e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall while(RTA_OK(rta, len)) { 203e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall switch(rta->rta_type) { 204e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall case IFLA_IFNAME: 205e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall char buffer[16 + IFNAMSIZ]; 206e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall snprintf(buffer, sizeof(buffer), "INTERFACE=%s", 207e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall (char *) RTA_DATA(rta)); 208e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall mParams[0] = strdup(buffer); 209e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? 210e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall NlActionLinkUp : NlActionLinkDown; 211f34861346d5c207912075fba9874090e4c947869Lorenzo Colitti mSubsystem = strdup("net"); 212e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall break; 213ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen } 214e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 215e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall rta = RTA_NEXT(rta, len); 216ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen } 217ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 218e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } else if (nh->nlmsg_type == QLOG_NL_EVENT) { 219e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall char *devname; 220e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall ulog_packet_msg_t *pm; 221e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall size_t len = nh->nlmsg_len - sizeof(*nh); 222e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall if (sizeof(*pm) > len) { 223e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall SLOGE("Got a short QLOG message\n"); 224e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall continue; 225e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } 226e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall pm = (ulog_packet_msg_t *)NLMSG_DATA(nh); 227e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; 228e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix); 229e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall asprintf(&mParams[1], "INTERFACE=%s", devname); 230e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall mSubsystem = strdup("qlog"); 231e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall mAction = NlActionChange; 232e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall 233a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } else if (nh->nlmsg_type == RTM_NEWADDR || 234a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti nh->nlmsg_type == RTM_DELADDR) { 235a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti int len = nh->nlmsg_len - sizeof(*nh); 236a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti struct ifaddrmsg *ifa; 237a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 238a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (sizeof(*ifa) > (size_t) len) { 239a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti SLOGE("Got a short RTM_xxxADDR message\n"); 240a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 241a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 242a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti 243a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti ifa = (ifaddrmsg *)NLMSG_DATA(nh); 244a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti size_t rtasize = IFA_PAYLOAD(nh); 245a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti if (!parseIfAddrMessage(nh->nlmsg_type, ifa, rtasize)) { 246a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti continue; 247a4b4e9ad8e35ab424e61d76ebe6654445fc61e63Lorenzo Colitti } 248e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } else { 249e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall SLOGD("Unexpected netlink message. type=0x%x\n", nh->nlmsg_type); 250e6f80149a201e02ddd1e251e0690ad100b688cd6JP Abgrall } 251ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen } 252ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 253ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen return true; 254ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen} 255ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 2563311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* If the string between 'str' and 'end' begins with 'prefixlen' characters 2573311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner * from the 'prefix' array, then return 'str + prefixlen', otherwise return 2583311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner * NULL. 2593311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner */ 2603311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turnerstatic const char* 2613311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turnerhas_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen) 2623311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner{ 2633311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen)) 2643311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner return str + prefixlen; 2653311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner else 2663311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner return NULL; 2673311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner} 2683311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 2693311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* Same as strlen(x) for constant string literals ONLY */ 2703311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner#define CONST_STRLEN(x) (sizeof(x)-1) 2713311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 2723311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* Convenience macro to call has_prefix with a constant string literal */ 2733311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner#define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix)) 2743311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 2753311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 276ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen/* 277ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT 278ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen * netlink socket. 279ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen */ 280ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chenbool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) { 28117260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen const char *s = buffer; 28217260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen const char *end; 283168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int param_idx = 0; 284168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int i; 285168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int first = 1; 286168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 2873311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner if (size == 0) 2883311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner return false; 2893311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 2903311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner /* Ensure the buffer is zero-terminated, the code below depends on this */ 2913311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner buffer[size-1] = '\0'; 2923311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner 293168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat end = s + size; 294168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat while (s < end) { 295168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (first) { 2963311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner const char *p; 2973311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner /* buffer is 0-terminated, no need to check p < end */ 2983311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner for (p = s; *p != '@'; p++) { 2993311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner if (!*p) { /* no '@', should not happen */ 3003311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner return false; 3013311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } 3023311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } 3033311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner mPath = strdup(p+1); 304168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat first = 0; 305168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } else { 3063311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner const char* a; 3073311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) { 308168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (!strcmp(a, "add")) 309168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mAction = NlActionAdd; 310168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat else if (!strcmp(a, "remove")) 311168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mAction = NlActionRemove; 312168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat else if (!strcmp(a, "change")) 313168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mAction = NlActionChange; 3143311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) { 3153311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner mSeq = atoi(a); 3163311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) { 3173311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner mSubsystem = strdup(a); 3183311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } else if (param_idx < NL_PARAMS_MAX) { 319168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mParams[param_idx++] = strdup(s); 3203311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner } 321168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 3223311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner s += strlen(s) + 1; 323168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 324168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return true; 325168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 326168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 327ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chenbool NetlinkEvent::decode(char *buffer, int size, int format) { 32817260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen if (format == NetlinkListener::NETLINK_FORMAT_BINARY) { 32917260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen return parseBinaryNetlinkMessage(buffer, size); 33017260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen } else { 33117260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen return parseAsciiNetlinkMessage(buffer, size); 33217260b14682d4fe59dad3de2de8c9370e6ba9a71Mike J. Chen } 333ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen} 334ec16b9d47cacb0d873ee0ff80c919f49215c0005Mike J. Chen 335168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst char *NetlinkEvent::findParam(const char *paramName) { 33680ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang size_t len = strlen(paramName); 3373311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) { 33880ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang const char *ptr = mParams[i] + len; 33980ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang if (!strncmp(mParams[i], paramName, len) && *ptr == '=') 34080ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang return ++ptr; 341168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 342168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 3437e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName); 344168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return NULL; 345168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 346