blob: 34cb3e1aafd26faea7e4a93cf7e05815d3f7b540 [file] [log] [blame]
lhf4a45922022-02-17 22:08:54 -08001/* SPDX-License-Identifier: MediaTekProprietary */
xjb04a4022021-11-25 15:01:52 +08002
3#include <stdio.h>
4#include <stdlib.h>
5#include <stddef.h>
6#include <string.h>
7#include <errno.h>
8#include <assert.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <time.h>
12#include <sys/types.h>
13#include <sys/socket.h>
14#include <sys/un.h>
15#include <syslog.h>
16#include "utility.h"
17#include "request.h"
18
19/*******************************************************************************/
20/* REQUEST local definitions */
21/*******************************************************************************/
22
23/*******************************************************************************/
24/* REQUEST local prototypes */
25/*******************************************************************************/
26
27/*******************************************************************************/
28/* REQUEST local variables */
29/*******************************************************************************/
30
31/*******************************************************************************/
32/* REQUEST local functions */
33/*******************************************************************************/
34static int pack_request_string(char **p, char **next, const char *roof)
35{
36 if (*p == NULL) {
37 return 0;
38 } else {
39 size_t len = strlen(*p) + 1;
40
41 if ((roof - *next) < (ptrdiff_t)len) {
42 return -1;
43 } else {
44 strcpy(*next, *p);
45 *next += len;
46 *p = (char *)0x12345678;
47 return 0;
48 }
49 }
50}
51
52static int unpack_request_string(char **p, char **next, const char *roof)
53{
54 if (*p == NULL) {
55 return 0;
56 } else if (*p == (char *)0x12345678) {
57 char *end = memchr(*next, '\0', roof - *next);
58
59 if (end == NULL) {
60 return -1;
61 } else {
62 *p = *next;
63 *next = end + 1;
64 return 0;
65 }
66 }
67 return -1;
68}
69
70/*******************************************************************************/
71/* REQUEST functions */
72/*******************************************************************************/
73int pack_request(struct sncfg_request *request)
74{
75 int size;
76 char *next, *roof;
77
78 next = request->string + request->reservedLen;
79 roof = next + sizeof(request->string);
80
81 if (request->magic != SNCFG_REQUEST_MAGIC) {
82 return -1;
83 }
84
85 if (request->type >= SNCFG_REQUEST_TYPE_RESERVED) {
86 return -1;
87 }
88
89 if (pack_request_string(&request->key, &next, roof) < 0 ||
90 pack_request_string(&request->value, &next, roof) < 0) {
91 return -1;
92 }
93
94 size = next - (char *)request;
95 return size;
96}
97
98int unpack_request(struct sncfg_request *request, int size)
99{
100 char *next, *roof;
101
102 next = request->string + request->reservedLen;
103 roof = (char *)request + size;
104
105 if (roof < next) {
106 return -1;
107 }
108
109 if (request->magic != SNCFG_REQUEST_MAGIC) {
110 return -1;
111 }
112
113 if (request->type >= SNCFG_REQUEST_TYPE_RESERVED) {
114 return -1;
115 }
116
117 if (unpack_request_string(&request->key, &next, roof) < 0 ||
118 unpack_request_string(&request->value, &next, roof) < 0) {
119 return -1;
120 }
121
122 return 0;
123}
124
125int connect_request(void)
126{
127 int sock;
128 struct sockaddr_un addr = { AF_UNIX, SNCFG_REQUEST_UNIX_SOCKET };
129
130 if (access(addr.sun_path, R_OK | W_OK) < 0) {
131 return -1;
132 }
133
134 sock = socket(AF_UNIX, SOCK_STREAM, 0);
135 if (sock == -1) {
136 return -1;
137 }
138
139 struct timeval tm;
140 tm.tv_sec = 8; /* 8 Secs Timeout */
141 tm.tv_usec = 0;
142
143 if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
144 fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for connect ... %s !!\r\n", getpid(), strerror(errno));
145 syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for connect ... %s !!", getpid(), strerror(errno));
146 close(sock);
147 return -1;
148 }
149 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
150 fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for connect ... %s !!\r\n", getpid(), strerror(errno));
151 syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for connect ... %s !!", getpid(), strerror(errno));
152 close(sock);
153 return -1;
154 }
155
156 if (connect(sock, (struct sockaddr *)&addr,
157 offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) {
158 close(sock);
159 return -1;
160 }
161
162 return sock;
163}
164
165int accept_request(int sockfd)
166{
167 int sock;
168 socklen_t addrlen;
169 struct sockaddr_un addr;
170
171 addrlen = sizeof(addr);
172 sock = accept(sockfd, (struct sockaddr *)&addr, &addrlen);
173 if (sock == -1) {
174 return -1;
175 }
176
177 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
178 close(sock);
179 return -1;
180 }
181
182 struct timeval tm;
183 tm.tv_sec = 8; /* 8 Secs Timeout */
184 tm.tv_usec = 0;
185
186 if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
187 fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for accept ... %s !!\r\n", getpid(), strerror(errno));
188 syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for accept ... %s !!", getpid(), strerror(errno));
189 close(sock);
190 return -1;
191 }
192 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
193 fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for accept ... %s !!\r\n", getpid(), strerror(errno));
194 syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for accept ... %s !!", getpid(), strerror(errno));
195 close(sock);
196 return -1;
197 }
198
199 return sock;
200}
201
202int request_for_sncfg(struct sncfg_request *request)
203{
204 int sock, size;
205
206 size = pack_request(request);
207 if (size < 0) {
208 return -1;
209 }
210
211 sock = connect_request();
212 if (sock < 0) {
213 return -1;
214 }
215
216 if (safe_write(sock, request, size) != size) {
217 close(sock);
218 return -1;
219 }
220
221 size = safe_read(sock, request, sizeof(struct sncfg_request));
222
223 if (size < 0 ||
224 unpack_request(request, size) < 0 ||
225 request->status < 0) {
226 /* request processing failed */
227 close(sock);
228 return -1;
229 }
230
231 close(sock);
232 return 0;
233}