blob: 177dba8c15db4d7570a2afa82660a959aa302d5c
1 | /* |
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 | |
17 | #include <stdio.h> |
18 | #include <errno.h> |
19 | #include <string.h> |
20 | |
21 | #include <sys/socket.h> |
22 | #include <sys/select.h> |
23 | #include <sys/time.h> |
24 | #include <sys/types.h> |
25 | #include <sys/un.h> |
26 | |
27 | #include <linux/netlink.h> |
28 | |
29 | #define LOG_TAG "droidVold" |
30 | |
31 | #include <cutils/log.h> |
32 | |
33 | #include "NetlinkManager.h" |
34 | #include "NetlinkHandler.h" |
35 | |
36 | NetlinkManager *NetlinkManager::sInstance = NULL; |
37 | |
38 | NetlinkManager *NetlinkManager::Instance() { |
39 | if (!sInstance) |
40 | sInstance = new NetlinkManager(); |
41 | return sInstance; |
42 | } |
43 | |
44 | NetlinkManager::NetlinkManager() { |
45 | mBroadcaster = NULL; |
46 | } |
47 | |
48 | NetlinkManager::~NetlinkManager() { |
49 | } |
50 | |
51 | int NetlinkManager::start() { |
52 | struct sockaddr_nl nladdr; |
53 | int sz = 64 * 1024; |
54 | int on = 1; |
55 | |
56 | memset(&nladdr, 0, sizeof(nladdr)); |
57 | nladdr.nl_family = AF_NETLINK; |
58 | nladdr.nl_pid = getpid(); |
59 | nladdr.nl_groups = 0xffffffff; |
60 | |
61 | if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, |
62 | NETLINK_KOBJECT_UEVENT)) < 0) { |
63 | SLOGE("Unable to create uevent socket: %s", strerror(errno)); |
64 | return -1; |
65 | } |
66 | |
67 | if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { |
68 | SLOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); |
69 | goto out; |
70 | } |
71 | |
72 | if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { |
73 | SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); |
74 | goto out; |
75 | } |
76 | |
77 | if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { |
78 | SLOGE("Unable to bind uevent socket: %s", strerror(errno)); |
79 | goto out; |
80 | } |
81 | |
82 | mHandler = new NetlinkHandler(mSock); |
83 | if (mHandler->start()) { |
84 | SLOGE("Unable to start NetlinkHandler: %s", strerror(errno)); |
85 | goto out; |
86 | } |
87 | |
88 | return 0; |
89 | |
90 | out: |
91 | close(mSock); |
92 | return -1; |
93 | } |
94 | |
95 | int NetlinkManager::stop() { |
96 | int status = 0; |
97 | |
98 | if (mHandler->stop()) { |
99 | SLOGE("Unable to stop NetlinkHandler: %s", strerror(errno)); |
100 | status = -1; |
101 | } |
102 | delete mHandler; |
103 | mHandler = NULL; |
104 | |
105 | close(mSock); |
106 | mSock = -1; |
107 | |
108 | return status; |
109 | } |
110 |