⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip6_nt.c

📁 广泛使用的邮件服务器!同时
💻 C
字号:
/* ======================================================================== * Copyright 1988-2006 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	UNIX IPv6 routines * * Author:	Mark Crispin *		Networks and Distributed Computing *		Computing & Communications *		University of Washington *		Administration Building, AG-44 *		Seattle, WA  98195 *		Internet: MRC@CAC.Washington.EDU * * Date:	18 December 2003 * Last Edited:	30 August 2006 *//* * There is some amazingly bad design in IPv6 sockets. * * Supposedly, the new getnameinfo() and getaddrinfo() functions create an * abstraction that is not dependent upon IPv4 or IPv6.  However, the * definition of getnameinfo() requires that the caller pass the length of * the sockaddr instead of deriving it from sa_family.  The man page says * that there's an sa_len member in the sockaddr, but actually there isn't. * This means that any caller to getnameinfo() and getaddrinfo() has to know * the size for the protocol family used by that sockaddr. * * The new sockaddr_in6 is bigger than the generic sockaddr (which is what * connect(), accept(), bind(), getpeername(), getsockname(), etc. expect). * Rather than increase the size of sockaddr, there's a new sockaddr_storage * which is only usable for allocating space. */#define SADRLEN sizeof (struct sockaddr_storage)#define SADR4(sadr) ((struct sockaddr_in *) sadr)#define SADR4LEN sizeof (struct sockaddr_in)#define SADR4ADR(sadr) SADR4 (sadr)->sin_addr#define ADR4LEN sizeof (struct in_addr)#define SADR4PORT(sadr) SADR4 (sadr)->sin_port#define SADR6(sadr) ((struct sockaddr_in6 *) sadr)#define SADR6LEN sizeof (struct sockaddr_in6)#define SADR6ADR(sadr) SADR6 (sadr)->sin6_addr#define ADR6LEN sizeof (struct in6_addr)#define SADR6PORT(sadr) SADR6 (sadr)->sin6_port/* IP abstraction layer */char *ip_sockaddrtostring (struct sockaddr *sadr);long ip_sockaddrtoport (struct sockaddr *sadr);void *ip_stringtoaddr (char *text,size_t *len,int *family);struct sockaddr *ip_newsockaddr (size_t *len);struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,			      unsigned short port,size_t *len);char *ip_sockaddrtoname (struct sockaddr *sadr);void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,		     void **next);/* Return IP address string from socket address * Accepts: socket address * Returns: IP address as name string */char *ip_sockaddrtostring (struct sockaddr *sadr){  static char tmp[NI_MAXHOST];  switch (sadr->sa_family) {  case PF_INET:			/* IPv4 */    if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST))      return tmp;    break;  case PF_INET6:		/* IPv6 */    if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NUMERICHOST))      return tmp;    break;  }  return "NON-IP";}/* Return port from socket address * Accepts: socket address * Returns: port number or -1 if can't determine it */long ip_sockaddrtoport (struct sockaddr *sadr){  switch (sadr->sa_family) {  case PF_INET:    return ntohs (SADR4PORT (sadr));  case PF_INET6:    return ntohs (SADR6PORT (sadr));  }  return -1;}/* Return IP address from string * Accepts: name string *	    pointer to returned length *	    pointer to returned address family * Returns: address if valid, length and family updated, or NIL */void *ip_stringtoaddr (char *text,size_t *len,int *family){  char tmp[MAILTMPLEN];  static struct addrinfo *hints;  struct addrinfo *ai;  void *adr = NIL;  if (!hints) {			/* hints set up yet? */    hints = (struct addrinfo *) /* one-time setup */      memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo));    hints->ai_family = AF_UNSPEC;/* allow any address family */    hints->ai_socktype = SOCK_STREAM;				/* numeric name only */    hints->ai_flags = AI_NUMERICHOST;  }				/* case-independent lookup */  if (text && (strlen (text) < MAILTMPLEN) &&      (!getaddrinfo (lcase (strcpy (tmp,text)),NIL,hints,&ai))) {    switch (*family = ai->ai_family) {    case AF_INET:		/* IPv4 */      adr = fs_get (*len = ADR4LEN);      memcpy (adr,(void *) &SADR4ADR (ai->ai_addr),*len);      break;    case AF_INET6:		/* IPv6 */      adr = fs_get (*len = ADR6LEN);      memcpy (adr,(void *) &SADR6ADR (ai->ai_addr),*len);      break;    }    freeaddrinfo (ai);		/* free addrinfo */  }  return adr;}/* Create a maximum-size socket address * Accepts: pointer to return maximum socket address length * Returns: new, empty socket address of maximum size */struct sockaddr *ip_newsockaddr (size_t *len){  return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN);}/* Stuff a socket address * Accepts: address family *	    IPv4 address *	    length of address *	    port number *	    pointer to return socket address length * Returns: socket address */struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,			      unsigned short port,size_t *len){  struct sockaddr *sadr = ip_newsockaddr (len);  switch (family) {		/* build socket address based upon family */  case AF_INET:			/* IPv4 */    sadr->sa_family = PF_INET;				/* copy host address */    memcpy (&SADR4ADR (sadr),adr,adrlen);				/* copy port number in network format */    SADR4PORT (sadr) = htons (port);    *len = SADR4LEN;    break;  case AF_INET6:		/* IPv6 */    sadr->sa_family = PF_INET6;				/* copy host address */    memcpy (&SADR6ADR (sadr),adr,adrlen);				/* copy port number in network format */    SADR6PORT (sadr) = htons (port);    *len = SADR6LEN;    break;  default:			/* non-IP?? */    sadr->sa_family = PF_UNSPEC;    break;  }  return sadr;}/* Return name from socket address * Accepts: socket address * Returns: canonical name for that address or NIL if none */char *ip_sockaddrtoname (struct sockaddr *sadr){  static char tmp[NI_MAXHOST];  switch (sadr->sa_family) {  case PF_INET:			/* IPv4 */    if (!getnameinfo (sadr,SADR4LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD))      return tmp;    break;  case PF_INET6:		/* IPv6 */    if (!getnameinfo (sadr,SADR6LEN,tmp,NI_MAXHOST,NIL,NIL,NI_NAMEREQD))      return tmp;    break;  }  return NIL;}/* Return address from name * Accepts: name or NIL to return next address *	    pointer to previous/returned length *	    pointer to previous/returned address family *	    pointer to previous/returned canonical name *	    pointer to previous/return state for next-address calls * Returns: address with length/family/canonical updated if needed, or NIL */void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,		     void **next){  struct addrinfo *cur = NIL;  static struct addrinfo *hints;  static struct addrinfo *ai = NIL;  static char lcname[MAILTMPLEN];  if (!hints) {			/* hints set up yet? */    hints = (struct addrinfo *) /* one-time setup */      memset (fs_get (sizeof (struct addrinfo)),0,sizeof (struct addrinfo));				/* allow any address family */    hints->ai_family = AF_UNSPEC;    hints->ai_socktype = SOCK_STREAM;				/* need canonical name */    hints->ai_flags = AI_CANONNAME;  }  if (name) {			/* name supplied? */    if (ai) {      freeaddrinfo (ai);	/* free old addrinfo */      ai = NIL;    }				/* case-independent lookup */    if ((strlen (name) < MAILTMPLEN) &&	(!getaddrinfo (lcase (strcpy (lcname,name)),NIL,hints,&ai))) {      cur = ai;			/* current block */      if (canonical)		/* set canonical name */	*canonical = cur->ai_canonname ? cur->ai_canonname : lcname;				/* remember as next block */      if (next) *next = (void *) ai;    }    else {			/* error */      cur = NIL;      if (len) *len = 0;      if (family) *family = 0;      if (canonical) *canonical = NIL;      if (next) *next = NIL;    }  }				/* return next in series */  else if (next && (cur = ((struct addrinfo *) *next)->ai_next)) {    *next = cur;		/* set as last address */				/* set canonical in case changed */    if (canonical && cur->ai_canonname) *canonical = cur->ai_canonname;  }  if (cur) {			/* got data? */    if (family) *family = cur->ai_family;    switch (cur->ai_family) {    case AF_INET:      if (len) *len = ADR4LEN;      return (void *) &SADR4ADR (cur->ai_addr);    case AF_INET6:      if (len) *len = ADR6LEN;      return (void *) &SADR6ADR (cur->ai_addr);    }  }  if (len) *len = 0;		/* error return */  return NIL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -