1*c9945492SAndroid Build Coastguard Worker #include <sys/socket.h>
2*c9945492SAndroid Build Coastguard Worker #include <netinet/in.h>
3*c9945492SAndroid Build Coastguard Worker #include <netdb.h>
4*c9945492SAndroid Build Coastguard Worker #include <ctype.h>
5*c9945492SAndroid Build Coastguard Worker #include <string.h>
6*c9945492SAndroid Build Coastguard Worker #include <stdlib.h>
7*c9945492SAndroid Build Coastguard Worker #include <fcntl.h>
8*c9945492SAndroid Build Coastguard Worker #include <errno.h>
9*c9945492SAndroid Build Coastguard Worker #include "lookup.h"
10*c9945492SAndroid Build Coastguard Worker #include "stdio_impl.h"
11*c9945492SAndroid Build Coastguard Worker
__lookup_serv(struct service buf[static MAXSERVS],const char * name,int proto,int socktype,int flags)12*c9945492SAndroid Build Coastguard Worker int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int socktype, int flags)
13*c9945492SAndroid Build Coastguard Worker {
14*c9945492SAndroid Build Coastguard Worker char line[128];
15*c9945492SAndroid Build Coastguard Worker int cnt = 0;
16*c9945492SAndroid Build Coastguard Worker char *p, *z = "";
17*c9945492SAndroid Build Coastguard Worker unsigned long port = 0;
18*c9945492SAndroid Build Coastguard Worker
19*c9945492SAndroid Build Coastguard Worker switch (socktype) {
20*c9945492SAndroid Build Coastguard Worker case SOCK_STREAM:
21*c9945492SAndroid Build Coastguard Worker switch (proto) {
22*c9945492SAndroid Build Coastguard Worker case 0:
23*c9945492SAndroid Build Coastguard Worker proto = IPPROTO_TCP;
24*c9945492SAndroid Build Coastguard Worker case IPPROTO_TCP:
25*c9945492SAndroid Build Coastguard Worker break;
26*c9945492SAndroid Build Coastguard Worker default:
27*c9945492SAndroid Build Coastguard Worker return EAI_SERVICE;
28*c9945492SAndroid Build Coastguard Worker }
29*c9945492SAndroid Build Coastguard Worker break;
30*c9945492SAndroid Build Coastguard Worker case SOCK_DGRAM:
31*c9945492SAndroid Build Coastguard Worker switch (proto) {
32*c9945492SAndroid Build Coastguard Worker case 0:
33*c9945492SAndroid Build Coastguard Worker proto = IPPROTO_UDP;
34*c9945492SAndroid Build Coastguard Worker case IPPROTO_UDP:
35*c9945492SAndroid Build Coastguard Worker break;
36*c9945492SAndroid Build Coastguard Worker default:
37*c9945492SAndroid Build Coastguard Worker return EAI_SERVICE;
38*c9945492SAndroid Build Coastguard Worker }
39*c9945492SAndroid Build Coastguard Worker case 0:
40*c9945492SAndroid Build Coastguard Worker break;
41*c9945492SAndroid Build Coastguard Worker default:
42*c9945492SAndroid Build Coastguard Worker if (name) return EAI_SERVICE;
43*c9945492SAndroid Build Coastguard Worker buf[0].port = 0;
44*c9945492SAndroid Build Coastguard Worker buf[0].proto = proto;
45*c9945492SAndroid Build Coastguard Worker buf[0].socktype = socktype;
46*c9945492SAndroid Build Coastguard Worker return 1;
47*c9945492SAndroid Build Coastguard Worker }
48*c9945492SAndroid Build Coastguard Worker
49*c9945492SAndroid Build Coastguard Worker if (name) {
50*c9945492SAndroid Build Coastguard Worker if (!*name) return EAI_SERVICE;
51*c9945492SAndroid Build Coastguard Worker port = strtoul(name, &z, 10);
52*c9945492SAndroid Build Coastguard Worker }
53*c9945492SAndroid Build Coastguard Worker if (!*z) {
54*c9945492SAndroid Build Coastguard Worker if (port > 65535) return EAI_SERVICE;
55*c9945492SAndroid Build Coastguard Worker if (proto != IPPROTO_UDP) {
56*c9945492SAndroid Build Coastguard Worker buf[cnt].port = port;
57*c9945492SAndroid Build Coastguard Worker buf[cnt].socktype = SOCK_STREAM;
58*c9945492SAndroid Build Coastguard Worker buf[cnt++].proto = IPPROTO_TCP;
59*c9945492SAndroid Build Coastguard Worker }
60*c9945492SAndroid Build Coastguard Worker if (proto != IPPROTO_TCP) {
61*c9945492SAndroid Build Coastguard Worker buf[cnt].port = port;
62*c9945492SAndroid Build Coastguard Worker buf[cnt].socktype = SOCK_DGRAM;
63*c9945492SAndroid Build Coastguard Worker buf[cnt++].proto = IPPROTO_UDP;
64*c9945492SAndroid Build Coastguard Worker }
65*c9945492SAndroid Build Coastguard Worker return cnt;
66*c9945492SAndroid Build Coastguard Worker }
67*c9945492SAndroid Build Coastguard Worker
68*c9945492SAndroid Build Coastguard Worker if (flags & AI_NUMERICSERV) return EAI_NONAME;
69*c9945492SAndroid Build Coastguard Worker
70*c9945492SAndroid Build Coastguard Worker size_t l = strlen(name);
71*c9945492SAndroid Build Coastguard Worker
72*c9945492SAndroid Build Coastguard Worker unsigned char _buf[1032];
73*c9945492SAndroid Build Coastguard Worker FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf);
74*c9945492SAndroid Build Coastguard Worker if (!f) switch (errno) {
75*c9945492SAndroid Build Coastguard Worker case ENOENT:
76*c9945492SAndroid Build Coastguard Worker case ENOTDIR:
77*c9945492SAndroid Build Coastguard Worker case EACCES:
78*c9945492SAndroid Build Coastguard Worker return EAI_SERVICE;
79*c9945492SAndroid Build Coastguard Worker default:
80*c9945492SAndroid Build Coastguard Worker return EAI_SYSTEM;
81*c9945492SAndroid Build Coastguard Worker }
82*c9945492SAndroid Build Coastguard Worker
83*c9945492SAndroid Build Coastguard Worker while (fgets(line, sizeof line, f) && cnt < MAXSERVS) {
84*c9945492SAndroid Build Coastguard Worker if ((p=strchr(line, '#'))) *p++='\n', *p=0;
85*c9945492SAndroid Build Coastguard Worker
86*c9945492SAndroid Build Coastguard Worker /* Find service name */
87*c9945492SAndroid Build Coastguard Worker for(p=line; (p=strstr(p, name)); p++) {
88*c9945492SAndroid Build Coastguard Worker if (p>line && !isspace(p[-1])) continue;
89*c9945492SAndroid Build Coastguard Worker if (p[l] && !isspace(p[l])) continue;
90*c9945492SAndroid Build Coastguard Worker break;
91*c9945492SAndroid Build Coastguard Worker }
92*c9945492SAndroid Build Coastguard Worker if (!p) continue;
93*c9945492SAndroid Build Coastguard Worker
94*c9945492SAndroid Build Coastguard Worker /* Skip past canonical name at beginning of line */
95*c9945492SAndroid Build Coastguard Worker for (p=line; *p && !isspace(*p); p++);
96*c9945492SAndroid Build Coastguard Worker
97*c9945492SAndroid Build Coastguard Worker port = strtoul(p, &z, 10);
98*c9945492SAndroid Build Coastguard Worker if (port > 65535 || z==p) continue;
99*c9945492SAndroid Build Coastguard Worker if (!strncmp(z, "/udp", 4)) {
100*c9945492SAndroid Build Coastguard Worker if (proto == IPPROTO_TCP) continue;
101*c9945492SAndroid Build Coastguard Worker buf[cnt].port = port;
102*c9945492SAndroid Build Coastguard Worker buf[cnt].socktype = SOCK_DGRAM;
103*c9945492SAndroid Build Coastguard Worker buf[cnt++].proto = IPPROTO_UDP;
104*c9945492SAndroid Build Coastguard Worker }
105*c9945492SAndroid Build Coastguard Worker if (!strncmp(z, "/tcp", 4)) {
106*c9945492SAndroid Build Coastguard Worker if (proto == IPPROTO_UDP) continue;
107*c9945492SAndroid Build Coastguard Worker buf[cnt].port = port;
108*c9945492SAndroid Build Coastguard Worker buf[cnt].socktype = SOCK_STREAM;
109*c9945492SAndroid Build Coastguard Worker buf[cnt++].proto = IPPROTO_TCP;
110*c9945492SAndroid Build Coastguard Worker }
111*c9945492SAndroid Build Coastguard Worker }
112*c9945492SAndroid Build Coastguard Worker __fclose_ca(f);
113*c9945492SAndroid Build Coastguard Worker return cnt > 0 ? cnt : EAI_SERVICE;
114*c9945492SAndroid Build Coastguard Worker }
115