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