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 36 37 38

static int CreateSocket(struct ServiceSocket *sockopt)
{
    if (!sockopt || !sockopt->name) {
        return -1;
    }
S
sun_fan 已提交
39 40 41 42 43 44
    if (sockopt->sockFd >= 0) {
        close(sockopt->sockFd);
        sockopt->sockFd = -1;
    }
    sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0);
    if (sockopt->sockFd < 0) {
Z
zhong_ning 已提交
45
        INIT_LOGE("socket fail %d ", errno);
Z
zhong_ning 已提交
46 47 48 49 50 51
        return -1;
    }

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

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

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

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

S
sun_fan 已提交
95
static int SetSocketEnv(int fd, const char *name)
Z
zhong_ning 已提交
96
{
S
sun_fan 已提交
97 98 99 100 101 102
    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 已提交
103
        HOS_SOCKET_ENV_PREFIX"%s", name) < 0) {
S
sun_fan 已提交
104 105 106 107 108
        return -1;
    }
    if (snprintf_s(val, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) {
        return -1;
    }
Z
zhong_ning 已提交
109 110
    int ret = setenv(pubName, val, 1);
    if (ret < 0) {
Z
zhong_ning 已提交
111
        INIT_LOGE("setenv fail %d ", errno);
Z
zhong_ning 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
        return -1;
    }
    fcntl(fd, F_SETFD, 0);
    return 0;
}

int DoCreateSocket(struct ServiceSocket *sockopt)
{
    if (!sockopt) {
        return -1;
    }
    struct ServiceSocket *tmpSock = sockopt;
    while (tmpSock) {
        int fd = CreateSocket(tmpSock);
        if (fd < 0) {
            return -1;
        }
S
sun_fan 已提交
129 130 131
        if (tmpSock->name == NULL) {
            return -1;
        }
Z
zhong_ning 已提交
132 133 134 135 136 137 138 139 140
        int ret = SetSocketEnv(fd, tmpSock->name);
        if (ret < 0) {
            return -1;
        }
        tmpSock = tmpSock->next;
    }
    return 0;
}