imapext-2007

view src/osdep/nt/ip6_nt.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
line source
1 /* ========================================================================
2 * Copyright 1988-2006 University of Washington
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *
11 * ========================================================================
12 */
14 /*
15 * Program: UNIX IPv6 routines
16 *
17 * Author: Mark Crispin
18 * Networks and Distributed Computing
19 * Computing & Communications
20 * University of Washington
21 * Administration Building, AG-44
22 * Seattle, WA 98195
23 * Internet: MRC@CAC.Washington.EDU
24 *
25 * Date: 18 December 2003
26 * Last Edited: 30 August 2006
27 */
30 /*
31 * There is some amazingly bad design in IPv6 sockets.
32 *
33 * Supposedly, the new getnameinfo() and getaddrinfo() functions create an
34 * abstraction that is not dependent upon IPv4 or IPv6. However, the
35 * definition of getnameinfo() requires that the caller pass the length of
36 * the sockaddr instead of deriving it from sa_family. The man page says
37 * that there's an sa_len member in the sockaddr, but actually there isn't.
38 * This means that any caller to getnameinfo() and getaddrinfo() has to know
39 * the size for the protocol family used by that sockaddr.
40 *
41 * The new sockaddr_in6 is bigger than the generic sockaddr (which is what
42 * connect(), accept(), bind(), getpeername(), getsockname(), etc. expect).
43 * Rather than increase the size of sockaddr, there's a new sockaddr_storage
44 * which is only usable for allocating space.
45 */
47 #define SADRLEN sizeof (struct sockaddr_storage)
49 #define SADR4(sadr) ((struct sockaddr_in *) sadr)
50 #define SADR4LEN sizeof (struct sockaddr_in)
51 #define SADR4ADR(sadr) SADR4 (sadr)->sin_addr
52 #define ADR4LEN sizeof (struct in_addr)
53 #define SADR4PORT(sadr) SADR4 (sadr)->sin_port
55 #define SADR6(sadr) ((struct sockaddr_in6 *) sadr)
56 #define SADR6LEN sizeof (struct sockaddr_in6)
57 #define SADR6ADR(sadr) SADR6 (sadr)->sin6_addr
58 #define ADR6LEN sizeof (struct in6_addr)
59 #define SADR6PORT(sadr) SADR6 (sadr)->sin6_port
62 /* IP abstraction layer */
64 char *ip_sockaddrtostring (struct sockaddr *sadr);
65 long ip_sockaddrtoport (struct sockaddr *sadr);
66 void *ip_stringtoaddr (char *text,size_t *len,int *family);
67 struct sockaddr *ip_newsockaddr (size_t *len);
68 struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
69 unsigned short port,size_t *len);
70 char *ip_sockaddrtoname (struct sockaddr *sadr);
71 void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
72 void **next);
74 /* Return IP address string from socket address
75 * Accepts: socket address
76 * Returns: IP address as name string
77 */
79 char *ip_sockaddrtostring (struct sockaddr *sadr)
80 {
81 static char tmp[NI_MAXHOST];
82 switch (sadr->sa_family) {
83 case PF_INET: /* IPv4 */
84 if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST))
85 return tmp;
86 break;
87 case PF_INET6: /* IPv6 */
88 if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST))
89 return tmp;
90 break;
91 }
92 return "NON-IP";
93 }
96 /* Return port from socket address
97 * Accepts: socket address
98 * Returns: port number or -1 if can't determine it
99 */
101 long ip_sockaddrtoport (struct sockaddr *sadr)
102 {
103 switch (sadr->sa_family) {
104 case PF_INET:
105 return ntohs (SADR4PORT (sadr));
106 case PF_INET6:
107 return ntohs (SADR6PORT (sadr));
108 }
109 return -1;
110 }
112 /* Return IP address from string
113 * Accepts: name string
114 * pointer to returned length
115 * pointer to returned address family
116 * Returns: address if valid, length and family updated, or NIL
117 */
119 void *ip_stringtoaddr (char *text,size_t *len,int *family)
121 {
122 char tmp[MAILTMPLEN];
123 static struct addrinfo *hints;
124 struct addrinfo *ai;
125 void *adr = NIL;
126 if (!hints) { /* hints set up yet? */
127 hints = (struct addrinfo *) /* one-time setup */
128 memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo));
129 hints->ai_family = AF_UNSPEC;/* allow any address family */
130 hints->ai_socktype = SOCK_STREAM;
131 /* numeric name only */
132 hints->ai_flags = AI_NUMERICHOST;
133 }
134 /* case-independent lookup */
135 if (text && (strlen (text) < MAILTMPLEN) &&
136 (!getaddrinfo (lcase (strcpy (tmp,text)),NIL,hints,&ai))) {
137 switch (*family = ai->ai_family) {
138 case AF_INET: /* IPv4 */
139 adr = fs_get (*len = ADR4LEN);
140 memcpy (adr,(void *) &SADR4ADR (ai->ai_addr),*len);
141 break;
142 case AF_INET6: /* IPv6 */
143 adr = fs_get (*len = ADR6LEN);
144 memcpy (adr,(void *) &SADR6ADR (ai->ai_addr),*len);
145 break;
146 }
147 freeaddrinfo (ai); /* free addrinfo */
148 }
149 return adr;
150 }
152 /* Create a maximum-size socket address
153 * Accepts: pointer to return maximum socket address length
154 * Returns: new, empty socket address of maximum size
155 */
157 struct sockaddr *ip_newsockaddr (size_t *len)
158 {
159 return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN);
160 }
163 /* Stuff a socket address
164 * Accepts: address family
165 * IPv4 address
166 * length of address
167 * port number
168 * pointer to return socket address length
169 * Returns: socket address
170 */
172 struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
173 unsigned short port,size_t *len)
174 {
175 struct sockaddr *sadr = ip_newsockaddr (len);
176 switch (family) { /* build socket address based upon family */
177 case AF_INET: /* IPv4 */
178 sadr->sa_family = PF_INET;
179 /* copy host address */
180 memcpy (&SADR4ADR (sadr),adr,adrlen);
181 /* copy port number in network format */
182 SADR4PORT (sadr) = htons (port);
183 *len = SADR4LEN;
184 break;
185 case AF_INET6: /* IPv6 */
186 sadr->sa_family = PF_INET6;
187 /* copy host address */
188 memcpy (&SADR6ADR (sadr),adr,adrlen);
189 /* copy port number in network format */
190 SADR6PORT (sadr) = htons (port);
191 *len = SADR6LEN;
192 break;
193 default: /* non-IP?? */
194 sadr->sa_family = PF_UNSPEC;
195 break;
196 }
197 return sadr;
198 }
200 /* Return name from socket address
201 * Accepts: socket address
202 * Returns: canonical name for that address or NIL if none
203 */
205 char *ip_sockaddrtoname (struct sockaddr *sadr)
206 {
207 static char tmp[NI_MAXHOST];
208 switch (sadr->sa_family) {
209 case PF_INET: /* IPv4 */
210 if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD))
211 return tmp;
212 break;
213 case PF_INET6: /* IPv6 */
214 if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD))
215 return tmp;
216 break;
217 }
218 return NIL;
219 }
221 /* Return address from name
222 * Accepts: name or NIL to return next address
223 * pointer to previous/returned length
224 * pointer to previous/returned address family
225 * pointer to previous/returned canonical name
226 * pointer to previous/return state for next-address calls
227 * Returns: address with length/family/canonical updated if needed, or NIL
228 */
230 void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
231 void **next)
232 {
233 struct addrinfo *cur = NIL;
234 static struct addrinfo *hints;
235 static struct addrinfo *ai = NIL;
236 static char lcname[MAILTMPLEN];
237 if (!hints) { /* hints set up yet? */
238 hints = (struct addrinfo *) /* one-time setup */
239 memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo));
240 /* allow any address family */
241 hints->ai_family = AF_UNSPEC;
242 hints->ai_socktype = SOCK_STREAM;
243 /* need canonical name */
244 hints->ai_flags = AI_CANONNAME;
245 }
246 if (name) { /* name supplied? */
247 if (ai) {
248 freeaddrinfo (ai); /* free old addrinfo */
249 ai = NIL;
250 }
251 /* case-independent lookup */
252 if ((strlen (name) < MAILTMPLEN) &&
253 (!getaddrinfo (lcase (strcpy (lcname,name)),NIL,hints,&ai))) {
254 cur = ai; /* current block */
255 if (canonical) /* set canonical name */
256 *canonical = cur->ai_canonname ? cur->ai_canonname : lcname;
257 /* remember as next block */
258 if (next) *next = (void *) ai;
259 }
260 else { /* error */
261 cur = NIL;
262 if (len) *len = 0;
263 if (family) *family = 0;
264 if (canonical) *canonical = NIL;
265 if (next) *next = NIL;
266 }
267 }
268 /* return next in series */
269 else if (next && (cur = ((struct addrinfo *) *next)->ai_next)) {
270 *next = cur; /* set as last address */
271 /* set canonical in case changed */
272 if (canonical && cur->ai_canonname) *canonical = cur->ai_canonname;
273 }
275 if (cur) { /* got data? */
276 if (family) *family = cur->ai_family;
277 switch (cur->ai_family) {
278 case AF_INET:
279 if (len) *len = ADR4LEN;
280 return (void *) &SADR4ADR (cur->ai_addr);
281 case AF_INET6:
282 if (len) *len = ADR6LEN;
283 return (void *) &SADR6ADR (cur->ai_addr);
284 }
285 }
286 if (len) *len = 0; /* error return */
287 return NIL;
288 }

UW-IMAP'd extensions by yuuji