imapext-2007
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/osdep/nt/ip6_nt.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,288 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2006 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: UNIX IPv6 routines 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * Networks and Distributed Computing 1.22 + * Computing & Communications 1.23 + * University of Washington 1.24 + * Administration Building, AG-44 1.25 + * Seattle, WA 98195 1.26 + * Internet: MRC@CAC.Washington.EDU 1.27 + * 1.28 + * Date: 18 December 2003 1.29 + * Last Edited: 30 August 2006 1.30 + */ 1.31 + 1.32 + 1.33 +/* 1.34 + * There is some amazingly bad design in IPv6 sockets. 1.35 + * 1.36 + * Supposedly, the new getnameinfo() and getaddrinfo() functions create an 1.37 + * abstraction that is not dependent upon IPv4 or IPv6. However, the 1.38 + * definition of getnameinfo() requires that the caller pass the length of 1.39 + * the sockaddr instead of deriving it from sa_family. The man page says 1.40 + * that there's an sa_len member in the sockaddr, but actually there isn't. 1.41 + * This means that any caller to getnameinfo() and getaddrinfo() has to know 1.42 + * the size for the protocol family used by that sockaddr. 1.43 + * 1.44 + * The new sockaddr_in6 is bigger than the generic sockaddr (which is what 1.45 + * connect(), accept(), bind(), getpeername(), getsockname(), etc. expect). 1.46 + * Rather than increase the size of sockaddr, there's a new sockaddr_storage 1.47 + * which is only usable for allocating space. 1.48 + */ 1.49 + 1.50 +#define SADRLEN sizeof (struct sockaddr_storage) 1.51 + 1.52 +#define SADR4(sadr) ((struct sockaddr_in *) sadr) 1.53 +#define SADR4LEN sizeof (struct sockaddr_in) 1.54 +#define SADR4ADR(sadr) SADR4 (sadr)->sin_addr 1.55 +#define ADR4LEN sizeof (struct in_addr) 1.56 +#define SADR4PORT(sadr) SADR4 (sadr)->sin_port 1.57 + 1.58 +#define SADR6(sadr) ((struct sockaddr_in6 *) sadr) 1.59 +#define SADR6LEN sizeof (struct sockaddr_in6) 1.60 +#define SADR6ADR(sadr) SADR6 (sadr)->sin6_addr 1.61 +#define ADR6LEN sizeof (struct in6_addr) 1.62 +#define SADR6PORT(sadr) SADR6 (sadr)->sin6_port 1.63 + 1.64 + 1.65 +/* IP abstraction layer */ 1.66 + 1.67 +char *ip_sockaddrtostring (struct sockaddr *sadr); 1.68 +long ip_sockaddrtoport (struct sockaddr *sadr); 1.69 +void *ip_stringtoaddr (char *text,size_t *len,int *family); 1.70 +struct sockaddr *ip_newsockaddr (size_t *len); 1.71 +struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen, 1.72 + unsigned short port,size_t *len); 1.73 +char *ip_sockaddrtoname (struct sockaddr *sadr); 1.74 +void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical, 1.75 + void **next); 1.76 + 1.77 +/* Return IP address string from socket address 1.78 + * Accepts: socket address 1.79 + * Returns: IP address as name string 1.80 + */ 1.81 + 1.82 +char *ip_sockaddrtostring (struct sockaddr *sadr) 1.83 +{ 1.84 + static char tmp[NI_MAXHOST]; 1.85 + switch (sadr->sa_family) { 1.86 + case PF_INET: /* IPv4 */ 1.87 + if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST)) 1.88 + return tmp; 1.89 + break; 1.90 + case PF_INET6: /* IPv6 */ 1.91 + if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST)) 1.92 + return tmp; 1.93 + break; 1.94 + } 1.95 + return "NON-IP"; 1.96 +} 1.97 + 1.98 + 1.99 +/* Return port from socket address 1.100 + * Accepts: socket address 1.101 + * Returns: port number or -1 if can't determine it 1.102 + */ 1.103 + 1.104 +long ip_sockaddrtoport (struct sockaddr *sadr) 1.105 +{ 1.106 + switch (sadr->sa_family) { 1.107 + case PF_INET: 1.108 + return ntohs (SADR4PORT (sadr)); 1.109 + case PF_INET6: 1.110 + return ntohs (SADR6PORT (sadr)); 1.111 + } 1.112 + return -1; 1.113 +} 1.114 + 1.115 +/* Return IP address from string 1.116 + * Accepts: name string 1.117 + * pointer to returned length 1.118 + * pointer to returned address family 1.119 + * Returns: address if valid, length and family updated, or NIL 1.120 + */ 1.121 + 1.122 +void *ip_stringtoaddr (char *text,size_t *len,int *family) 1.123 + 1.124 +{ 1.125 + char tmp[MAILTMPLEN]; 1.126 + static struct addrinfo *hints; 1.127 + struct addrinfo *ai; 1.128 + void *adr = NIL; 1.129 + if (!hints) { /* hints set up yet? */ 1.130 + hints = (struct addrinfo *) /* one-time setup */ 1.131 + memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo)); 1.132 + hints->ai_family = AF_UNSPEC;/* allow any address family */ 1.133 + hints->ai_socktype = SOCK_STREAM; 1.134 + /* numeric name only */ 1.135 + hints->ai_flags = AI_NUMERICHOST; 1.136 + } 1.137 + /* case-independent lookup */ 1.138 + if (text && (strlen (text) < MAILTMPLEN) && 1.139 + (!getaddrinfo (lcase (strcpy (tmp,text)),NIL,hints,&ai))) { 1.140 + switch (*family = ai->ai_family) { 1.141 + case AF_INET: /* IPv4 */ 1.142 + adr = fs_get (*len = ADR4LEN); 1.143 + memcpy (adr,(void *) &SADR4ADR (ai->ai_addr),*len); 1.144 + break; 1.145 + case AF_INET6: /* IPv6 */ 1.146 + adr = fs_get (*len = ADR6LEN); 1.147 + memcpy (adr,(void *) &SADR6ADR (ai->ai_addr),*len); 1.148 + break; 1.149 + } 1.150 + freeaddrinfo (ai); /* free addrinfo */ 1.151 + } 1.152 + return adr; 1.153 +} 1.154 + 1.155 +/* Create a maximum-size socket address 1.156 + * Accepts: pointer to return maximum socket address length 1.157 + * Returns: new, empty socket address of maximum size 1.158 + */ 1.159 + 1.160 +struct sockaddr *ip_newsockaddr (size_t *len) 1.161 +{ 1.162 + return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN); 1.163 +} 1.164 + 1.165 + 1.166 +/* Stuff a socket address 1.167 + * Accepts: address family 1.168 + * IPv4 address 1.169 + * length of address 1.170 + * port number 1.171 + * pointer to return socket address length 1.172 + * Returns: socket address 1.173 + */ 1.174 + 1.175 +struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen, 1.176 + unsigned short port,size_t *len) 1.177 +{ 1.178 + struct sockaddr *sadr = ip_newsockaddr (len); 1.179 + switch (family) { /* build socket address based upon family */ 1.180 + case AF_INET: /* IPv4 */ 1.181 + sadr->sa_family = PF_INET; 1.182 + /* copy host address */ 1.183 + memcpy (&SADR4ADR (sadr),adr,adrlen); 1.184 + /* copy port number in network format */ 1.185 + SADR4PORT (sadr) = htons (port); 1.186 + *len = SADR4LEN; 1.187 + break; 1.188 + case AF_INET6: /* IPv6 */ 1.189 + sadr->sa_family = PF_INET6; 1.190 + /* copy host address */ 1.191 + memcpy (&SADR6ADR (sadr),adr,adrlen); 1.192 + /* copy port number in network format */ 1.193 + SADR6PORT (sadr) = htons (port); 1.194 + *len = SADR6LEN; 1.195 + break; 1.196 + default: /* non-IP?? */ 1.197 + sadr->sa_family = PF_UNSPEC; 1.198 + break; 1.199 + } 1.200 + return sadr; 1.201 +} 1.202 + 1.203 +/* Return name from socket address 1.204 + * Accepts: socket address 1.205 + * Returns: canonical name for that address or NIL if none 1.206 + */ 1.207 + 1.208 +char *ip_sockaddrtoname (struct sockaddr *sadr) 1.209 +{ 1.210 + static char tmp[NI_MAXHOST]; 1.211 + switch (sadr->sa_family) { 1.212 + case PF_INET: /* IPv4 */ 1.213 + if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD)) 1.214 + return tmp; 1.215 + break; 1.216 + case PF_INET6: /* IPv6 */ 1.217 + if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD)) 1.218 + return tmp; 1.219 + break; 1.220 + } 1.221 + return NIL; 1.222 +} 1.223 + 1.224 +/* Return address from name 1.225 + * Accepts: name or NIL to return next address 1.226 + * pointer to previous/returned length 1.227 + * pointer to previous/returned address family 1.228 + * pointer to previous/returned canonical name 1.229 + * pointer to previous/return state for next-address calls 1.230 + * Returns: address with length/family/canonical updated if needed, or NIL 1.231 + */ 1.232 + 1.233 +void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical, 1.234 + void **next) 1.235 +{ 1.236 + struct addrinfo *cur = NIL; 1.237 + static struct addrinfo *hints; 1.238 + static struct addrinfo *ai = NIL; 1.239 + static char lcname[MAILTMPLEN]; 1.240 + if (!hints) { /* hints set up yet? */ 1.241 + hints = (struct addrinfo *) /* one-time setup */ 1.242 + memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo)); 1.243 + /* allow any address family */ 1.244 + hints->ai_family = AF_UNSPEC; 1.245 + hints->ai_socktype = SOCK_STREAM; 1.246 + /* need canonical name */ 1.247 + hints->ai_flags = AI_CANONNAME; 1.248 + } 1.249 + if (name) { /* name supplied? */ 1.250 + if (ai) { 1.251 + freeaddrinfo (ai); /* free old addrinfo */ 1.252 + ai = NIL; 1.253 + } 1.254 + /* case-independent lookup */ 1.255 + if ((strlen (name) < MAILTMPLEN) && 1.256 + (!getaddrinfo (lcase (strcpy (lcname,name)),NIL,hints,&ai))) { 1.257 + cur = ai; /* current block */ 1.258 + if (canonical) /* set canonical name */ 1.259 + *canonical = cur->ai_canonname ? cur->ai_canonname : lcname; 1.260 + /* remember as next block */ 1.261 + if (next) *next = (void *) ai; 1.262 + } 1.263 + else { /* error */ 1.264 + cur = NIL; 1.265 + if (len) *len = 0; 1.266 + if (family) *family = 0; 1.267 + if (canonical) *canonical = NIL; 1.268 + if (next) *next = NIL; 1.269 + } 1.270 + } 1.271 + /* return next in series */ 1.272 + else if (next && (cur = ((struct addrinfo *) *next)->ai_next)) { 1.273 + *next = cur; /* set as last address */ 1.274 + /* set canonical in case changed */ 1.275 + if (canonical && cur->ai_canonname) *canonical = cur->ai_canonname; 1.276 + } 1.277 + 1.278 + if (cur) { /* got data? */ 1.279 + if (family) *family = cur->ai_family; 1.280 + switch (cur->ai_family) { 1.281 + case AF_INET: 1.282 + if (len) *len = ADR4LEN; 1.283 + return (void *) &SADR4ADR (cur->ai_addr); 1.284 + case AF_INET6: 1.285 + if (len) *len = ADR6LEN; 1.286 + return (void *) &SADR6ADR (cur->ai_addr); 1.287 + } 1.288 + } 1.289 + if (len) *len = 0; /* error return */ 1.290 + return NIL; 1.291 +}