boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

lookup_serv.c (2413B)


      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[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 }