xref: /aosp_15_r20/external/musl/src/network/lookup_serv.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
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