9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

_p9dialparse.c (3441B)


      1 #include <u.h>
      2 #define NOPLAN9DEFINES
      3 #include <libc.h>
      4 
      5 #include <sys/types.h>
      6 #include <netdb.h>
      7 #include <sys/un.h>
      8 #include <netinet/in.h>
      9 
     10 static char *nets[] = { "tcp", "udp", nil };
     11 #define CLASS(p) ((*(uchar*)(p))>>6)
     12 
     13 static struct {
     14 	char *net;
     15 	char *service;
     16 	int port;
     17 } porttbl[] = {
     18 	"tcp",	"9fs",	564,
     19 	"tcp",	"whoami",	565,
     20 	"tcp",	"guard",	566,
     21 	"tcp",	"ticket",	567,
     22 	"tcp",	"exportfs",	17007,
     23 	"tcp",	"rexexec",	17009,
     24 	"tcp",	"ncpu",	17010,
     25 	"tcp",	"cpu",	17013,
     26 	"tcp",	"venti",	17034,
     27 	"tcp",	"wiki",	17035,
     28 	"tcp",	"secstore",	5356,
     29 	"udp",	"dns",	53,
     30 	"tcp",	"dns",	53,
     31 };
     32 
     33 static int
     34 parseip(char *host, u32int *pip)
     35 {
     36 	uchar addr[4];
     37 	int x, i;
     38 	char *p;
     39 
     40 	p = host;
     41 	for(i=0; i<4 && *p; i++){
     42 		x = strtoul(p, &p, 0);
     43 		if(x < 0 || x >= 256)
     44 			return -1;
     45 		if(*p != '.' && *p != 0)
     46 			return -1;
     47 		if(*p == '.')
     48 			p++;
     49 		addr[i] = x;
     50 	}
     51 
     52 	switch(CLASS(addr)){
     53 	case 0:
     54 	case 1:
     55 		if(i == 3){
     56 			addr[3] = addr[2];
     57 			addr[2] = addr[1];
     58 			addr[1] = 0;
     59 		}else if(i == 2){
     60 			addr[3] = addr[1];
     61 			addr[2] = 0;
     62 			addr[1] = 0;
     63 		}else if(i != 4)
     64 			return -1;
     65 		break;
     66 	case 2:
     67 		if(i == 3){
     68 			addr[3] = addr[2];
     69 			addr[2] = 0;
     70 		}else if(i != 4)
     71 			return -1;
     72 		break;
     73 	}
     74 	memmove(pip, addr, 4);
     75 	return 0;
     76 }
     77 
     78 int
     79 p9dialparse(char *addr, char **pnet, char **punix, u32int *phost, int *pport)
     80 {
     81 	char *net, *host, *port, *e;
     82 	int i;
     83 	struct servent *se;
     84 	struct hostent *he;
     85 	struct sockaddr_un *sockun;
     86 
     87 	*punix = nil;
     88 	net = addr;
     89 	if((host = strchr(net, '!')) == nil){
     90 		werrstr("malformed address");
     91 		return -1;
     92 	}
     93 	*host++ = 0;
     94 	if((port = strchr(host, '!')) == nil){
     95 		if(strcmp(net, "unix")==0 || strcmp(net, "net")==0){
     96 		Unix:
     97 			if(strlen(host)+1 > sizeof sockun->sun_path){
     98 				werrstr("unix socket name too long");
     99 				return -1;
    100 			}
    101 			*punix = host;
    102 			*pnet = "unix";
    103 			*phost = 0;
    104 			*pport = 0;
    105 			return 0;
    106 		}
    107 		werrstr("malformed address");
    108 		return -1;
    109 	}
    110 	*port++ = 0;
    111 
    112 	if(*host == 0){
    113 		werrstr("malformed address (empty host)");
    114 		return -1;
    115 	}
    116 	if(*port == 0){
    117 		werrstr("malformed address (empty port)");
    118 		return -1;
    119 	}
    120 
    121 	if(strcmp(net, "unix") == 0)
    122 		goto Unix;
    123 
    124 	if(strcmp(net, "tcp")!=0 && strcmp(net, "udp")!=0 && strcmp(net, "net") != 0){
    125 		werrstr("bad network %s!%s!%s", net, host, port);
    126 		return -1;
    127 	}
    128 
    129 	/* translate host */
    130 	if(strcmp(host, "*") == 0)
    131 		*phost = 0;
    132 	else if(parseip(host, phost) == 0)
    133 		{}
    134 	else if((he = gethostbyname(host)) != nil)
    135 		*phost = *(u32int*)(he->h_addr);
    136 	else{
    137 		werrstr("unknown host %s", host);
    138 		return -1;
    139 	}
    140 
    141 	/* translate network and port; should return list rather than first */
    142 	if(strcmp(net, "net") == 0){
    143 		for(i=0; nets[i]; i++){
    144 			if((se = getservbyname(port, nets[i])) != nil){
    145 				*pnet = nets[i];
    146 				*pport = ntohs(se->s_port);
    147 				return 0;
    148 			}
    149 		}
    150 	}
    151 
    152 	for(i=0; i<nelem(porttbl); i++){
    153 		if(strcmp(net, "net") == 0 || strcmp(porttbl[i].net, net) == 0)
    154 		if(strcmp(porttbl[i].service, port) == 0){
    155 			*pnet = porttbl[i].net;
    156 			*pport = porttbl[i].port;
    157 			return 0;
    158 		}
    159 	}
    160 
    161 	if(strcmp(net, "net") == 0){
    162 		werrstr("unknown service net!*!%s", port);
    163 		return -1;
    164 	}
    165 
    166 	if(strcmp(net, "tcp") != 0 && strcmp(net, "udp") != 0){
    167 		werrstr("unknown network %s", net);
    168 		return -1;
    169 	}
    170 
    171 	*pnet = net;
    172 	i = strtol(port, &e, 0);
    173 	if(*e == 0){
    174 		*pport = i;
    175 		return 0;
    176 	}
    177 
    178 	if((se = getservbyname(port, net)) != nil){
    179 		*pport = ntohs(se->s_port);
    180 		return 0;
    181 	}
    182 	werrstr("unknown service %s!*!%s", net, port);
    183 	return -1;
    184 }