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