]>
jfr.im git - irc/ircd-hybrid/bopm.git/blob - src/inet.c
3 * This code is borrowed from ircd-hybrid version 7
12 #include <netinet/in.h>
13 #include <sys/socket.h>
40 extern const unsigned char ToLowerTab
[];
41 #define ToLower(c) (ToLowerTab[(unsigned char)(c)])
44 * From: Thomas Helvey <tomh@inxpress.net>
46 static const char *IpQuadTab
[] = {
47 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
48 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
49 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
50 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
51 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
52 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
53 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
54 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
55 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
56 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
57 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
58 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
59 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
60 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
61 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
62 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
63 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
64 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
65 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
66 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
67 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
68 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
69 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
70 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
71 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
72 "250", "251", "252", "253", "254", "255"
77 * inetntoa - in_addr to string
78 * changed name to remove collision possibility and
79 * so behaviour is guaranteed to take a pointer arg.
81 * inet_ntoa -- returned the dotted notation of a given
84 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
87 char *inetntoa(char *in
)
90 register char *bufptr
= buf
;
91 register const unsigned char *a
= (const unsigned char *) in
;
92 register const char *n
;
114 * Copyright (c) 1996-1999 by Internet Software Consortium.
116 * Permission to use, copy, modify, and distribute this software for any
117 * purpose with or without fee is hereby granted, provided that the above
118 * copyright notice and this permission notice appear in all copies.
120 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
121 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
122 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
123 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
124 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
125 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
126 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
131 * WARNING: Don't even consider trying to compile this on a system where
132 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
135 static const char *inet_ntop4(const u_char
*src
, char *dst
, unsigned int size
);
137 static const char *inet_ntop6(const u_char
*src
, char *dst
, unsigned int size
);
141 * inet_ntop4(src, dst, size)
142 * format an IPv4 address
146 * (1) uses no statics
147 * (2) takes a u_char* not an in_addr as input
151 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
155 return strcpy(dst
, inetntoa((char *) src
));
159 * inet_ntop6(src, dst, size)
160 * convert IPv6 binary address into presentation (printable) format
165 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
168 * Note that int32_t and int16_t need only be "at least" large enough
169 * to contain a value of the specified size. On some systems, like
170 * Crays, there is no such thing as an integer variable with 16 bits.
171 * Keep this in mind if you think this function should have been coded
172 * to use pointer overlays. All the world's not a VAX.
174 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
178 u_int words
[IN6ADDRSZ
/ INT16SZ
];
183 * Copy the input (bytewise) array into a wordwise array.
184 * Find the longest run of 0x00's in src[] for :: shorthanding.
186 memset(words
, '\0', sizeof words
);
187 for (i
= 0; i
< IN6ADDRSZ
; i
+= 2)
188 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
191 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++) {
194 cur
.base
= i
, cur
.len
= 1;
198 if (cur
.base
!= -1) {
199 if (best
.base
== -1 || cur
.len
> best
.len
)
205 if (cur
.base
!= -1) {
206 if (best
.base
== -1 || cur
.len
> best
.len
)
209 if (best
.base
!= -1 && best
.len
< 2)
216 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++) {
217 /* Are we inside the best run of 0x00's? */
218 if (best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
)) {
223 /* Are we following an initial run of 0x00s or any real hex? */
226 /* Is this address an encapsulated IPv4? */
227 if (i
== 6 && best
.base
== 0 && (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff))) {
228 if (!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
233 tp
+= sprintf(tp
, "%x", words
[i
]);
235 /* Was it a trailing run of 0x00's? */
236 if (best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
242 * Check for overflow, copy, and we're done.
245 if ((tp
- tmp
) > size
) {
248 return strcpy(dst
, tmp
);
253 * inetntop(af, src, dst, size)
254 * convert a network format address to presentation format.
256 * pointer to presentation format address (`dst'), or NULL (see errno).
260 const char *inetntop(int af
, const void *src
, char *dst
, unsigned int size
)
264 return (inet_ntop4(src
, dst
, size
));
267 if (IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*) src
) ||
268 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*) src
))
270 ((unsigned char *) &((struct in6_addr
*) src
)->s6_addr
[12], dst
, size
));
272 return (inet_ntop6(src
, dst
, size
));
282 * WARNING: Don't even consider trying to compile this on a system where
283 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
287 * inetpton(af, src, dst)
288 * convert from presentation format (which usually means ASCII printable)
289 * to network format (which is usually some kind of binary format).
291 * 1 if the address was valid for the specified address family
292 * 0 if the address wasn't valid (`dst' is untouched in this case)
293 * -1 if some other error occurred (`dst' is untouched in this case, too)
299 * inet_pton4(src, dst)
300 * like inet_aton() but without all the hexadecimal and shorthand.
302 * 1 if `src' is a valid dotted quad, else 0.
304 * does not touch `dst' unless it's returning 1.
309 static int inet_pton4(src
, dst
)
313 int saw_digit
, octets
, ch
;
314 unsigned char tmp
[INADDRSZ
], *tp
;
319 while ((ch
= *src
++) != '\0') {
321 if (ch
>= '0' && ch
<= '9') {
322 unsigned int new = *tp
* 10 + (ch
- '0');
332 } else if (ch
== '.' && saw_digit
) {
342 memcpy(dst
, tmp
, INADDRSZ
);
348 * inet_pton6(src, dst)
349 * convert presentation level address to network order binary form.
351 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
353 * (1) does not touch `dst' unless it's returning 1.
354 * (2) :: in a full address is silently ignored.
356 * inspired by Mark Andrews.
361 static int inet_pton6(src
, dst
)
365 static const char xdigits
[] = "0123456789abcdef";
366 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
371 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
372 endp
= tp
+ IN6ADDRSZ
;
374 /* Leading :: requires some special handling. */
381 while ((ch
= ToLower(*src
++)) != '\0') {
384 pch
= strchr(xdigits
, ch
);
387 val
|= (pch
- xdigits
);
400 } else if (*src
== '\0') {
403 if (tp
+ INT16SZ
> endp
)
405 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
406 *tp
++ = (unsigned char) val
& 0xff;
412 if (*src
!= '\0' && ch
== '.') {
413 if (((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0) {
416 break; /* '\0' was seen by inet_pton4(). */
423 if (tp
+ INT16SZ
> endp
)
425 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
426 *tp
++ = (unsigned char) val
& 0xff;
428 if (colonp
!= NULL
) {
430 * Since some memmove()'s erroneously fail to handle
431 * overlapping regions, we'll do the shift by hand.
433 const int n
= tp
- colonp
;
438 for (i
= 1; i
<= n
; i
++) {
439 endp
[-i
] = colonp
[n
- i
];
446 memcpy(dst
, tmp
, IN6ADDRSZ
);
450 int inetpton(af
, src
, dst
)
457 return (inet_pton4(src
, dst
));
460 /* Somebody might have passed as an IPv4 address this is sick but it works */
461 if (inet_pton4(src
, dst
)) {
463 sprintf(tmp
, "::ffff:%s", src
);
464 return (inet_pton6(tmp
, dst
));
466 return (inet_pton6(src
, dst
));
474 struct hostent
*bopm_gethostbyname(const char *name
)
478 #if defined(HAVE_GETHOSTBYNAME2)
479 if (strchr(name
, ':')) {
481 return gethostbyname2(name
, AF_INET6
);
483 he
= gethostbyname2(name
, AF_INET
);
484 if (h_errno
== NO_ADDRESS
) {
485 return gethostbyname2(name
, AF_INET6
);
490 return gethostbyname(name
);