1 /*
2  * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
3  *
4  * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
5  */
6 
7 /* /etc/protocols
8 #   protocol-name   number   [aliases ...]
9 ip                  0        IP  # internet protocol, pseudo protocol number
10 
11 protocol-name: case sensitive friendly name of the IP protocol
12 number: decimal protocol number
13 aliases: case sensitive optional space or tab separated list of other names
14 */
15 
16 #include <features.h>
17 #include <netdb.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include "internal/parse_config.h"
25 
26 #include <bits/uClibc_mutex.h>
27 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
28 
29 #define MINTOKENS	2
30 #define	MAXALIASES	8 /* will probably never be more than one */
31 #define MAXTOKENS	(MINTOKENS + MAXALIASES + 1)
32 #define BUFSZ		(255) /* one line */
33 #define SBUFSIZE	(BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
34 
35 static parser_t *protop = NULL;
36 static struct protoent protoe;
37 static char *protobuf = NULL;
38 static smallint proto_stayopen;
39 
setprotoent(int stayopen)40 void setprotoent(int stayopen)
41 {
42 	__UCLIBC_MUTEX_LOCK(mylock);
43 	if (protop)
44 		config_close(protop);
45 	protop = config_open(_PATH_PROTOCOLS);
46 	if (stayopen)
47 		proto_stayopen = 1;
48 	__UCLIBC_MUTEX_UNLOCK(mylock);
49 }
libc_hidden_def(setprotoent)50 libc_hidden_def(setprotoent)
51 
52 void endprotoent(void)
53 {
54 	__UCLIBC_MUTEX_LOCK(mylock);
55 	if (protop) {
56 		config_close(protop);
57 		protop = NULL;
58 	}
59 	proto_stayopen = 0;
60 	__UCLIBC_MUTEX_UNLOCK(mylock);
61 }
libc_hidden_def(endprotoent)62 libc_hidden_def(endprotoent)
63 
64 int getprotoent_r(struct protoent *result_buf,
65 				 char *buf, size_t buflen, struct protoent **result)
66 {
67 	char **tok = NULL;
68 	const size_t aliaslen = sizeof(char *) * MAXTOKENS;
69 	int ret = ERANGE;
70 
71 	*result = NULL;
72 	if (buflen < aliaslen
73 		|| (buflen - aliaslen) < BUFSZ + 1)
74 		goto DONE_NOUNLOCK;
75 
76 	__UCLIBC_MUTEX_LOCK(mylock);
77 	//tok = (char **) buf;
78 	ret = ENOENT;
79 	if (protop == NULL)
80 		setprotoent(proto_stayopen);
81 	if (protop == NULL)
82 		goto DONE;
83 	protop->data = buf;
84 	protop->data_len = aliaslen;
85 	protop->line_len = buflen - aliaslen;
86 	/* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */
87 	if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
88 		goto DONE;
89 	}
90 	result_buf->p_name = *(tok++);
91 	result_buf->p_proto = atoi(*(tok++));
92 	result_buf->p_aliases = tok;
93 	*result = result_buf;
94 	ret = 0;
95  DONE:
96 	__UCLIBC_MUTEX_UNLOCK(mylock);
97  DONE_NOUNLOCK:
98 	errno = ret;
99 	return errno;
100 }
libc_hidden_def(getprotoent_r)101 libc_hidden_def(getprotoent_r)
102 
103 static void __initbuf(void)
104 {
105 	if (!protobuf) {
106 		protobuf = malloc(SBUFSIZE);
107 		if (!protobuf)
108 			abort();
109 	}
110 }
111 
getprotoent(void)112 struct protoent *getprotoent(void)
113 {
114 	struct protoent *result;
115 
116 	__initbuf();
117 	getprotoent_r(&protoe, protobuf, SBUFSIZE, &result);
118 	return result;
119 }
120 
getprotobyname_r(const char * name,struct protoent * result_buf,char * buf,size_t buflen,struct protoent ** result)121 int getprotobyname_r(const char *name,
122 					struct protoent *result_buf, char *buf, size_t buflen,
123 					struct protoent **result)
124 {
125 	register char **cp;
126 	int ret;
127 
128 	__UCLIBC_MUTEX_LOCK(mylock);
129 	setprotoent(proto_stayopen);
130 	while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) {
131 		if (strcmp(name, result_buf->p_name) == 0)
132 			break;
133 		for (cp = result_buf->p_aliases; *cp; cp++)
134 			if (strcmp(name, *cp) == 0)
135 				goto gotname;
136 	}
137  gotname:
138 	if (!proto_stayopen)
139 		endprotoent();
140 	__UCLIBC_MUTEX_UNLOCK(mylock);
141 	return *result ? 0 : ret;
142 }
libc_hidden_def(getprotobyname_r)143 libc_hidden_def(getprotobyname_r)
144 
145 struct protoent *getprotobyname(const char *name)
146 {
147 	struct protoent *result;
148 
149 	__initbuf();
150 	getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result);
151 	return result;
152 }
153 
getprotobynumber_r(int proto,struct protoent * result_buf,char * buf,size_t buflen,struct protoent ** result)154 int getprotobynumber_r(int proto,
155 					struct protoent *result_buf, char *buf,
156 					size_t buflen, struct protoent **result)
157 {
158 	int ret;
159 
160 	__UCLIBC_MUTEX_LOCK(mylock);
161 	setprotoent(proto_stayopen);
162 	while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) {
163 		if (proto == result_buf->p_proto)
164 			break;
165 	}
166 	if (!proto_stayopen)
167 		endprotoent();
168 	__UCLIBC_MUTEX_UNLOCK(mylock);
169 	return *result ? 0 : ret;
170 }
libc_hidden_def(getprotobynumber_r)171 libc_hidden_def(getprotobynumber_r)
172 
173 struct protoent *getprotobynumber(int proto)
174 {
175 	struct protoent *result;
176 
177 	__initbuf();
178 	getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result);
179 	return result;
180 }
181 
182