blob: 34cb3e1aafd26faea7e4a93cf7e05815d3f7b540 [file] [log] [blame]
/* SPDX-License-Identifier: MediaTekProprietary */
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <syslog.h>
#include "utility.h"
#include "request.h"
/*******************************************************************************/
/* REQUEST local definitions */
/*******************************************************************************/
/*******************************************************************************/
/* REQUEST local prototypes */
/*******************************************************************************/
/*******************************************************************************/
/* REQUEST local variables */
/*******************************************************************************/
/*******************************************************************************/
/* REQUEST local functions */
/*******************************************************************************/
static int pack_request_string(char **p, char **next, const char *roof)
{
if (*p == NULL) {
return 0;
} else {
size_t len = strlen(*p) + 1;
if ((roof - *next) < (ptrdiff_t)len) {
return -1;
} else {
strcpy(*next, *p);
*next += len;
*p = (char *)0x12345678;
return 0;
}
}
}
static int unpack_request_string(char **p, char **next, const char *roof)
{
if (*p == NULL) {
return 0;
} else if (*p == (char *)0x12345678) {
char *end = memchr(*next, '\0', roof - *next);
if (end == NULL) {
return -1;
} else {
*p = *next;
*next = end + 1;
return 0;
}
}
return -1;
}
/*******************************************************************************/
/* REQUEST functions */
/*******************************************************************************/
int pack_request(struct sncfg_request *request)
{
int size;
char *next, *roof;
next = request->string + request->reservedLen;
roof = next + sizeof(request->string);
if (request->magic != SNCFG_REQUEST_MAGIC) {
return -1;
}
if (request->type >= SNCFG_REQUEST_TYPE_RESERVED) {
return -1;
}
if (pack_request_string(&request->key, &next, roof) < 0 ||
pack_request_string(&request->value, &next, roof) < 0) {
return -1;
}
size = next - (char *)request;
return size;
}
int unpack_request(struct sncfg_request *request, int size)
{
char *next, *roof;
next = request->string + request->reservedLen;
roof = (char *)request + size;
if (roof < next) {
return -1;
}
if (request->magic != SNCFG_REQUEST_MAGIC) {
return -1;
}
if (request->type >= SNCFG_REQUEST_TYPE_RESERVED) {
return -1;
}
if (unpack_request_string(&request->key, &next, roof) < 0 ||
unpack_request_string(&request->value, &next, roof) < 0) {
return -1;
}
return 0;
}
int connect_request(void)
{
int sock;
struct sockaddr_un addr = { AF_UNIX, SNCFG_REQUEST_UNIX_SOCKET };
if (access(addr.sun_path, R_OK | W_OK) < 0) {
return -1;
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
return -1;
}
struct timeval tm;
tm.tv_sec = 8; /* 8 Secs Timeout */
tm.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for connect ... %s !!\r\n", getpid(), strerror(errno));
syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for connect ... %s !!", getpid(), strerror(errno));
close(sock);
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for connect ... %s !!\r\n", getpid(), strerror(errno));
syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for connect ... %s !!", getpid(), strerror(errno));
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *)&addr,
offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) {
close(sock);
return -1;
}
return sock;
}
int accept_request(int sockfd)
{
int sock;
socklen_t addrlen;
struct sockaddr_un addr;
addrlen = sizeof(addr);
sock = accept(sockfd, (struct sockaddr *)&addr, &addrlen);
if (sock == -1) {
return -1;
}
if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
close(sock);
return -1;
}
struct timeval tm;
tm.tv_sec = 8; /* 8 Secs Timeout */
tm.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for accept ... %s !!\r\n", getpid(), strerror(errno));
syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_SNDTIMEO 8 seconds for accept ... %s !!", getpid(), strerror(errno));
close(sock);
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const void *)&tm, sizeof(tm)) < 0) {
fprintf(stderr, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for accept ... %s !!\r\n", getpid(), strerror(errno));
syslog(LOG_WARNING, "[LIBSNCFG][%d] Can't setsockopt SO_RCVTIMEO 8 seconds for accept ... %s !!", getpid(), strerror(errno));
close(sock);
return -1;
}
return sock;
}
int request_for_sncfg(struct sncfg_request *request)
{
int sock, size;
size = pack_request(request);
if (size < 0) {
return -1;
}
sock = connect_request();
if (sock < 0) {
return -1;
}
if (safe_write(sock, request, size) != size) {
close(sock);
return -1;
}
size = safe_read(sock, request, sizeof(struct sncfg_request));
if (size < 0 ||
unpack_request(request, size) < 0 ||
request->status < 0) {
/* request processing failed */
close(sock);
return -1;
}
close(sock);
return 0;
}