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 +}

UW-IMAP'd extensions by yuuji