lookup_serv.c raw

   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  
  12  int __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  }
 115