init_service_socket.c 3.9 KB
Newer Older
Z
zhong_ning 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "init_service_socket.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/un.h>
Z
zhong_ning 已提交
26
#include "init_log.h"
S
sun_fan 已提交
27
#include "securec.h"
Z
zhong_ning 已提交
28 29 30

#define HOS_SOCKET_DIR    "/dev/unix/socket"
#define HOS_SOCKET_ENV_PREFIX    "OHOS_SOCKET_"
S
sun_fan 已提交
31 32
#define MAX_SOCKET_ENV_PREFIX_LEN 64
#define MAX_SOCKET_FD_LEN 16
Z
zhong_ning 已提交
33 34 35

static int CreateSocket(struct ServiceSocket *sockopt)
{
S
sun_fan 已提交
36
    if (sockopt == NULL || sockopt->name == NULL) {
Z
zhong_ning 已提交
37 38
        return -1;
    }
S
sun_fan 已提交
39 40 41 42 43
    if (sockopt->sockFd >= 0) {
        close(sockopt->sockFd);
        sockopt->sockFd = -1;
    }
    sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0);
S
sun_fan 已提交
44
    INIT_ERROR_CHECK(sockopt->sockFd >= 0, return -1, "socket fail %d ", errno);
Z
zhong_ning 已提交
45 46

    struct sockaddr_un addr;
S
sun_fan 已提交
47
    bzero(&addr, sizeof(addr));
Z
zhong_ning 已提交
48
    addr.sun_family = AF_UNIX;
S
sun_fan 已提交
49
    if (snprintf_s(addr.sun_path, sizeof(addr.sun_path), sizeof(addr.sun_path) - 1, HOS_SOCKET_DIR"/%s",
Z
zhong_ning 已提交
50
        sockopt->name) < 0) {
S
sun_fan 已提交
51 52
        return -1;
    }
Z
zhong_ning 已提交
53
    if (access(addr.sun_path, F_OK)) {
Z
zhong_ning 已提交
54
        INIT_LOGE("%s already exist, remove it", addr.sun_path);
S
sun_fan 已提交
55
        if (unlink(addr.sun_path) != 0) {
Z
zhong_ning 已提交
56
            INIT_LOGE("ulink fail err %d ", errno);
S
sun_fan 已提交
57
        }
Z
zhong_ning 已提交
58 59 60
    }
    if (sockopt->passcred) {
        int on = 1;
S
sun_fan 已提交
61
        if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
Z
zhong_ning 已提交
62
            unlink(addr.sun_path);
S
sun_fan 已提交
63
            close(sockopt->sockFd);
Z
zhong_ning 已提交
64 65 66 67
            return -1;
        }
    }

S
sun_fan 已提交
68
    if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) {
Z
zhong_ning 已提交
69
        INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno);
Z
zhong_ning 已提交
70
        unlink(addr.sun_path);
S
sun_fan 已提交
71
        close(sockopt->sockFd);
Z
zhong_ning 已提交
72 73
        return -1;
    }
Z
zhong_ning 已提交
74

Z
zhong_ning 已提交
75 76
    if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) {
        unlink(addr.sun_path);
S
sun_fan 已提交
77
        close(sockopt->sockFd);
Z
zhong_ning 已提交
78
        INIT_LOGE("lchown fail %d ", errno);
Z
zhong_ning 已提交
79 80 81 82 83
        return -1;
    }

    if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) {
        unlink(addr.sun_path);
S
sun_fan 已提交
84
        close(sockopt->sockFd);
Z
zhong_ning 已提交
85
        INIT_LOGE("fchmodat fail %d ", errno);
Z
zhong_ning 已提交
86 87
        return -1;
    }
Z
zhong_ning 已提交
88
    INIT_LOGI("CreateSocket success ");
S
sun_fan 已提交
89
    return sockopt->sockFd;
Z
zhong_ning 已提交
90 91
}

S
sun_fan 已提交
92
static int SetSocketEnv(int fd, const char *name)
Z
zhong_ning 已提交
93
{
S
sun_fan 已提交
94 95 96 97 98 99
    if (name == NULL) {
        return -1;
    }
    char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = {0};
    char val[MAX_SOCKET_FD_LEN] = {0};
    if (snprintf_s(pubName, MAX_SOCKET_ENV_PREFIX_LEN, MAX_SOCKET_ENV_PREFIX_LEN - 1,
Z
zhong_ning 已提交
100
        HOS_SOCKET_ENV_PREFIX"%s", name) < 0) {
S
sun_fan 已提交
101 102 103 104 105
        return -1;
    }
    if (snprintf_s(val, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) {
        return -1;
    }
Z
zhong_ning 已提交
106 107
    int ret = setenv(pubName, val, 1);
    if (ret < 0) {
Z
zhong_ning 已提交
108
        INIT_LOGE("setenv fail %d ", errno);
Z
zhong_ning 已提交
109 110 111 112 113 114 115 116
        return -1;
    }
    fcntl(fd, F_SETFD, 0);
    return 0;
}

int DoCreateSocket(struct ServiceSocket *sockopt)
{
S
sun_fan 已提交
117
    if (sockopt == NULL) {
Z
zhong_ning 已提交
118 119 120
        return -1;
    }
    struct ServiceSocket *tmpSock = sockopt;
S
sun_fan 已提交
121
    while (tmpSock != NULL) {
Z
zhong_ning 已提交
122 123 124 125
        int fd = CreateSocket(tmpSock);
        if (fd < 0) {
            return -1;
        }
S
sun_fan 已提交
126 127 128
        if (tmpSock->name == NULL) {
            return -1;
        }
Z
zhong_ning 已提交
129 130 131 132 133 134 135 136 137
        int ret = SetSocketEnv(fd, tmpSock->name);
        if (ret < 0) {
            return -1;
        }
        tmpSock = tmpSock->next;
    }
    return 0;
}