blob: 2e3143dee2df2909ec0d2a2281bbbf48176b39f1 [file] [log] [blame]
San Mehat168415b2009-05-06 11:14:21 -07001/*
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>
San Mehat3d407292009-05-07 08:49:30 -070017#include <string.h>
San Mehat168415b2009-05-06 11:14:21 -070018
19#define LOG_TAG "NetlinkEvent"
20#include <cutils/log.h>
21
Stan Chesnutt8418ac82010-12-26 22:15:00 -080022#include <sysutils/NetlinkListener.h>
San Mehat168415b2009-05-06 11:14:21 -070023#include <sysutils/NetlinkEvent.h>
24
Stan Chesnutt8418ac82010-12-26 22:15:00 -080025#include <sys/types.h>
26#include <sys/socket.h>
27#include <linux/rtnetlink.h>
28#include <linux/if.h>
29
San Mehat168415b2009-05-06 11:14:21 -070030const int NetlinkEvent::NlActionUnknown = 0;
31const int NetlinkEvent::NlActionAdd = 1;
32const int NetlinkEvent::NlActionRemove = 2;
33const int NetlinkEvent::NlActionChange = 3;
Stan Chesnutt8418ac82010-12-26 22:15:00 -080034const int NetlinkEvent::NlActionLinkUp = 4;
35const int NetlinkEvent::NlActionLinkDown = 5;
San Mehat168415b2009-05-06 11:14:21 -070036
37NetlinkEvent::NetlinkEvent() {
38 mAction = NlActionUnknown;
San Mehatebfe3db2009-10-10 17:35:13 -070039 memset(mParams, 0, sizeof(mParams));
40 mPath = NULL;
41 mSubsystem = NULL;
San Mehat168415b2009-05-06 11:14:21 -070042}
43
44NetlinkEvent::~NetlinkEvent() {
45 int i;
46 if (mPath)
47 free(mPath);
48 if (mSubsystem)
49 free(mSubsystem);
50 for (i = 0; i < NL_PARAMS_MAX; i++) {
51 if (!mParams[i])
52 break;
53 free(mParams[i]);
54 }
55}
56
San Mehatd6744132009-12-24 07:17:09 -080057void NetlinkEvent::dump() {
58 int i;
59
60 for (i = 0; i < NL_PARAMS_MAX; i++) {
61 if (!mParams[i])
62 break;
San Mehat7e8529a2010-03-25 09:31:42 -070063 SLOGD("NL param '%s'\n", mParams[i]);
San Mehatd6744132009-12-24 07:17:09 -080064 }
65}
66
Stan Chesnutt8418ac82010-12-26 22:15:00 -080067/*
68 * Parse an binary message from a NETLINK_ROUTE netlink socket.
69 */
70bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
71 size_t sz = size;
72 struct nlmsghdr *nh = (struct nlmsghdr *) buffer;
73
74 while (NLMSG_OK(nh, sz) && (nh->nlmsg_type != NLMSG_DONE)) {
75 if (nh->nlmsg_type == RTM_NEWLINK) {
76 int len = nh->nlmsg_len - sizeof(*nh);
77 struct ifinfomsg *ifi;
78
79 if (sizeof(*ifi) <= (size_t) len) {
80 ifi = (ifinfomsg *)NLMSG_DATA(nh);
81
82 if ((ifi->ifi_flags & IFF_LOOPBACK) == 0) {
83 struct rtattr *rta = (struct rtattr *)
84 ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
85 len = NLMSG_PAYLOAD(nh, sizeof(*ifi));
86
87 while(RTA_OK(rta, len)) {
88 switch(rta->rta_type) {
89 case IFLA_IFNAME:
90 char buffer[16 + IFNAMSIZ];
91 snprintf(buffer, sizeof(buffer), "INTERFACE=%s",
92 (char *) RTA_DATA(rta));
93 mParams[0] = strdup(buffer);
94 mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?
95 NlActionLinkUp : NlActionLinkDown;
96 mSubsystem = strdup("net");
97 break;
98 }
99
100 rta = RTA_NEXT(rta, len);
101 }
102 }
103 }
104 }
105
106 nh = NLMSG_NEXT(nh, size);
107 }
108
109 return true;
110}
111
112/*
113 * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT
114 * netlink socket.
115 */
116bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) {
San Mehat168415b2009-05-06 11:14:21 -0700117 char *s = buffer;
118 char *end;
119 int param_idx = 0;
120 int i;
121 int first = 1;
122
123 end = s + size;
124 while (s < end) {
125 if (first) {
126 char *p;
127 for (p = s; *p != '@'; p++);
128 p++;
129 mPath = strdup(p);
130 first = 0;
131 } else {
132 if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
133 char *a = s + strlen("ACTION=");
134 if (!strcmp(a, "add"))
135 mAction = NlActionAdd;
136 else if (!strcmp(a, "remove"))
137 mAction = NlActionRemove;
138 else if (!strcmp(a, "change"))
139 mAction = NlActionChange;
San Mehat03f0d272009-05-26 15:18:25 -0700140 } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
San Mehat168415b2009-05-06 11:14:21 -0700141 mSeq = atoi(s + strlen("SEQNUM="));
San Mehat03f0d272009-05-26 15:18:25 -0700142 else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
San Mehat168415b2009-05-06 11:14:21 -0700143 mSubsystem = strdup(s + strlen("SUBSYSTEM="));
144 else
145 mParams[param_idx++] = strdup(s);
146 }
147 s+= strlen(s) + 1;
148 }
149 return true;
150}
151
Stan Chesnutt8418ac82010-12-26 22:15:00 -0800152bool NetlinkEvent::decode(char *buffer, int size, int format) {
153 if (format == NetlinkListener::NETLINK_FORMAT_BINARY) {
154 return parseBinaryNetlinkMessage(buffer, size);
155 } else {
156 return parseAsciiNetlinkMessage(buffer, size);
157 }
158}
159
San Mehat168415b2009-05-06 11:14:21 -0700160const char *NetlinkEvent::findParam(const char *paramName) {
Chih-Wei Huang80ec37a2010-07-14 14:00:41 +0800161 size_t len = strlen(paramName);
162 for (int i = 0; mParams[i] && i < NL_PARAMS_MAX; ++i) {
163 const char *ptr = mParams[i] + len;
164 if (!strncmp(mParams[i], paramName, len) && *ptr == '=')
165 return ++ptr;
San Mehat168415b2009-05-06 11:14:21 -0700166 }
167
San Mehat7e8529a2010-03-25 09:31:42 -0700168 SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
San Mehat168415b2009-05-06 11:14:21 -0700169 return NULL;
170}