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

📄 su_localinfo.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* Get the list of known IP address from the kernel */  if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) {    /* can't get number of interfaces -- fall back */    SU_DEBUG_1(("su_localinfo: SIOCGIFNUM failed: %s\n", 		su_strerror(su_errno())));    error = ELI_SYSTEM;    goto err;  }  SU_DEBUG_9(("su_localinfo: %d active interfaces according to SIOCGIFNUM\n", 	      numifs));  if (numifs < 0)# endif    /* Default to 64 interfaces. Enough? */    numifs = 64;  if (numifs == 0)    return 0;  /*   * Allocate memory for SIOCGIFCONF ioctl buffer. This memory block is also   * used as li_first, first localinfo struct that is returned, so it can be   * freed by freelocalinfo() without any complications.   */  ifc.ifc_len = numifs * sizeof (struct ifreq);  buffer = malloc(sizeof(su_localinfo_t) + ifc.ifc_len + su_xtra);  if (!buffer) {    SU_DEBUG_1(("su_localinfo: memory exhausted\n"));    error = ELI_MEMORY;    goto err;  }    li_first = (su_localinfo_t *)buffer;  memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra);  ifc.ifc_buf = buffer + sizeof(su_localinfo_t) + su_xtra;#if HAVE_OPEN_C  if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) {    SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", 		su_strerror(su_errno())));    error = ELI_SYSTEM;    goto err;  }#else  if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {    SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", 		su_strerror(su_errno())));    error = ELI_SYSTEM;    goto err;  }#endif  buffer = ifc.ifc_buf + ifc.ifc_len;  for (ifr = ifc.ifc_req;       (void *)ifr < (void *)buffer;       ifr = ifr_next) {    struct ifreq ifreq[1];    int scope, if_index, flags = 0, gni_flags = 0;    char *if_name;    su_sockaddr_t su2[1];#if SA_LEN    if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))      ifr_next = (struct ifreq *)	(ifr->ifr_addr.sa_len + (char *)(&ifr->ifr_addr));    else#else      ifr_next = ifr + 1;#endif    if_name = ifr->ifr_name;#if defined(SIOCGIFINDEX)    ifreq[0] = *ifr;    if (ioctl(s, SIOCGIFINDEX, ifreq) < 0) {      SU_DEBUG_1(("su_localinfo: SIOCGIFINDEX failed: %s\n", 		  su_strerror(su_errno())));      error = ELI_SYSTEM;      goto err;    }#if HAVE_IFR_INDEX    if_index = ifreq->ifr_index;#elif HAVE_IFR_IFINDEX    if_index = ifreq->ifr_ifindex;#else#error Unknown index field in struct ifreq#endif#else#warning su_localinfo() cannot map interface name to number    if_index = 0;#endif    SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index));#if HAVE_OPEN_C    su_close(s);    li = calloc(1, sizeof(su_localinfo_t));    sa = calloc(1, sizeof(su_sockaddr_t));    if (su_get_local_ip_addr(sa) < 0)      goto err;          li->li_family = sa->su_family;    li->li_scope = LI_SCOPE_GLOBAL /* scope */;    li->li_index = if_index;    li->li_addrlen = su_sockaddr_size(sa);    li->li_addr = sa;    if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)      goto err;    if (canonname) {      if (strchr(canonname, ':') ||	  strspn(canonname, "0123456789.") == strlen(canonname))	    li->li_flags |= LI_NUMERIC;    }    else      li->li_flags = 0;    li->li_canonname = canonname;    canonname = NULL;    *rresult = li;    return 0;#endif#if defined(SIOCGIFFLAGS)    ifreq[0] = *ifr;    if (ioctl(s, SIOCGIFFLAGS, ifreq) < 0) {      SU_DEBUG_1(("su_localinfo: SIOCGIFFLAGS failed: %s\n", 		  su_strerror(su_errno())));      error = ELI_SYSTEM;      goto err;    }    /* Do not include interfaces that are down unless explicitly asked */    if ((ifreq->ifr_flags & IFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0) {      SU_DEBUG_9(("su_localinfo: if %s with index %d is down\n", 		  if_name, if_index));      continue;    }#elif defined(SIOCGIFACTIVECONF)/* Handled above in SIOCGIFACTIVECONF vs. SIOCGIFCONF*/#else#error su_localinfo() cannot determine interface status#endif#if 0    *ifreq = *ifr;    ifreq->ifr_addr.sa_family = AF_INET;    if (ioctl(s, SIOCGIFADDR, ifreq) < 0) {      SU_DEBUG_1(("su_localinfo: SIOCGIFADDR failed: %s\n", 		  su_strerror(su_errno())));      error = ELI_SYSTEM;      goto err;    }    ifr->ifr_addr = ifreq->ifr_addr;#endif    su = (su_sockaddr_t *)&ifr->ifr_addr;    if (SU_HAS_INADDR_ANY(su))      continue;    scope = li_scope4(su->su_sin.sin_addr.s_addr);    if ((hints->li_scope && (hints->li_scope & scope) == 0) ||	(hints->li_ifname && strcmp(hints->li_ifname, if_name) != 0) ||	(hints->li_index && hints->li_index != if_index))      continue;#if SU_HAVE_IN6    if (su_xtra) {      /* Map IPv4 address to IPv6 address */      memset(su2, 0, sizeof(*su2));      su2->su_family = AF_INET6;      ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);      ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;      su = su2;    }#endif    if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)      gni_flags = NI_NUMERICHOST;    if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)      goto err;    else if (error > 0)      continue;        if (canonname)      if (strchr(canonname, ':') ||	  strspn(canonname, "0123456789.") == strlen(canonname))	flags |= LI_NUMERIC;    if (li_first)      li = li_first;      /* Use li_first with all ifr structs to be freed */    else if (!(li = calloc(1, (sizeof *li) + su_xtra))) {      error = ELI_MEMORY;      goto err;    }    if (!tbf) tbf = li;    *lli = li; lli = &li->li_next;    if (su_xtra)      su = (su_sockaddr_t *)memcpy(li + 1, su, su_xtra);    li->li_flags = flags;    li->li_family = su->su_family;    li->li_scope = scope;    li->li_index = if_index;    li->li_addrlen = su_sockaddr_size(su);    li->li_addr = su;    li->li_canonname = canonname;    if (hints->li_flags & LI_IFNAME)      li->li_ifname = if_name;    canonname = NULL;    li_first = NULL;  }  if (canonname) free(canonname);  if (li_first) free(li_first);  su_close(s);  if (tbf) *rresult = tbf;  return 0;err:  if (canonname) free(canonname);  if (li_first) free(li_first);  su_freelocalinfo(tbf);  su_close(s);  return error;}#endif /* __APPLE_CC__ */#elsestaticint localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult){  /* Kikka #3: resolve hostname */  char hostname[SU_MAXHOST] = "";  char *name, *ifname;  struct hostent *h;  int i, flags, error, gni_flags = 0;  su_localinfo_t *tbf = NULL;  su_localinfo_t *li = NULL, **lli = &tbf;  su_sockaddr_t *su;#if SU_HAVE_IN6  socklen_t su_sockaddr_size =     (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : sizeof(struct sockaddr_in);  flags = hints->li_flags & (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);#else  socklen_t su_sockaddr_size = sizeof(struct sockaddr_in);  flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);#endif  error = ELI_NOERROR;  if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {    if (hints->li_canonname)      name = hints->li_canonname;    else if (gethostname(name = hostname, sizeof(hostname)) != 0)      return ELI_SYSTEM;      h = gethostbyname(name);    if (name)      if (strchr(name, ':') ||	  strspn(name, "0123456789.") == strlen(name))	flags |= LI_NUMERIC;    for (i = 0; h && h->h_addr_list[i]; i++) {      if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {	error = ELI_MEMORY;	goto err;      }      li->li_flags = flags;      li->li_scope = li_scope4(*(uint32_t *)h->h_addr_list[i]);      if (li->li_scope == LI_SCOPE_HOST)	li->li_index = 1, ifname = "lo";      else	li->li_index = 2, ifname = "eth";      li->li_addrlen = su_sockaddr_size;      li->li_addr = su = (su_sockaddr_t *)(li + 1);      su->su_family = li->li_family = 	li->li_flags & LI_V4MAPPED ? AF_INET6 : AF_INET;#if SU_HAVE_IN6      if (li->li_flags & LI_V4MAPPED) {	((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);	memcpy(&((int32_t*)&su->su_sin6.sin6_addr)[3],	       h->h_addr_list[i], h->h_length);      }      else #endif	memcpy(&su->su_sin.sin_addr.s_addr, h->h_addr_list[i], h->h_length);      if (li->li_flags & LI_IFNAME) 	li->li_ifname = ifname;      if (li->li_scope == LI_SCOPE_HOST || li->li_scope == LI_SCOPE_LINK)	gni_flags = NI_NUMERICHOST;      if ((error = li_name(hints, gni_flags, su, &li->li_canonname)) < 0)	goto err;      else if (error > 0) {	free(li); li = NULL; continue;      } else	error = ELI_NOADDRESS;      *lli = li; lli = &li->li_next; li = NULL;    }  }  if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_HOST)) {    if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {      error = ELI_MEMORY;      goto err;    }    li->li_flags = hints->li_flags &       (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);    li->li_scope = LI_SCOPE_HOST, li->li_index = 1;    if (li->li_flags & LI_IFNAME)      li->li_ifname = "lo";    li->li_addrlen = su_sockaddr_size;    li->li_addr = su = (su_sockaddr_t *)(li + 1);#if SU_HAVE_IN6    if (li->li_flags & LI_V4MAPPED) {      su->su_family = li->li_family = AF_INET6;      ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);      ((int32_t*)&su->su_sin6.sin6_addr)[3] = htonl(0x7f000001);    }    else #endif      su->su_family = li->li_family = AF_INET,      su->su_sin.sin_addr.s_addr = htonl(0x7f000001);    if ((error = li_name(hints, NI_NUMERICHOST, su, &li->li_canonname)) < 0) {      goto err;    } else if (error > 0) {      free(li); li = NULL;     } else {      *lli = li; lli = &li->li_next; li = NULL;    }  }  *rresult = tbf;  return 0;err:  if (li) su_freelocalinfo(li);  su_freelocalinfo(tbf);  return error;}#endif#if USE_LOCALINFO0 || !SU_HAVE_IN6#elif HAVE_PROC_NET_IF_INET6 /** Build a list of local IPv6 addresses and append it to *return_result. */staticint localinfo6(su_localinfo_t const *hints, su_localinfo_t **return_result){  su_localinfo_t *li = NULL;  su_sockaddr_t su[1] = {{ 0 }}, *addr;  int error = ELI_NOADDRESS;  char *canonname = NULL;  char line[80];  FILE *f;  if ((f = fopen("/proc/net/if_inet6", "r"))) {    for (;error;) {      struct in6_addr in6;      unsigned if_index, prefix_len, scope, flags;      int addrlen, if_namelen;      char ifname[16];      if (!fgets(line, sizeof(line), f)) {	if (feof(f))	  error = ELI_NOERROR;	break;      }      if (sscanf(line, "%08x%08x%08x%08x %2x %2x %2x %02x %016s\n",		 &in6.s6_addr32[0],		 &in6.s6_addr32[1],		 &in6.s6_addr32[2],		 &in6.s6_addr32[3], 		 &if_index, &prefix_len, &scope, &flags, ifname) != 9)	break;      flags = 0;      /* Fix global scope (it is 0) */      if (!scope) scope = LI_SCOPE_GLOBAL;      in6.s6_addr32[0] = htonl(in6.s6_addr32[0]);      in6.s6_addr32[1] = htonl(in6.s6_addr32[1]);      in6.s6_addr32[2] = htonl(in6.s6_addr32[2]);      in6.s6_addr32[3] = htonl(in6.s6_addr32[3]);      if (IN6_IS_ADDR_V4MAPPED(&in6) || IN6_IS_ADDR_V4COMPAT(&in6)) {	uint32_t ip4 = *(uint32_t *)(in6.s6_addr + 12);	scope = li_scope4(ip4);      }      if ((hints->li_scope && (hints->li_scope & scope) == 0) ||	  (hints->li_index && hints->li_index != if_index) ||	  (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0))	continue;            su->su_family = AF_INET6;      su->su_sin6.sin6_addr = in6;             addrlen = su_sockaddr_size(su);      if ((error = li_name(hints, 0, su, &canonname)) < 0)	break;      else if (error > 0)	continue;      else	error = ELI_NOADDRESS;      if (canonname && 	  (strchr(canonname, ':') ||	   strspn(canonname, "0123456789.") == strlen(canonname)))	flags |= LI_NUMERIC;      if (hints->li_flags & LI_IFNAME)	if_namelen = strlen(ifname) + 1;      else	if_namelen = 0;      if ((li = calloc(1, sizeof *li + addrlen + if_namelen)) == NULL) {	error = ELI_MEMORY;	break;      }      addr = (su_sockaddr_t*)memcpy((li + 1), su, addrlen);      *return_result = li; return_result = &li->li_next;      li->li_flags = flags;      li->li_family = AF_INET6;      li->li_scope = scope;      li->li_index = if_index;      li->li_addr = addr;      li->li_addrlen = addrlen;      li->li_canonname = canonname;      if (if_namelen)	li->li_ifname = memcpy(addrlen + (char *)addr, ifname, if_namelen);            canonname = NULL;    }    fclose(f);  }  if (canonname)     free(canonname);  return error;}#else/* Use HOSTADDR6 */staticint localinfo6(su_localinfo_t const *hints, su_localinfo_t **rresult){  char *addr, *ifname;  int flags, error;  su_localinfo_t *li = NULL;  su_sockaddr_t *su;  int const su_sockaddr_size = sizeof(*su);    error = ELI_NOADDRESS;#if defined(__APPLE_CC__)  {    su_sockaddr_t *sa;    int salen = sizeof(*sa);    int s;    if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {      if ((addr = getenv("HOSTADDR6"))) {	li = calloc(1, sizeof(su_localinfo_t));	sa = calloc(1, sizeof(su_sockaddr_t));	sa->su_family = AF_INET6;	if (su_inet_pton(AF_INET6, addr, &sa->su_sin6.sin6_addr) <= 0)	  goto err;		s = su_socket(AF_INET6, SOCK_DGRAM, 0);	if (s == -1) {	  SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", 		      su_strerror(su_errno())));	  return ELI_SYSTEM;	}		error = getsockname(s, (struct sockaddr *) sa, &salen);	if (error < 0 && errno == SOCKET_ERROR) {	  SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,		      su_strerror(su_errno())));	}		error = bind(s, (struct sockaddr *) sa, salen);		if (error < 0) {	  SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,		      su_strerror(su_errno())));	  goto err;	}		su_close(s);		li->li_family = sa->su_family;	li->li_scope = LI_SCOPE_GLOBAL;	li->li_index = 0;	li->li_addrlen = su_sockaddr_size(sa);	li->li_addr = sa;		if ((error = li_name(hints, NI_NUMERICHOST, sa, &li->li_canonname)) < 0)	  goto err;		li->li_flags = NI_NUMERICHOST;      }    }    *rresult = li;    return 0;  }#endif  if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {    if ((addr = getenv("HOSTADDR6"))) {      flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);      if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {	error = ELI_MEMORY;	goto err;      }      li->li_flags = flags;      li->li_scope = LI_SCOPE_GLOBAL, li->li_index = 2, ifname = "eth";      li->li_addrlen = sizeof(*su);      li->li_addr = su = (su_sockaddr_t *)(li + 1);      su->su_family = li->li_family = AF_INET6;      if (su_inet_pton(AF_INET6, addr, &su->su_sin6.sin6_addr) <= 0)

⌨️ 快捷键说明

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