inet_pton.c 1.4 KB
Newer Older
R
Rich Felker 已提交
1 2 3 4 5
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
6 7 8 9 10 11 12 13 14
#include <string.h>

static int hexval(unsigned c)
{
	if (c-'0'<10) return c-'0';
	c |= 32;
	if (c-'a'<6) return c-'a'+10;
	return -1;
}
R
Rich Felker 已提交
15

16
int inet_pton(int af, const char *restrict s, void *restrict a0)
R
Rich Felker 已提交
17
{
18
	uint16_t ip[8];
R
Rich Felker 已提交
19
	unsigned char *a = a0;
20
	int i, j, v, d, brk=-1, need_v4=0;
R
Rich Felker 已提交
21 22

	if (af==AF_INET) {
S
Szabolcs Nagy 已提交
23 24 25 26 27 28 29 30
		for (i=0; i<4; i++) {
			for (v=j=0; j<3 && isdigit(s[j]); j++)
				v = 10*v + s[j]-'0';
			if (j==0 || (j>1 && s[0]=='0') || v>255) return 0;
			a[i] = v;
			if (s[j]==0 && i==3) return 1;
			if (s[j]!='.') return 0;
			s += j+1;
R
Rich Felker 已提交
31
		}
S
Szabolcs Nagy 已提交
32
		return 0;
33 34 35
	} else if (af!=AF_INET6) {
		errno = EAFNOSUPPORT;
		return -1;
R
Rich Felker 已提交
36 37
	}

S
Szabolcs Nagy 已提交
38
	if (*s==':' && *++s!=':') return 0;
39

S
Szabolcs Nagy 已提交
40
	for (i=0; ; i++) {
41 42 43
		if (s[0]==':' && brk<0) {
			brk=i;
			ip[i]=0;
S
Szabolcs Nagy 已提交
44
			if (!*++s) break;
45 46
			continue;
		}
S
Szabolcs Nagy 已提交
47
		for (v=j=0; j<4 && (d=hexval(s[j]))>=0; j++)
48
			v=16*v+d;
S
Szabolcs Nagy 已提交
49
		if (j==0 || v > 65535) return 0;
50
		ip[i] = v;
S
Szabolcs Nagy 已提交
51 52 53 54
		if (!s[j] && (brk>=0 || i==7)) break;
		if (i==7) return 0;
		if (s[j]!=':') {
			if (s[j]!='.' || (i<6 && brk<0)) return 0;
55 56 57 58
			need_v4=1;
			i++;
			break;
		}
S
Szabolcs Nagy 已提交
59
		s += j+1;
60 61 62 63 64 65 66 67 68
	}
	if (brk>=0) {
		memmove(ip+brk+7-i, ip+brk, 2*(i+1-brk));
		for (j=0; j<7-i; j++) ip[brk+j] = 0;
	}
	for (j=0; j<8; j++) {
		*a++ = ip[j]>>8;
		*a++ = ip[j];
	}
69
	if (need_v4 && inet_pton(AF_INET, (void *)s, a-4) <= 0) return 0;
70
	return 1;
R
Rich Felker 已提交
71
}