1 /* $NetBSD: type_ipv6.c,v 1.10 2004/11/24 11:57:09 blymn Exp $ */
2
3 /*-
4 * Copyright (c) 1998-1999 Brett Lymn
5 * (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6 * All rights reserved.
7 *
8 * This code has been donated to The NetBSD Foundation by the Author.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Many thanks to Jun-ichiro itojun Hagino <itojun@NetBSD.org> for providing
30 * the sample code for the check field function, this function is 99.999%
31 * his code.
32 *
33 */
34
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: type_ipv6.c,v 1.10 2004/11/24 11:57:09 blymn Exp $");
37
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <ctype.h>
41 #include <netdb.h>
42 #include <string.h>
43 #include "form.h"
44 #include "internals.h"
45
46 /*
47 * The IP v6 address type handling.
48 */
49
50 /*
51 * Check the contents of the field buffer are a valid Ipv6 address only.
52 */
53 static int
ipv6_check_field(FIELD * field,char * args)54 ipv6_check_field(FIELD *field, char *args)
55 {
56 char cleaned[NI_MAXHOST];
57 struct addrinfo hints, *res;
58 const int niflags = NI_NUMERICHOST;
59
60 if (args == NULL)
61 return FALSE;
62
63 memset(&hints, 0, sizeof(hints));
64 hints.ai_family = AF_INET6;
65 hints.ai_socktype = SOCK_DGRAM; /* dummy */
66 hints.ai_flags = AI_NUMERICHOST;
67
68 if (getaddrinfo(args, "0", &hints, &res) != 0) {
69 /* no it is not an IPv6 address */
70 return FALSE;
71 }
72
73 if (res->ai_next) {
74 /* somehow the address resolved to multiple
75 * addresses - strange
76 */
77 freeaddrinfo(res);
78 return FALSE;
79 }
80
81 if (getnameinfo(res->ai_addr, res->ai_addrlen, cleaned,
82 (socklen_t) sizeof(cleaned), NULL, 0, niflags) != 0) {
83 freeaddrinfo(res);
84 return FALSE;
85 }
86
87 freeaddrinfo(res);
88
89 /*
90 * now we are sure host is an IPv6 address literal, and "cleaned"
91 * has the uniformly-formatted IPv6 address literal. Re-set the
92 * field buffer to be the reformatted IPv6 address
93 */
94 set_field_buffer(field, 0, cleaned);
95
96 return TRUE;
97 }
98
99 /*
100 * Check the given character is numeric, return TRUE if it is.
101 */
102 static int
ipv6_check_char(int c,char * args)103 ipv6_check_char(/* ARGSUSED1 */ int c, char *args)
104 {
105 return (isxdigit(c) || (c == '.') || (c == ':')) ? TRUE : FALSE;
106 }
107
108 static FIELDTYPE builtin_ipv6 = {
109 _TYPE_IS_BUILTIN, /* flags */
110 0, /* refcount */
111 NULL, /* link */
112 NULL, /* make_args */
113 NULL, /* copy_args */
114 NULL, /* free_args */
115 ipv6_check_field, /* field_check */
116 ipv6_check_char, /* char_check */
117 NULL, /* next_choice */
118 NULL /* prev_choice */
119 };
120
121 FIELDTYPE *TYPE_IPV6 = &builtin_ipv6;
122
123
124