2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Rafal Krypa <r.krypa@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 * @file connection.cpp
20 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21 * @author Lukasz Kostyra (l.kostyra@samsung.com)
23 * @brief This file is implementation of common connection functions.
26 #include "connection.h"
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <sys/smack.h>
33 #include <sys/xattr.h>
34 #include <linux/xattr.h>
37 #include <dpl/log/log.h>
38 #include <dpl/serialization.h>
40 #include <message-buffer.h>
42 #include <protocols.h>
46 const int POLL_TIMEOUT = -1;
48 int waitForSocket(int sock, int event, int timeout) {
52 desc[0].events = event;
54 while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
60 LogDebug("Poll timeout");
61 } else if (-1 == retval) {
63 LogError("Error in poll: " << strerror(err));
79 int Connect(char const * const interface) {
80 sockaddr_un clientAddr;
83 if (m_sock != -1) // guard
86 m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
89 LogError("Error creating socket: " << strerror(err));
90 return SECURITY_MANAGER_API_ERROR_SOCKET;
93 if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
94 fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
97 LogError("Error in fcntl: " << strerror(err));
98 return SECURITY_MANAGER_API_ERROR_SOCKET;
101 memset(&clientAddr, 0, sizeof(clientAddr));
103 clientAddr.sun_family = AF_UNIX;
105 if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
106 LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
107 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
110 strcpy(clientAddr.sun_path, interface);
112 LogDebug("ClientAddr.sun_path = " << interface);
114 int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
115 if ((retval == -1) && (errno == EINPROGRESS)) {
116 if (0 >= waitForSocket(m_sock, POLLIN, POLL_TIMEOUT)) {
117 LogError("Error in waitForSocket.");
118 return SECURITY_MANAGER_API_ERROR_SOCKET;
121 socklen_t len = sizeof(error);
122 retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len);
126 LogError("Error in getsockopt: " << strerror(err));
127 return SECURITY_MANAGER_API_ERROR_SOCKET;
130 if (error == EACCES) {
131 LogError("Access denied");
132 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
136 LogError("Error in connect: " << strerror(error));
137 return SECURITY_MANAGER_API_ERROR_SOCKET;
140 return SECURITY_MANAGER_API_SUCCESS;
145 LogError("Error connecting socket: " << strerror(err));
147 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
149 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
150 return SECURITY_MANAGER_API_ERROR_SOCKET;
153 return SECURITY_MANAGER_API_SUCCESS;
164 } // namespace anonymous
166 namespace SecurityManager {
168 int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
174 if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
175 LogError("Error in SockRAII");
179 while ((send.size() - done) > 0) {
180 if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
181 LogError("Error in poll(POLLOUT)");
182 return SECURITY_MANAGER_API_ERROR_SOCKET;
184 ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
187 LogError("Error in write: " << strerror(err));
188 return SECURITY_MANAGER_API_ERROR_SOCKET;
194 if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
195 LogError("Error in poll(POLLIN)");
196 return SECURITY_MANAGER_API_ERROR_SOCKET;
198 ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
201 LogError("Error in read: " << strerror(err));
202 return SECURITY_MANAGER_API_ERROR_SOCKET;
206 LogError("Read return 0/Connection closed by server(?)");
207 return SECURITY_MANAGER_API_ERROR_SOCKET;
210 RawBuffer raw(buffer, buffer+temp);
212 } while(!recv.Ready());
213 return SECURITY_MANAGER_API_SUCCESS;
216 int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) {
221 if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
222 LogError("Error in SockRAII");
226 while ((send.size() - done) > 0) {
227 if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
228 LogError("Error in poll(POLLOUT)");
229 return SECURITY_MANAGER_API_ERROR_SOCKET;
231 ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
234 LogError("Error in write: " << strerror(err));
235 return SECURITY_MANAGER_API_ERROR_SOCKET;
240 if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
241 LogError("Error in poll(POLLIN)");
242 return SECURITY_MANAGER_API_ERROR_SOCKET;
245 ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC));
249 LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err);
250 return SECURITY_MANAGER_API_ERROR_SOCKET;
254 LogError("Read return 0/Connection closed by server(?)");
255 return SECURITY_MANAGER_API_ERROR_SOCKET;
258 return SECURITY_MANAGER_API_SUCCESS;
261 } // namespace SecurityManager