1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi/native_api.h"
17 #include <cerrno>
18 #include <cstring>
19 #include <ifaddrs.h>
20 #include <js_native_api_types.h>
21 #include <net/if.h>
22 #include <netdb.h>
23 #include <sys/inotify.h>
24 #include <uv.h>
25 
26 #define PARAM_0 0
27 #define PARAM_1 1
28 #define PARAM_2 2
29 #define PARAM_8192 8192
30 #define PARAM_UNNORMAL (-1)
31 #define ERRON_0 0
32 #define ONEVAL 1
33 #define MINUSONE (-1)
34 #define MINUSTWO (-2)
35 #define MINUSTHR (-3)
36 #define MAX_NAMBER 1024
37 #define PARAM_4 4
38 #define NO_ERR 0
39 #define SUCCESS 1
40 #define FAIL (-1)
41 #define TRUE 1
42 #define LENGTH 64
43 #define EIGHTY 80
44 #define BUFLEN 256
45 #define FLAG 127
46 
GetProtoEnt(napi_env env, napi_callback_info info)47 static napi_value GetProtoEnt(napi_env env, napi_callback_info info)
48 {
49     struct protoent *getInfo = nullptr;
50     getInfo = getprotoent();
51     int ret = FAIL;
52     if (getInfo != nullptr) {
53         ret = SUCCESS;
54     }
55     napi_value result = nullptr;
56     napi_create_int32(env, ret, &result);
57     return result;
58 }
GetProtoByName(napi_env env, napi_callback_info info)59 static napi_value GetProtoByName(napi_env env, napi_callback_info info)
60 {
61     size_t argc = PARAM_1;
62     napi_value args[1] = {nullptr};
63     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
64 
65     size_t length = LENGTH, strResult = PARAM_0;
66     char proto_name[LENGTH] = {0};
67 
68     napi_get_value_string_utf8(env, args[0], proto_name, length, &strResult);
69     struct protoent *getInfo = nullptr;
70     getInfo = getprotobyname(proto_name);
71     napi_value result = nullptr;
72     if (getInfo != nullptr) {
73         napi_create_string_utf8(env, getInfo->p_name, NAPI_AUTO_LENGTH, &result);
74     } else {
75         napi_create_string_utf8(env, "null", NAPI_AUTO_LENGTH, &result);
76     }
77     return result;
78 }
Hstrerror(napi_env env, napi_callback_info info)79 static napi_value Hstrerror(napi_env env, napi_callback_info info)
80 {
81     const char *ret = hstrerror(PARAM_1);
82     napi_value result;
83     if (strcmp(ret, "Unknown error nnn")) {
84         napi_create_int32(env, PARAM_0, &result);
85     } else {
86         napi_create_int32(env, PARAM_UNNORMAL, &result);
87     }
88     return result;
89 }
90 
Herror(napi_env env, napi_callback_info info)91 static napi_value Herror(napi_env env, napi_callback_info info)
92 {
93     errno = ERRON_0;
94     herror("herror");
95     napi_value result;
96     if (errno == ERRON_0) {
97         napi_create_int32(env, PARAM_0, &result);
98     } else {
99         napi_create_int32(env, PARAM_UNNORMAL, &result);
100     }
101     return result;
102 }
103 
GetProtoByNumber(napi_env env, napi_callback_info info)104 static napi_value GetProtoByNumber(napi_env env, napi_callback_info info)
105 {
106     size_t argc = PARAM_1;
107     napi_value args[1] = {nullptr};
108     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
109 
110     int valueZero = PARAM_0;
111     napi_get_value_int32(env, args[0], &valueZero);
112     struct protoent *getInfo = nullptr;
113     getInfo = getprotobynumber(valueZero);
114     napi_value result = nullptr;
115     if (getInfo != nullptr) {
116         napi_create_string_utf8(env, getInfo->p_name, NAPI_AUTO_LENGTH, &result);
117     } else {
118         napi_create_string_utf8(env, "null", NAPI_AUTO_LENGTH, &result);
119     }
120     return result;
121 }
GetNameInfo(napi_env env, napi_callback_info info)122 static napi_value GetNameInfo(napi_env env, napi_callback_info info)
123 {
124     char hostname[128] = {PARAM_0};
125     char serverName[128] = {PARAM_0};
126     sockaddr_in addR_dst = {PARAM_0};
127     memset(&addR_dst, PARAM_0, sizeof(addR_dst));
128     addR_dst.sin_family = AF_INET;
129     inet_pton(AF_INET, "127.0.0.1", &addR_dst.sin_addr.s_addr);
130     int getInfo = getnameinfo((sockaddr *)&addR_dst, sizeof(addR_dst), hostname, sizeof(hostname), serverName,
131                               sizeof(serverName), PARAM_0);
132     napi_value result = nullptr;
133     napi_create_int32(env, getInfo, &result);
134     return result;
135 }
GetHostEnt(napi_env env, napi_callback_info info)136 static napi_value GetHostEnt(napi_env env, napi_callback_info info)
137 {
138     hostent *getInfo = nullptr;
139     sethostent(TRUE);
140     getInfo = gethostent();
141     int ret = FAIL;
142     if (getInfo == nullptr) {
143         ret = SUCCESS;
144     }
145     endhostent();
146     napi_value result = nullptr;
147     napi_create_int32(env, ret, &result);
148     return result;
149 }
GetServEnt(napi_env env, napi_callback_info info)150 static napi_value GetServEnt(napi_env env, napi_callback_info info)
151 {
152     errno = NO_ERR;
153     setservent(TRUE);
154     int ret = FAIL;
155     getservent();
156     if (errno == NO_ERR) {
157         ret = SUCCESS;
158     }
159     napi_value result = nullptr;
160     napi_create_int32(env, ret, &result);
161     return result;
162 }
GetNetEnt(napi_env env, napi_callback_info info)163 static napi_value GetNetEnt(napi_env env, napi_callback_info info)
164 {
165     netent *getInfo = nullptr;
166     getInfo = getnetent();
167     int ret = FAIL;
168     if (getInfo == nullptr) {
169         ret = SUCCESS;
170     }
171     napi_value result = nullptr;
172     napi_create_int32(env, ret, &result);
173     return result;
174 }
GetNetByAddr(napi_env env, napi_callback_info info)175 static napi_value GetNetByAddr(napi_env env, napi_callback_info info)
176 {
177     netent *getInfo = nullptr;
178     errno = NO_ERR;
179     getInfo = getnetbyaddr(FLAG, AF_INET);
180     int ret = FAIL;
181     if (getInfo != nullptr) {
182         ret = SUCCESS;
183     }
184     napi_value result = nullptr;
185     napi_create_int32(env, ret, &result);
186     return result;
187 }
GetNetByName(napi_env env, napi_callback_info info)188 static napi_value GetNetByName(napi_env env, napi_callback_info info)
189 {
190     netent *getInfo = nullptr;
191     errno = NO_ERR;
192     getInfo = getnetbyname("loopback");
193     int ret = FAIL;
194     if (getInfo != nullptr) {
195         ret = SUCCESS;
196     }
197     napi_value result = nullptr;
198     napi_create_int32(env, ret, &result);
199     return result;
200 }
GetServByName(napi_env env, napi_callback_info info)201 static napi_value GetServByName(napi_env env, napi_callback_info info)
202 {
203     servent *getInfo = nullptr;
204     errno = NO_ERR;
205     getInfo = getservbyname("http", "tcp");
206     int ret = FAIL;
207     if (getInfo != nullptr) {
208         ret = SUCCESS;
209     }
210     napi_value result = nullptr;
211     napi_create_int32(env, ret, &result);
212     return result;
213 }
GetServByPort(napi_env env, napi_callback_info info)214 static napi_value GetServByPort(napi_env env, napi_callback_info info)
215 {
216     servent *getInfo = nullptr;
217     errno = NO_ERR;
218     getInfo = getservbyport(htons(EIGHTY), "tcp");
219     int ret = FAIL;
220     if (getInfo != nullptr) {
221         ret = SUCCESS;
222     }
223     napi_value result = nullptr;
224     napi_create_int32(env, ret, &result);
225     return result;
226 }
GetHostByName(napi_env env, napi_callback_info info)227 static napi_value GetHostByName(napi_env env, napi_callback_info info)
228 {
229     hostent *getInfo = nullptr;
230     errno = NO_ERR;
231     getInfo = gethostbyname("127.0.0.1");
232     int ret = FAIL;
233     if (getInfo != nullptr) {
234         ret = SUCCESS;
235     }
236     napi_value result = nullptr;
237     napi_create_int32(env, ret, &result);
238     return result;
239 }
GetHostByAddr(napi_env env, napi_callback_info info)240 static napi_value GetHostByAddr(napi_env env, napi_callback_info info)
241 {
242     hostent *getInfo = nullptr;
243     errno = NO_ERR;
244     const char *add = "127.0.0.1";
245     in_addr addr = {PARAM_0};
246     inet_pton(AF_INET, add, &addr);
247     getInfo = gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET);
248     int ret = FAIL;
249     if (getInfo != nullptr) {
250         ret = SUCCESS;
251     }
252     napi_value result = nullptr;
253     napi_create_int32(env, ret, &result);
254     return result;
255 }
GetHostByNameR(napi_env env, napi_callback_info info)256 static napi_value GetHostByNameR(napi_env env, napi_callback_info info)
257 {
258     int getInfo;
259     errno = NO_ERR;
260     char buf[1024] = "\0";
261     hostent hostInfo;
262     hostent *pHost = nullptr;
263     int type;
264     getInfo = gethostbyname_r("127.0.0.1", &hostInfo, buf, sizeof(buf), &pHost, &type);
265     napi_value result = nullptr;
266     napi_create_int32(env, getInfo, &result);
267     return result;
268 }
GetHostByAddrR(napi_env env, napi_callback_info info)269 static napi_value GetHostByAddrR(napi_env env, napi_callback_info info)
270 {
271     int getInfo;
272     errno = NO_ERR;
273     in_addr_t address = inet_addr("127.0.0.1");
274     hostent hostBuf;
275     hostent *hostResult = nullptr;
276     char buffer[2048];
277     int errNum = PARAM_0;
278     getInfo = gethostbyaddr_r(&address, PARAM_4, AF_INET, &hostBuf, buffer, sizeof(buffer), &hostResult, &errNum);
279     napi_value result = nullptr;
280     napi_create_int32(env, getInfo, &result);
281     return result;
282 }
GetHostByName2(napi_env env, napi_callback_info info)283 static napi_value GetHostByName2(napi_env env, napi_callback_info info)
284 {
285     hostent *getInfo = nullptr;
286     errno = NO_ERR;
287     getInfo = gethostbyname2("127.0.0.1", AF_INET);
288     int ret = FAIL;
289     if (getInfo != nullptr) {
290         ret = SUCCESS;
291     }
292     napi_value result = nullptr;
293     napi_create_int32(env, ret, &result);
294     return result;
295 }
296 
GetHostByName2R(napi_env env, napi_callback_info info)297 static napi_value GetHostByName2R(napi_env env, napi_callback_info info)
298 {
299     int getInfo;
300     errno = NO_ERR;
301     int err;
302     int buf_len = PARAM_8192;
303     hostent hBuf;
304     hostent *ret = nullptr;
305     char buf[buf_len];
306     memset(buf, PARAM_0, buf_len);
307     getInfo = gethostbyname2_r("127.0.0.1", AF_INET, &hBuf, buf, buf_len, &ret, &err);
308     napi_value result = nullptr;
309     napi_create_int32(env, getInfo, &result);
310     return result;
311 }
Sethostent(napi_env env, napi_callback_info info)312 static napi_value Sethostent(napi_env env, napi_callback_info info)
313 {
314     errno = ERRON_0;
315     sethostent(ONEVAL);
316     gethostent();
317     endhostent();
318     napi_value result;
319     napi_create_int32(env, errno, &result);
320     return result;
321 }
322 
Setnetent(napi_env env, napi_callback_info info)323 static napi_value Setnetent(napi_env env, napi_callback_info info)
324 {
325     errno = ERRON_0;
326     const char *netname = nullptr;
327     napi_value result = nullptr;
328     netent *ne = nullptr;
329     setnetent(ONEVAL);
330     while (ONEVAL) {
331         ne = getnetent();
332         if (!ne)
333             break;
334         if (strcmp(ne->n_name, netname) == PARAM_0) {
335             setnetent(PARAM_0);
336             endnetent();
337             napi_create_int32(env, ONEVAL, &result);
338             return result;
339         }
340     }
341     setnetent(PARAM_0);
342     endnetent();
343     napi_create_int32(env, errno, &result);
344     return result;
345 }
346 
Setprotoent(napi_env env, napi_callback_info info)347 static napi_value Setprotoent(napi_env env, napi_callback_info info)
348 {
349     errno = ERRON_0;
350     endprotoent();
351     napi_value result = nullptr;
352     protoent *getval = getprotoent();
353     if (getval == nullptr) {
354         napi_create_int32(env, MINUSONE, &result);
355     }
356     char buf[MAX_NAMBER] = {PARAM_0};
357     strcpy(buf, getval->p_name);
358     setprotoent(PARAM_0);
359     getval = getprotoent();
360     if (getval == nullptr) {
361         napi_create_int32(env, MINUSTWO, &result);
362     }
363     if (strcmp(getval->p_name, buf)) {
364         napi_create_int32(env, MINUSTHR, &result);
365     } else {
366         napi_create_int32(env, errno, &result);
367     }
368     return result;
369 }
370 
Setservent(napi_env env, napi_callback_info info)371 static napi_value Setservent(napi_env env, napi_callback_info info)
372 {
373     errno = ERRON_0;
374     char **p = nullptr;
375     struct servent *serv = nullptr;
376     napi_value result;
377     setservent(ONEVAL);
378     while ((serv = getservent()) != nullptr) {
379         for (p = serv->s_aliases; *p != nullptr; p++)
380             ;
381     }
382     endservent();
383     if (errno == PARAM_0) {
384         napi_create_int32(env, errno, &result);
385     } else {
386         napi_create_int32(env, MINUSONE, &result);
387     }
388     return result;
389 }
390 
EndServEnt(napi_env env, napi_callback_info info)391 static napi_value EndServEnt(napi_env env, napi_callback_info info)
392 {
393     errno = NO_ERR;
394     endservent();
395     napi_value result = nullptr;
396     napi_create_int32(env, errno, &result);
397     return result;
398 }
399 
EndProToEnt(napi_env env, napi_callback_info info)400 static napi_value EndProToEnt(napi_env env, napi_callback_info info)
401 {
402     errno = NO_ERR;
403     endprotoent();
404     napi_value result = nullptr;
405     napi_create_int32(env, errno, &result);
406     return result;
407 }
408 
EndNetEnt(napi_env env, napi_callback_info info)409 static napi_value EndNetEnt(napi_env env, napi_callback_info info)
410 {
411     errno = NO_ERR;
412     endnetent();
413     napi_value result = nullptr;
414     napi_create_int32(env, errno, &result);
415     return result;
416 }
417 
EndHostEnt(napi_env env, napi_callback_info info)418 static napi_value EndHostEnt(napi_env env, napi_callback_info info)
419 {
420     errno = NO_ERR;
421     endhostent();
422     napi_value result = nullptr;
423     napi_create_int32(env, errno, &result);
424     return result;
425 }
426 
GaiStrerror(napi_env env, napi_callback_info info)427 napi_value GaiStrerror(napi_env env, napi_callback_info info)
428 {
429     const char *value = gai_strerror(EAI_BADFLAGS);
430     int ret = FAIL;
431     if (value != nullptr) {
432         ret = SUCCESS;
433     }
434     napi_value result = nullptr;
435     napi_create_int32(env, ret, &result);
436     return result;
437 }
Freeaddrinfo(napi_env env, napi_callback_info info)438 napi_value Freeaddrinfo(napi_env env, napi_callback_info info)
439 {
440     struct addrinfo *ai, hint;
441     hint.ai_flags = AI_PASSIVE;
442     hint.ai_family = AF_UNSPEC;
443     getaddrinfo("127.0.0.1", nullptr, &hint, &ai);
444     errno = NO_ERR;
445     try{
446         freeaddrinfo(ai);
447     }
448     catch(...)
449     {
450         errno = FAIL;
451     }
452     napi_value result = nullptr;
453     napi_create_int32(env, errno, &result);
454     return result;
455 }
456 
Getaddrinfo(napi_env env, napi_callback_info info)457 napi_value Getaddrinfo(napi_env env, napi_callback_info info)
458 {
459     struct addrinfo hint, *ai;
460     hint.ai_flags = AI_PASSIVE;
461     hint.ai_family = AF_UNSPEC;
462     int ret = getaddrinfo("127.0.0.1", nullptr, &hint, &ai);
463     freeaddrinfo(ai);
464     napi_value result = nullptr;
465     napi_create_int32(env, ret, &result);
466     return result;
467 }
468 EXTERN_C_START
Init(napi_env env, napi_value exports)469 static napi_value Init(napi_env env, napi_value exports)
470 {
471     napi_property_descriptor desc[] = {
472         {"hstrerror", nullptr, Hstrerror, nullptr, nullptr, nullptr, napi_default, nullptr},
473         {"herror", nullptr, Herror, nullptr, nullptr, nullptr, napi_default, nullptr},
474         {"getProtoEnt", nullptr, GetProtoEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
475         {"getProtoByName", nullptr, GetProtoByName, nullptr, nullptr, nullptr, napi_default, nullptr},
476         {"getProtoByNumber", nullptr, GetProtoByNumber, nullptr, nullptr, nullptr, napi_default, nullptr},
477         {"getNameInfo", nullptr, GetNameInfo, nullptr, nullptr, nullptr, napi_default, nullptr},
478         {"getHostEnt", nullptr, GetHostEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
479         {"getServEnt", nullptr, GetServEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
480         {"getNetEnt", nullptr, GetNetEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
481         {"getNetByAddr", nullptr, GetNetByAddr, nullptr, nullptr, nullptr, napi_default, nullptr},
482         {"getNetByName", nullptr, GetNetByName, nullptr, nullptr, nullptr, napi_default, nullptr},
483         {"getServByName", nullptr, GetServByName, nullptr, nullptr, nullptr, napi_default, nullptr},
484         {"getServByPort", nullptr, GetServByPort, nullptr, nullptr, nullptr, napi_default, nullptr},
485         {"getHostByName", nullptr, GetHostByName, nullptr, nullptr, nullptr, napi_default, nullptr},
486         {"getHostByAddr", nullptr, GetHostByAddr, nullptr, nullptr, nullptr, napi_default, nullptr},
487         {"getHostByNameR", nullptr, GetHostByNameR, nullptr, nullptr, nullptr, napi_default, nullptr},
488         {"getHostByAddrR", nullptr, GetHostByAddrR, nullptr, nullptr, nullptr, napi_default, nullptr},
489         {"getHostByName2", nullptr, GetHostByName2, nullptr, nullptr, nullptr, napi_default, nullptr},
490         {"getHostByName2R", nullptr, GetHostByName2R, nullptr, nullptr, nullptr, napi_default, nullptr},
491         {"sethostent", nullptr, Sethostent, nullptr, nullptr, nullptr, napi_default, nullptr},
492         {"setnetent", nullptr, Setnetent, nullptr, nullptr, nullptr, napi_default, nullptr},
493         {"setprotoent", nullptr, Setprotoent, nullptr, nullptr, nullptr, napi_default, nullptr},
494         {"setservent", nullptr, Setservent, nullptr, nullptr, nullptr, napi_default, nullptr},
495         {"endservent", nullptr, EndServEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
496         {"endprotoent", nullptr, EndProToEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
497         {"endnetent", nullptr, EndNetEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
498         {"endhostent", nullptr, EndHostEnt, nullptr, nullptr, nullptr, napi_default, nullptr},
499         {"gaiStrerror", nullptr, GaiStrerror, nullptr, nullptr, nullptr, napi_default, nullptr},
500         {"freeaddrinfo", nullptr, Freeaddrinfo, nullptr, nullptr, nullptr, napi_default, nullptr},
501         {"getaddrinfo", nullptr, Getaddrinfo, nullptr, nullptr, nullptr, napi_default, nullptr}};
502     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
503     return exports;
504 }
505 EXTERN_C_END
506 
507 static napi_module demoModule = {
508     .nm_version = 1,
509     .nm_flags = 0,
510     .nm_filename = nullptr,
511     .nm_register_func = Init,
512     .nm_modname = "netdb",
513     .nm_priv = ((void *)0),
514     .reserved = {0},
515 };
516 
RegisterModule(void)517 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }
518