1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "netlink/netlink_manager.h"
17 
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <iostream>
21 #include <sys/socket.h>
22 #include <unistd.h>
23 #include <linux/netlink.h>
24 
25 #include "securec.h"
26 #include "storage_service_errno.h"
27 #include "storage_service_log.h"
28 
29 namespace OHOS {
30 namespace StorageDaemon {
31 NetlinkManager* NetlinkManager::instance_ = nullptr;
32 
Instance()33 NetlinkManager* NetlinkManager::Instance()
34 {
35     if (instance_ == nullptr) {
36         instance_ = new NetlinkManager();
37     }
38 
39     return instance_;
40 }
41 
Start()42 int32_t NetlinkManager::Start()
43 {
44     struct sockaddr_nl addr;
45     int32_t bufferSize = 256 * ONE_KB;
46     int32_t passCred = 1;
47 
48     (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
49     addr.nl_family = AF_NETLINK;
50     addr.nl_pid = static_cast<uint32_t>(getprocpid());
51     addr.nl_groups = 0xffffffff;
52 
53     socketFd_ = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
54     if (socketFd_ < 0) {
55         LOGE("Create netlink socket failed, errno %{public}d", errno);
56         return E_ERR;
57     }
58 
59     if (setsockopt(socketFd_, SOL_SOCKET, SO_RCVBUFFORCE, &bufferSize, sizeof(bufferSize)) != 0) {
60         LOGE("Set SO_RCVBUFFORCE failed, errno %{public}d", errno);
61         (void)close(socketFd_);
62         return E_ERR;
63     }
64 
65     if (setsockopt(socketFd_, SOL_SOCKET, SO_PASSCRED, &passCred, sizeof(passCred)) != 0) {
66         LOGE("Set SO_PASSCRED failed, errno %{public}d", errno);
67         (void)close(socketFd_);
68         return E_ERR;
69     }
70 
71     if (bind(socketFd_, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) != 0) {
72         LOGE("Socket bind failed, errno %{public}d", errno);
73         (void)close(socketFd_);
74         return E_ERR;
75     }
76 
77     nlHandler_ = new NetlinkHandler(socketFd_);
78     if (nlHandler_->Start()) {
79         (void)close(socketFd_);
80         return E_ERR;
81     }
82     return E_OK;
83 }
84 
Stop()85 int32_t NetlinkManager::Stop()
86 {
87     int32_t ret = 0;
88     if (nlHandler_ != nullptr) {
89         if (nlHandler_->Stop()) {
90             ret = E_ERR;
91         }
92         delete nlHandler_;
93     }
94     nlHandler_ = nullptr;
95     (void)close(socketFd_);
96     socketFd_ = -1;
97 
98     return ret;
99 }
100 } // StorageDaemon
101 } // OHOS
102