xref: /netbsd/lib/libform/type_ipv6.c (revision bf9ec67e)
1 /*	$NetBSD: type_ipv6.c,v 1.6 2001/06/13 10:45:59 wiz 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/types.h>
36 #include <sys/socket.h>
37 #include <ctype.h>
38 #include <netdb.h>
39 #include <string.h>
40 #include "form.h"
41 #include "internals.h"
42 
43 /*
44  * The IP v6 address type handling.
45  */
46 
47 /*
48  * Check the contents of the field buffer are a valid Ipv6 address only.
49  */
50 static int
51 ipv6_check_field(FIELD *field, char *args)
52 {
53 	char cleaned[NI_MAXHOST];
54 	struct addrinfo hints, *res;
55 #ifdef NI_WITHSCOPEID	/* KAME extension */
56 	const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
57 #else
58 	const int niflags = NI_NUMERICHOST;
59 #endif
60 
61 	if (args == NULL)
62 		return FALSE;
63 
64 	memset(&hints, 0, sizeof(hints));
65 	hints.ai_family = AF_INET6;
66 	hints.ai_socktype = SOCK_DGRAM;	/* dummy */
67 	hints.ai_flags = AI_NUMERICHOST;
68 
69 	if (getaddrinfo(args, "0", &hints, &res) != 0) {
70 		  /* no it is not an IPv6 address */
71 		return FALSE;
72 	}
73 
74 	if (res->ai_next) {
75 		  /* somehow the address resolved to multiple
76 		   *  addresses - strange
77 		   */
78 		freeaddrinfo(res);
79 		return FALSE;
80 	}
81 
82 	if (getnameinfo(res->ai_addr, res->ai_addrlen, cleaned,
83 			sizeof(cleaned), NULL, 0, niflags) != 0) {
84 		freeaddrinfo(res);
85 		return FALSE;
86 	}
87 
88 	freeaddrinfo(res);
89 
90 	  /*
91 	   * now we are sure host is an IPv6 address literal, and "cleaned"
92 	   * has the uniformly-formatted IPv6 address literal.  Re-set the
93 	   * field buffer to be the reformatted IPv6 address
94 	   */
95 	set_field_buffer(field, 0, cleaned);
96 
97 	return TRUE;
98 }
99 
100 /*
101  * Check the given character is numeric, return TRUE if it is.
102  */
103 static int
104 ipv6_check_char(/* ARGSUSED1 */ int c, char *args)
105 {
106 	return (isxdigit(c) || (c == '.') || (c == ':')) ? TRUE : FALSE;
107 }
108 
109 static FIELDTYPE builtin_ipv6 = {
110 	_TYPE_IS_BUILTIN,                   /* flags */
111 	0,                                  /* refcount */
112 	NULL,                               /* link */
113 	NULL,                               /* make_args */
114 	NULL,                               /* copy_args */
115 	NULL,                               /* free_args */
116 	ipv6_check_field,                   /* field_check */
117 	ipv6_check_char,                    /* char_check */
118 	NULL,                               /* next_choice */
119 	NULL                                /* prev_choice */
120 };
121 
122 FIELDTYPE *TYPE_IPV6 = &builtin_ipv6;
123 
124 
125