1 /*
2  * Copyright (C) 2020 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 
17 #include "Ctrl.h"
18 
19 #include "families/Nl80211.h"
20 
21 #include <libnl++/Message.h>
22 
23 namespace android::nl::protocols::generic {
24 
25 using DataType = AttributeDefinition::DataType;
26 using Flags = AttributeDefinition::Flags;
27 
28 // clang-format off
Ctrl(Generic::FamilyRegister & familyRegister)29 Ctrl::Ctrl(Generic::FamilyRegister& familyRegister)
30     : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL",
31 {
32     {CTRL_CMD_NEWFAMILY, "NEWFAMILY"},
33     {CTRL_CMD_DELFAMILY, "DELFAMILY"},
34     {CTRL_CMD_GETFAMILY, "GETFAMILY"},
35     {CTRL_CMD_NEWOPS, "NEWOPS"},
36     {CTRL_CMD_DELOPS, "DELOPS"},
37     {CTRL_CMD_GETOPS, "GETOPS"},
38     {CTRL_CMD_NEWMCAST_GRP, "NEWMCAST_GRP"},
39     {CTRL_CMD_DELMCAST_GRP, "DELMCAST_GRP"},
40     {CTRL_CMD_GETMCAST_GRP, "GETMCAST_GRP"},
41 }, {
42     {CTRL_ATTR_FAMILY_ID, {"FAMILY_ID", DataType::Uint}},
43     {CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::StringNul}},
44     {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}},
45     {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}},
46     {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}},
47     {CTRL_ATTR_OPS, {"OPS", DataType::Nested, AttributeMap{
48         {std::nullopt, {"OP", DataType::Nested, AttributeMap{
49             {CTRL_ATTR_OP_ID, {"ID", DataType::Uint}},
50             {CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}},
51         }}},
52     }, Flags::Verbose}},
53     {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{
54         {std::nullopt, {"GRP", DataType::Nested, AttributeMap{
55             {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::StringNul}},
56             {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}},
57         }}},
58     }}},
59 }), mFamilyRegister(familyRegister) {}
60 // clang-format on
61 
track(const Buffer<nlmsghdr> hdr)62 void Ctrl::track(const Buffer<nlmsghdr> hdr) {
63     const auto msgMaybe = Message<genlmsghdr>::parse(hdr, {GENL_ID_CTRL});
64     if (!msgMaybe.has_value()) return;
65     const auto msg = *msgMaybe;
66 
67     if (msg->cmd != CTRL_CMD_NEWFAMILY) return;
68     const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
69     const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
70 
71     /* For now, we support just a single family. But if you add more, please define proper
72      * abstraction and not hardcode every name and class here.
73      */
74     if (familyName == "nl80211") {
75         mFamilyRegister[familyId] = std::make_shared<families::Nl80211>(familyId);
76     }
77 }
78 
79 }  // namespace android::nl::protocols::generic
80