summaryrefslogtreecommitdiff
path: root/libc/inet/addr.c
blob: abee083da81f82070434ebf70314fcec785083a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
 *
 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 */

/*
 * Manuel Novoa III       Dec 2000
 *
 * Converted to use my new (un)signed long (long) to string routines, which
 * are smaller than the previous functions and don't require static buffers.
 * In the process, removed the reference to strcat and cut object size of
 * inet_ntoa in half (from 190 bytes down to 94).
 *
 * Manuel Novoa III       Feb 2002
 *
 * Changed to use _int10tostr.
 */

#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <bits/uClibc_uintmaxtostr.h>

#ifdef L_inet_aton
/*
 * More undocumented inet_aton features.
 * (read: uclibc doesnt support but glibc does)
 * http://www.mkssoftware.com/docs/man3/inet_aton.3.asp
 *
 * *cp can take the form of:
 * a.b.c.d    - {a,b,c,d} -> 1 byte
 * a.b.c      - {a,b}     -> 1 byte    {c} -> 2 bytes
 * a.b        - {a}       -> 1 byte    {b} -> 3 bytes
 * a          -                        {a} -> 4 bytes
 *
 * Each part may be decimal, octal, or hexadecimal as in ISO C.
 * 0x or 0X    -> hexadecimal
 * leading 0   -> octal
 * all else    -> decimal
 */
#ifdef __UCLIBC_HAS_XLOCALE__
libc_hidden_proto(__ctype_b_loc)
#elif defined __UCLIBC_HAS_CTYPE_TABLES__
libc_hidden_proto(__ctype_b)
#endif
libc_hidden_proto(inet_aton)
int inet_aton(const char *cp, struct in_addr *addrptr)
{
	in_addr_t addr;
	int value;
	int part;

	if (cp == NULL) {	/* check for NULL arg */
	    return 0;
	}

	addr = 0;
	for (part = 1; part <= 4; part++) {

		if (!isdigit(*cp))
			return 0;

		value = 0;
		while (isdigit(*cp)) {
			value *= 10;
			value += *cp++ - '0';
			if (value > 255)
				return 0;
		}

		if (part < 4) {
			if (*cp++ != '.')
				return 0;
		} else {
			char c = *cp++;
			if (c != '\0' && !isspace(c))
			return 0;
		}

		addr <<= 8;
		addr |= value;
	}

	/*  W. Richard Stevens in his book UNIX Network Programming,
	 *  Volume 1, second edition, on page 71 says:
	 *
	 *  An undocumented feature of inet_aton is that if addrptr is
	 *  a null pointer, the function still performs it validation
	 *  of the input string, but does not store the result.
	 */
	if (addrptr) {
		addrptr->s_addr = htonl(addr);
	}

	return 1;
}
libc_hidden_def(inet_aton)
#endif

#ifdef L_inet_addr
libc_hidden_proto(inet_aton)

libc_hidden_proto(inet_addr)
in_addr_t inet_addr(const char *cp)
{
	struct in_addr a;

	if (!inet_aton(cp, &a))
		return INADDR_NONE;
	else
		return a.s_addr;
}
libc_hidden_def(inet_addr)
#endif

#ifdef L_inet_ntoa

#define INET_NTOA_MAX_LEN	16	/* max 12 digits + 3 '.'s + 1 nul */

libc_hidden_proto(inet_ntoa_r)
char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN])
{
	in_addr_t addr = ntohl(in.s_addr);
	int i;
	char *p, *q;

	q = 0;
	p = buf + INET_NTOA_MAX_LEN - 1; /* cannot use sizeof(buf) here */
	for (i=0 ; i < 4 ; i++ ) {
		p = _int10tostr(p, addr & 0xff) - 1;
		addr >>= 8;
		if (q) {
			*q = '.';
		}
		q = p;
	}

	return p+1;
}
libc_hidden_def(inet_ntoa_r)

libc_hidden_proto(inet_ntoa)
char *inet_ntoa(struct in_addr in)
{
	static char buf[INET_NTOA_MAX_LEN];
	return(inet_ntoa_r(in, buf));
}
libc_hidden_def(inet_ntoa)
#endif

#ifdef L_inet_makeaddr

/* for some reason it does not remove the jump relocation */
/* Experimentally off - libc_hidden_proto(memmove) */

/*
 * Formulate an Internet address from network + host.  Used in
 * building addresses stored in the ifnet structure.
 */
libc_hidden_proto(inet_makeaddr)
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host)
{
	in_addr_t addr;

	if (net < 128)
		addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
	else if (net < 65536)
		addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
	else if (net < 16777216UL)
		addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
	else
		addr = net | host;
	addr = htonl(addr);
	return (*(struct in_addr *)&addr);
}
libc_hidden_def(inet_makeaddr)
#endif

#ifdef L_inet_lnaof
/*
 * Return the local network address portion of an
 * internet address; handles class a/b/c network
 * number formats.
 */
in_addr_t inet_lnaof(struct in_addr in)
{
	in_addr_t i = ntohl(in.s_addr);

	if (IN_CLASSA(i))
		return ((i)&IN_CLASSA_HOST);
	else if (IN_CLASSB(i))
		return ((i)&IN_CLASSB_HOST);
	else
		return ((i)&IN_CLASSC_HOST);
}
#endif

#ifdef L_inet_netof

/*
 * Return the network number from an internet
 * address; handles class a/b/c network #'s.
 */
libc_hidden_proto(inet_netof)
in_addr_t
inet_netof(struct in_addr in)
{
	in_addr_t i = ntohl(in.s_addr);

	if (IN_CLASSA(i))
		return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
	else if (IN_CLASSB(i))
		return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
	else
	return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
}
libc_hidden_def(inet_netof)
#endif