blob: c8d3b1f2ca4b5493b78a09723d5b6f2dd9feb98a [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
22#include <sysutils/NetlinkEvent.h>
23
24const int NetlinkEvent::NlActionUnknown = 0;
25const int NetlinkEvent::NlActionAdd = 1;
26const int NetlinkEvent::NlActionRemove = 2;
27const int NetlinkEvent::NlActionChange = 3;
28
29NetlinkEvent::NetlinkEvent() {
30 mAction = NlActionUnknown;
San Mehatebfe3db2009-10-10 17:35:13 -070031 memset(mParams, 0, sizeof(mParams));
32 mPath = NULL;
33 mSubsystem = NULL;
San Mehat168415b2009-05-06 11:14:21 -070034}
35
36NetlinkEvent::~NetlinkEvent() {
37 int i;
38 if (mPath)
39 free(mPath);
40 if (mSubsystem)
41 free(mSubsystem);
42 for (i = 0; i < NL_PARAMS_MAX; i++) {
43 if (!mParams[i])
44 break;
45 free(mParams[i]);
46 }
47}
48
San Mehatd6744132009-12-24 07:17:09 -080049void NetlinkEvent::dump() {
50 int i;
51
52 for (i = 0; i < NL_PARAMS_MAX; i++) {
53 if (!mParams[i])
54 break;
San Mehat7e8529a2010-03-25 09:31:42 -070055 SLOGD("NL param '%s'\n", mParams[i]);
San Mehatd6744132009-12-24 07:17:09 -080056 }
57}
58
David 'Digit' Turner3311eea2011-01-17 01:59:22 +010059/* If the string between 'str' and 'end' begins with 'prefixlen' characters
60 * from the 'prefix' array, then return 'str + prefixlen', otherwise return
61 * NULL.
62 */
63static const char*
64has_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen)
65{
66 if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen))
67 return str + prefixlen;
68 else
69 return NULL;
70}
71
72/* Same as strlen(x) for constant string literals ONLY */
73#define CONST_STRLEN(x) (sizeof(x)-1)
74
75/* Convenience macro to call has_prefix with a constant string literal */
76#define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix))
77
78
San Mehat168415b2009-05-06 11:14:21 -070079bool NetlinkEvent::decode(char *buffer, int size) {
David 'Digit' Turner3311eea2011-01-17 01:59:22 +010080 const char *s = buffer;
81 const char *end;
San Mehat168415b2009-05-06 11:14:21 -070082 int param_idx = 0;
83 int i;
84 int first = 1;
85
David 'Digit' Turner3311eea2011-01-17 01:59:22 +010086 if (size == 0)
87 return false;
88
89 /* Ensure the buffer is zero-terminated, the code below depends on this */
90 buffer[size-1] = '\0';
91
San Mehat168415b2009-05-06 11:14:21 -070092 end = s + size;
93 while (s < end) {
94 if (first) {
David 'Digit' Turner3311eea2011-01-17 01:59:22 +010095 const char *p;
96 /* buffer is 0-terminated, no need to check p < end */
97 for (p = s; *p != '@'; p++) {
98 if (!*p) { /* no '@', should not happen */
99 return false;
100 }
101 }
102 mPath = strdup(p+1);
San Mehat168415b2009-05-06 11:14:21 -0700103 first = 0;
104 } else {
David 'Digit' Turner3311eea2011-01-17 01:59:22 +0100105 const char* a;
106 if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
San Mehat168415b2009-05-06 11:14:21 -0700107 if (!strcmp(a, "add"))
108 mAction = NlActionAdd;
109 else if (!strcmp(a, "remove"))
110 mAction = NlActionRemove;
111 else if (!strcmp(a, "change"))
112 mAction = NlActionChange;
David 'Digit' Turner3311eea2011-01-17 01:59:22 +0100113 } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
114 mSeq = atoi(a);
115 } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
116 mSubsystem = strdup(a);
117 } else if (param_idx < NL_PARAMS_MAX) {
San Mehat168415b2009-05-06 11:14:21 -0700118 mParams[param_idx++] = strdup(s);
David 'Digit' Turner3311eea2011-01-17 01:59:22 +0100119 }
San Mehat168415b2009-05-06 11:14:21 -0700120 }
David 'Digit' Turner3311eea2011-01-17 01:59:22 +0100121 s += strlen(s) + 1;
San Mehat168415b2009-05-06 11:14:21 -0700122 }
123 return true;
124}
125
126const char *NetlinkEvent::findParam(const char *paramName) {
Chih-Wei Huang80ec37a2010-07-14 14:00:41 +0800127 size_t len = strlen(paramName);
David 'Digit' Turner3311eea2011-01-17 01:59:22 +0100128 for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) {
Chih-Wei Huang80ec37a2010-07-14 14:00:41 +0800129 const char *ptr = mParams[i] + len;
130 if (!strncmp(mParams[i], paramName, len) && *ptr == '=')
131 return ++ptr;
San Mehat168415b2009-05-06 11:14:21 -0700132 }
133
San Mehat7e8529a2010-03-25 09:31:42 -0700134 SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
San Mehat168415b2009-05-06 11:14:21 -0700135 return NULL;
136}