NetlinkEvent.cpp revision 3311eea1d3881e6f3d6806988b7db3de0a5f68d5
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
24168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionUnknown = 0;
25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionAdd = 1;
26168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionRemove = 2;
27168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst int NetlinkEvent::NlActionChange = 3;
28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
29168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatNetlinkEvent::NetlinkEvent() {
30168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mAction = NlActionUnknown;
31ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat    memset(mParams, 0, sizeof(mParams));
32ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat    mPath = NULL;
33ebfe3db361c51d9d99bf6cfd495bd16bdf815e1fSan Mehat    mSubsystem = NULL;
34168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
35168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
36168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatNetlinkEvent::~NetlinkEvent() {
37168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    int i;
38168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (mPath)
39168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        free(mPath);
40168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (mSubsystem)
41168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        free(mSubsystem);
42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    for (i = 0; i < NL_PARAMS_MAX; i++) {
43168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if (!mParams[i])
44168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            break;
45168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        free(mParams[i]);
46168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
48168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
49d674413ff460afe1da049e54bb7a489132799749San Mehatvoid NetlinkEvent::dump() {
50d674413ff460afe1da049e54bb7a489132799749San Mehat    int i;
51d674413ff460afe1da049e54bb7a489132799749San Mehat
52d674413ff460afe1da049e54bb7a489132799749San Mehat    for (i = 0; i < NL_PARAMS_MAX; i++) {
53d674413ff460afe1da049e54bb7a489132799749San Mehat        if (!mParams[i])
54d674413ff460afe1da049e54bb7a489132799749San Mehat            break;
557e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGD("NL param '%s'\n", mParams[i]);
56d674413ff460afe1da049e54bb7a489132799749San Mehat    }
57d674413ff460afe1da049e54bb7a489132799749San Mehat}
58d674413ff460afe1da049e54bb7a489132799749San Mehat
593311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* If the string between 'str' and 'end' begins with 'prefixlen' characters
603311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner * from the 'prefix' array, then return 'str + prefixlen', otherwise return
613311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner * NULL.
623311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner */
633311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turnerstatic const char*
643311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turnerhas_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen)
653311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner{
663311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen))
673311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner        return str + prefixlen;
683311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    else
693311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner        return NULL;
703311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner}
713311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
723311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* Same as strlen(x) for constant string literals ONLY */
733311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner#define CONST_STRLEN(x)  (sizeof(x)-1)
743311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
753311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner/* Convenience macro to call has_prefix with a constant string literal  */
763311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner#define HAS_CONST_PREFIX(str,end,prefix)  has_prefix((str),(end),prefix,CONST_STRLEN(prefix))
773311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
783311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
79168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatbool NetlinkEvent::decode(char *buffer, int size) {
803311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    const char *s = buffer;
813311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    const char *end;
82168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    int param_idx = 0;
83168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    int i;
84168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    int first = 1;
85168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
863311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    if (size == 0)
873311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner        return false;
883311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
893311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    /* Ensure the buffer is zero-terminated, the code below depends on this */
903311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    buffer[size-1] = '\0';
913311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner
92168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    end = s + size;
93168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    while (s < end) {
94168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if (first) {
953311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            const char *p;
963311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            /* buffer is 0-terminated, no need to check p < end */
973311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            for (p = s; *p != '@'; p++) {
983311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner                if (!*p) { /* no '@', should not happen */
993311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner                    return false;
1003311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner                }
1013311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            }
1023311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            mPath = strdup(p+1);
103168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            first = 0;
104168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        } else {
1053311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            const char* a;
1063311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
107168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                if (!strcmp(a, "add"))
108168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                    mAction = NlActionAdd;
109168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                else if (!strcmp(a, "remove"))
110168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                    mAction = NlActionRemove;
111168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                else if (!strcmp(a, "change"))
112168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                    mAction = NlActionChange;
1133311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
1143311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner                mSeq = atoi(a);
1153311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
1163311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner                mSubsystem = strdup(a);
1173311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            } else if (param_idx < NL_PARAMS_MAX) {
118168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                mParams[param_idx++] = strdup(s);
1193311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner            }
120168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
1213311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner        s += strlen(s) + 1;
122168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
123168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    return true;
124168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
125168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
126168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatconst char *NetlinkEvent::findParam(const char *paramName) {
12780ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang    size_t len = strlen(paramName);
1283311eea1d3881e6f3d6806988b7db3de0a5f68d5David 'Digit' Turner    for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) {
12980ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang        const char *ptr = mParams[i] + len;
13080ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang        if (!strncmp(mParams[i], paramName, len) && *ptr == '=')
13180ec37aa15c138beee5889a257d1241c30a1e8d7Chih-Wei Huang            return ++ptr;
132168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
133168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
1347e8529a8b528fd30586aa037f15a31b29582c537San Mehat    SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
135168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    return NULL;
136168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
137