1570af302Sopenharmony_ci#include <sys/socket.h>
2570af302Sopenharmony_ci#include <fcntl.h>
3570af302Sopenharmony_ci#include <errno.h>
4570af302Sopenharmony_ci#include <dlfcn.h>
5570af302Sopenharmony_ci#include <stdint.h>
6570af302Sopenharmony_ci#include <stddef.h>
7570af302Sopenharmony_ci#include "syscall.h"
8570af302Sopenharmony_ci#ifdef OHOS_FDTRACK_HOOK_ENABLE
9570af302Sopenharmony_ci#include "musl_fdtrack_hook.h"
10570af302Sopenharmony_ci#endif
11570af302Sopenharmony_ci
12570af302Sopenharmony_ci#if OHOS_PERMISSION_INTERNET
13570af302Sopenharmony_citypedef uint8_t (*AllowFunc)(void);
14570af302Sopenharmony_cistatic const char *LIB_NETSYS_CLIENT_NAME = "libnetsys_client.z.so";
15570af302Sopenharmony_cistatic const char *ALLOW_SOCKET_FUNC_NAME = "IsAllowInternet";
16570af302Sopenharmony_ci
17570af302Sopenharmony_ci/*
18570af302Sopenharmony_ci * Read a flag from netsys_client, there is only one place to set this flag, is the
19570af302Sopenharmony_ci * founction named DoStartup in startup_appspawn.
20570af302Sopenharmony_ci * */
21570af302Sopenharmony_ciuint8_t is_allow_internet(void)
22570af302Sopenharmony_ci{
23570af302Sopenharmony_ci	static uint8_t first_time = 1;
24570af302Sopenharmony_ci	static uint8_t allow = 1;
25570af302Sopenharmony_ci
26570af302Sopenharmony_ci	if (!first_time) {
27570af302Sopenharmony_ci		return allow;
28570af302Sopenharmony_ci	}
29570af302Sopenharmony_ci
30570af302Sopenharmony_ci	void *handler = dlopen(LIB_NETSYS_CLIENT_NAME, RTLD_LAZY);
31570af302Sopenharmony_ci	if (handler != NULL) {
32570af302Sopenharmony_ci		AllowFunc func = (AllowFunc)dlsym(handler, ALLOW_SOCKET_FUNC_NAME);
33570af302Sopenharmony_ci		if (func != NULL && func() == 0) {
34570af302Sopenharmony_ci			allow = 0;
35570af302Sopenharmony_ci		}
36570af302Sopenharmony_ci		dlclose(handler);
37570af302Sopenharmony_ci	}
38570af302Sopenharmony_ci	first_time = 0;
39570af302Sopenharmony_ci	return allow;
40570af302Sopenharmony_ci}
41570af302Sopenharmony_ci#endif
42570af302Sopenharmony_ci
43570af302Sopenharmony_ci#ifdef OHOS_SOCKET_HOOK_ENABLE
44570af302Sopenharmony_ciint __libc_socket(int domain, int type, int protocol)
45570af302Sopenharmony_ci#else
46570af302Sopenharmony_ciint socket(int domain, int type, int protocol)
47570af302Sopenharmony_ci#endif
48570af302Sopenharmony_ci{
49570af302Sopenharmony_ci#if OHOS_PERMISSION_INTERNET
50570af302Sopenharmony_ci	if ((domain == AF_INET || domain == AF_INET6) && is_allow_internet() == 0) {
51570af302Sopenharmony_ci		errno = EPERM;
52570af302Sopenharmony_ci		return -1;
53570af302Sopenharmony_ci	}
54570af302Sopenharmony_ci#endif
55570af302Sopenharmony_ci
56570af302Sopenharmony_ci	int s = __socketcall(socket, domain, type, protocol, 0, 0, 0);
57570af302Sopenharmony_ci	if ((s==-EINVAL || s==-EPROTONOSUPPORT)
58570af302Sopenharmony_ci	    && (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
59570af302Sopenharmony_ci		s = __socketcall(socket, domain,
60570af302Sopenharmony_ci			type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
61570af302Sopenharmony_ci			protocol, 0, 0, 0);
62570af302Sopenharmony_ci		if (s < 0) return __syscall_ret(s);
63570af302Sopenharmony_ci		if (type & SOCK_CLOEXEC)
64570af302Sopenharmony_ci			__syscall(SYS_fcntl, s, F_SETFD, FD_CLOEXEC);
65570af302Sopenharmony_ci		if (type & SOCK_NONBLOCK)
66570af302Sopenharmony_ci			__syscall(SYS_fcntl, s, F_SETFL, O_NONBLOCK);
67570af302Sopenharmony_ci	}
68570af302Sopenharmony_ci#ifdef OHOS_FDTRACK_HOOK_ENABLE
69570af302Sopenharmony_ci	return FDTRACK_START_HOOK(__syscall_ret(s));
70570af302Sopenharmony_ci#endif
71570af302Sopenharmony_ci	return __syscall_ret(s);
72570af302Sopenharmony_ci}
73