1 /*
2  * Copyright 2019, 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 #pragma once
18 
19 #include "result.h"
20 
21 struct nl_cb;
22 struct nl_msg;
23 struct nl_sock;
24 struct nlmsgerr;
25 struct sockaddr_nl;
26 
27 class NetlinkMessage;
28 
29 class NetlinkSocket {
30 public:
31     NetlinkSocket();
32     ~NetlinkSocket();
33 
34     Result init();
35 
36     /* Set the size of the receive buffer to |rxBufferSize| bytes and the
37      * transmit buffer to |txBufferSize| bytes.
38      */
39     Result setBufferSizes(int rxBufferSize, int txBufferSize);
40 
41     Result setOnMsgInCallback(int (*callback)(struct nl_msg*, void*),
42                               void* context);
43     Result setOnMsgOutCallback(int (*callback)(struct nl_msg*, void*),
44                               void* context);
45     Result setOnSeqCheckCallback(int (*callback)(struct nl_msg*, void*),
46                                  void* context);
47     Result setOnAckCallback(int (*callback)(struct nl_msg*, void*),
48                             void* context);
49     Result setOnErrorCallback(int (*callback)(struct sockaddr_nl*,
50                                               struct nlmsgerr*,
51                                               void*),
52                               void* context);
53 
54     /* Connect socket to generic netlink. This needs to be done before generic
55      * netlink messages can be sent. After this is done the caller should use
56      * @resolveGenericNetlinkFamily to determine the generic family id to use.
57      * Then create NetlinkMessage's with that family id.
58      */
59     Result connectGeneric();
60 
61     /* Resolve a generic family name to a family identifier. This is used when
62      * sending generic netlink messages to indicate where the message should go.
63      * Examples of family names are "mac80211_hwsim" or "nl80211".
64      */
65     int resolveNetlinkFamily(const char* familyName);
66 
67     /* Send a netlink message on this socket. */
68     bool send(NetlinkMessage& message);
69 
70     /* Receive all pending message. This method does not return any messages,
71      * instead they will be provided through the callback set with
72      * setOnMsgInCallback. This callback will be called on the same thread as
73      * this method while this method is running. */
74     bool receive();
75 
76     int getFd() const;
77 
78 private:
79     struct nl_cb* mCallback = nullptr;
80     struct nl_sock* mSocket = nullptr;
81 };
82 
83