Tizen 2.0 Release
[framework/appfw/shortcut.git] / src / secom_socket.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <arpa/inet.h>
25 #include <sys/un.h>
26 #include <netinet/in.h>
27 #include <errno.h>
28
29 #include <secom_socket.h>
30 #include <dlog.h>
31
32
33
34 extern int errno;
35
36
37
38 inline static
39 int create_socket(const char *peer, struct sockaddr_un *addr)
40 {
41         int len;
42         int handle;
43
44         len = sizeof(struct sockaddr_un);
45         bzero(addr, len);
46
47         if (strlen(peer) >= sizeof(addr->sun_path)) {
48                 LOGE("peer %s is too long to remember it\\n", peer);
49                 return -1;
50         }
51
52         // We can believe this has no prob, because 
53         // we already check the size of add.rsun_path
54         strcpy(addr->sun_path, peer);
55         addr->sun_family = AF_UNIX;
56
57         handle = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
58         if (handle < 0) {
59                 LOGE("Failed to create a socket %s\n", strerror(errno));
60                 return -1;
61         }
62
63         return handle;
64 }
65
66
67
68 int secom_create_client(const char *peer)
69 {
70         struct sockaddr_un addr;
71         int handle;
72         int state;
73         int on = 1;
74
75         handle = create_socket(peer, &addr);
76         if (handle < 0)
77                 return handle;
78
79         state = connect(handle, (struct sockaddr*)&addr, sizeof(addr));
80         if (state < 0) {
81                 LOGE("Failed to connect to server [%s] %s\n", peer, strerror(errno));
82                 if (close(handle) < 0)
83                         LOGE("Failed to close a handle\n");
84
85                 return -1;
86         }
87
88         if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0)
89                 LOGE("Failed to change sock opt : %s\n", strerror(errno));
90
91         return handle;
92 }
93
94
95
96 int secom_create_server(const char *peer)
97 {
98         int handle;
99         int state;
100         struct sockaddr_un addr;
101
102         handle = create_socket(peer, &addr);
103         if (handle < 0) return handle;
104
105         state = bind(handle, &addr, sizeof(addr));
106         if (state < 0) {
107                 LOGE("Failed to bind a socket %s\n", strerror(errno));
108                 if (close(handle) < 0) {
109                         LOGE("Failed to close a handle\n");
110                 }
111                 return -1;
112         }
113
114         state = listen(handle, 5);
115         if (state < 0) {
116                 LOGE("Failed to listen a socket %s\n", strerror(errno));
117                 if (close(handle) < 0) {
118                         LOGE("Failed to close a handle\n");
119                 }
120                 return -1;
121         }
122
123         if (chmod(peer, 0666) < 0) {
124                 LOGE("Failed to change the permission of a socket (%s)\n", strerror(errno));
125         }
126
127         return handle;
128 }
129
130
131
132 int secom_get_connection_handle(int server_handle)
133 {
134         struct sockaddr_un addr;
135         int handle;
136         int on = 1;
137         socklen_t size = sizeof(addr);
138
139         handle = accept(server_handle, (struct sockaddr*)&addr, &size);
140         if (handle < 0) {
141                 LOGE("Failed to accept a new client %s\n", strerror(errno));
142                 return -1;
143         }
144
145         if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
146                 LOGE("Failed to change sock opt : %s\n", strerror(errno));
147         }
148
149         return handle;
150 }
151
152
153
154 int secom_put_connection_handle(int conn_handle)
155 {
156         if (close(conn_handle) < 0) {
157                 LOGE("Failed to close a handle\n");
158                 return -1;
159         }
160         return 0;
161 }
162
163
164
165 int secom_send(int handle, const char *buffer, int size)
166 {
167         struct msghdr msg;
168         struct iovec iov;
169         int ret;
170
171         memset(&msg, 0, sizeof(msg));
172         iov.iov_base = (char*)buffer;
173         iov.iov_len = size;
174         msg.msg_iov = &iov;
175         msg.msg_iovlen = 1;
176
177         ret = sendmsg(handle, &msg, 0);
178         if (ret < 0) {
179                 LOGE("Failed to send message [%s]\n", strerror(errno));
180                 return -1;
181         }
182         LOGD("Send done: %d\n", ret);
183
184         return iov.iov_len;
185 }
186
187
188
189 int secom_recv(int handle, char *buffer, int size, int *sender_pid)
190 {
191         struct msghdr msg;
192         struct cmsghdr *cmsg;
193         struct iovec iov;
194         int _pid;
195         int ret;
196         char control[1024];
197
198         if (!sender_pid) sender_pid = &_pid;
199         *sender_pid = -1;
200
201         memset(&msg, 0, sizeof(msg));
202         iov.iov_base = buffer;
203         iov.iov_len = size;
204         msg.msg_iov = &iov;
205         msg.msg_iovlen = 1;
206         msg.msg_control = control;
207         msg.msg_controllen = sizeof(control);
208
209         ret = recvmsg(handle, &msg, 0);
210         if (ret < 0) {
211                 LOGE("Failed to recvmsg [%s] (%d)\n", strerror(errno), ret);
212                 return -1;
213         }
214
215         cmsg = CMSG_FIRSTHDR(&msg);
216         while (cmsg) {
217                 if (cmsg->cmsg_level == SOL_SOCKET
218                         && cmsg->cmsg_type == SCM_CREDENTIALS)
219                 {
220                         struct ucred *cred;
221                         cred = (struct ucred*)CMSG_DATA(cmsg);
222                         *sender_pid = cred->pid;
223                 }
224
225                 cmsg = CMSG_NXTHDR(&msg, cmsg);
226         }
227
228         return iov.iov_len;
229 }
230
231
232
233 int secom_destroy(int handle)
234 {
235         if (close(handle) < 0) {
236                 LOGE("Failed to close a handle\n");
237                 return -1;
238         }
239         return 0;
240 }
241
242
243
244 #undef _GNU_SOURCE
245 // End of a file