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