/* vi: set sw=4 ts=4: */ /* * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> * * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. */ /* /etc/protocols # protocol-name number [aliases ...] ip 0 IP # internet protocol, pseudo protocol number protocol-name: case sensitive friendly name of the IP protocol number: decimal protocol number aliases: case sensitive optional space or tab separated list of other names */ #include <features.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <unistd.h> #include "internal/parse_config.h" #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); #define MINTOKENS 2 #define MAXALIASES 8 /* will probably never be more than one */ #define MAXTOKENS (MINTOKENS + MAXALIASES + 1) #define BUFSZ (255) /* one line */ #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) static parser_t *protop = NULL; static struct protoent protoe; static char *protobuf = NULL; static smallint proto_stayopen; void setprotoent(int stayopen) { __UCLIBC_MUTEX_LOCK(mylock); if (protop) config_close(protop); protop = config_open(_PATH_PROTOCOLS); if (stayopen) proto_stayopen = 1; __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(setprotoent) void endprotoent(void) { __UCLIBC_MUTEX_LOCK(mylock); if (protop) { config_close(protop); protop = NULL; } proto_stayopen = 0; __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(endprotoent) int getprotoent_r(struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { char **tok = NULL; const size_t aliaslen = sizeof(char *) * MAXTOKENS; int ret = ERANGE; *result = NULL; if (buflen < aliaslen || (buflen - aliaslen) < BUFSZ + 1) goto DONE_NOUNLOCK; __UCLIBC_MUTEX_LOCK(mylock); //tok = (char **) buf; ret = ENOENT; if (protop == NULL) setprotoent(proto_stayopen); if (protop == NULL) goto DONE; protop->data = buf; protop->data_len = aliaslen; protop->line_len = buflen - aliaslen; /* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */ if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { goto DONE; } result_buf->p_name = *(tok++); result_buf->p_proto = atoi(*(tok++)); result_buf->p_aliases = tok; *result = result_buf; ret = 0; DONE: __UCLIBC_MUTEX_UNLOCK(mylock); DONE_NOUNLOCK: errno = ret; return errno; } libc_hidden_def(getprotoent_r) static void __initbuf(void) { if (!protobuf) { protobuf = malloc(SBUFSIZE); if (!protobuf) abort(); } } struct protoent *getprotoent(void) { struct protoent *result; __initbuf(); getprotoent_r(&protoe, protobuf, SBUFSIZE, &result); return result; } int getprotobyname_r(const char *name, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { register char **cp; int ret; __UCLIBC_MUTEX_LOCK(mylock); setprotoent(proto_stayopen); while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { if (strcmp(name, result_buf->p_name) == 0) break; for (cp = result_buf->p_aliases; *cp; cp++) if (strcmp(name, *cp) == 0) goto gotname; } gotname: if (!proto_stayopen) endprotoent(); __UCLIBC_MUTEX_UNLOCK(mylock); return *result ? 0 : ret; } libc_hidden_def(getprotobyname_r) struct protoent *getprotobyname(const char *name) { struct protoent *result; __initbuf(); getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result); return result; } int getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { int ret; __UCLIBC_MUTEX_LOCK(mylock); setprotoent(proto_stayopen); while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { if (proto == result_buf->p_proto) break; } if (!proto_stayopen) endprotoent(); __UCLIBC_MUTEX_UNLOCK(mylock); return *result ? 0 : ret; } libc_hidden_def(getprotobynumber_r) struct protoent *getprotobynumber(int proto) { struct protoent *result; __initbuf(); getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result); return result; }