ip_util.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * $Id: ip_util.c,v 1.14 2010/03/17 18:57:01 aland Exp $
  3. *
  4. * Copyright (C) 1995,1996,1997 Lars Fenneberg
  5. *
  6. * Copyright 1992 Livingston Enterprises, Inc.
  7. *
  8. * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
  9. * and Merit Network, Inc. All Rights Reserved
  10. *
  11. * See the file COPYRIGHT for the respective terms and conditions.
  12. * If the file is missing contact me at lf@elemental.net
  13. * and I'll send you a copy.
  14. *
  15. */
  16. #include <config.h>
  17. #include <includes.h>
  18. #include <freeradius-client.h>
  19. #include "util.h"
  20. #define HOSTBUF_SIZE 1024
  21. /** Return a struct addrinfo from a host name or address in textual notation.
  22. * @param host the name of the host
  23. * @param flags should be a combinations of %PW_AI flags
  24. * @return address which should be deallocated using freeaddrinfo() or NULL on failure
  25. **/
  26. struct addrinfo *rc_getaddrinfo (char const *host, unsigned flags)
  27. {
  28. struct addrinfo hints, *res;
  29. int err;
  30. const char *service = NULL;
  31. memset(&hints, 0, sizeof(hints));
  32. hints.ai_socktype = SOCK_DGRAM;
  33. if (flags & PW_AI_PASSIVE)
  34. hints.ai_flags = AI_PASSIVE;
  35. if (flags & PW_AI_AUTH)
  36. service = "radius";
  37. else if (flags & PW_AI_ACCT)
  38. service = "radius-acct";
  39. err = getaddrinfo(host, service, &hints, &res);
  40. if (err != 0) {
  41. return NULL;
  42. }
  43. return res;
  44. }
  45. /** Get the port number for the supplied request type
  46. *
  47. * @param type %AUTH or %ACCT.
  48. * @return the port number.
  49. */
  50. unsigned short rc_getport(int type)
  51. {
  52. struct servent *svp;
  53. if ((svp = getservbyname ((type==AUTH)?"radius" : "radacct", "udp")) == NULL)
  54. {
  55. return (type==AUTH) ? PW_AUTH_UDP_PORT : PW_ACCT_UDP_PORT;
  56. } else {
  57. return ntohs ((unsigned short) svp->s_port);
  58. }
  59. }
  60. /** Get the hostname of this machine
  61. *
  62. * @param hostname will hold the name of the host.
  63. * @param len the size of hostname.
  64. * @return -1 on failure, 0 on success.
  65. */
  66. int
  67. rc_own_hostname(char *hostname, int len)
  68. {
  69. #ifdef HAVE_UNAME
  70. struct utsname uts;
  71. #endif
  72. #if defined(HAVE_UNAME)
  73. if (uname(&uts) < 0)
  74. {
  75. rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname");
  76. return -1;
  77. }
  78. strlcpy(hostname, uts.nodename, len);
  79. #elif defined(HAVE_GETHOSTNAME)
  80. if (gethostname(hostname, len) < 0)
  81. {
  82. rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname");
  83. return -1;
  84. }
  85. #elif defined(HAVE_SYSINFO)
  86. if (sysinfo(SI_HOSTNAME, hostname, len) < 0)
  87. {
  88. rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname");
  89. return -1;
  90. }
  91. #else
  92. return -1;
  93. #endif
  94. return 0;
  95. }
  96. /** Find outbound interface address for a given destination
  97. *
  98. * Given remote address find local address which the system will use as a source address for sending
  99. * datagrams to that remote address.
  100. *
  101. * @param lia local address.
  102. * @param ria the remove address.
  103. * @return 0 in success, -1 on failure, address is filled into the first argument.
  104. */
  105. int rc_get_srcaddr(struct sockaddr *lia, const struct sockaddr *ria)
  106. {
  107. int temp_sock;
  108. socklen_t namelen;
  109. temp_sock = socket(ria->sa_family, SOCK_DGRAM, 0);
  110. if (temp_sock == -1) {
  111. rc_log(LOG_ERR, "rc_get_srcaddr: socket: %s", strerror(errno));
  112. return -1;
  113. }
  114. if (connect(temp_sock, ria, SA_LEN(ria)) != 0) {
  115. rc_log(LOG_ERR, "rc_get_srcaddr: connect: %s",
  116. strerror(errno));
  117. close(temp_sock);
  118. return -1;
  119. }
  120. namelen = SA_LEN(ria);
  121. if (getsockname(temp_sock, lia, &namelen) != 0) {
  122. rc_log(LOG_ERR, "rc_get_srcaddr: getsockname: %s",
  123. strerror(errno));
  124. close(temp_sock);
  125. return -1;
  126. }
  127. close(temp_sock);
  128. return 0;
  129. }
  130. /** rc_own_bind_addr:
  131. * @rh: a handle to parsed configuration
  132. * @lia: the local address to listen to
  133. *
  134. * Get the IP address to be used as a source address
  135. * for sending requests in host order.
  136. *
  137. **/
  138. void rc_own_bind_addr(rc_handle *rh, struct sockaddr_storage *lia)
  139. {
  140. char *txtaddr = rc_conf_str(rh, "bindaddr");
  141. struct addrinfo *info;
  142. if (rh->own_bind_addr_set) {
  143. memcpy(lia, &rh->own_bind_addr, SS_LEN(&rh->own_bind_addr));
  144. return;
  145. }
  146. memset(lia, 0, sizeof(*lia));
  147. if (txtaddr == NULL || txtaddr[0] == '*') {
  148. ((struct sockaddr_in*)lia)->sin_family = AF_INET;
  149. ((struct sockaddr_in*)lia)->sin_addr.s_addr = INADDR_ANY;
  150. } else {
  151. info = rc_getaddrinfo (txtaddr, PW_AI_PASSIVE);
  152. if (info == NULL) {
  153. rc_log(LOG_ERR, "rc_own_ipaddress: couldn't get IP address from bindaddr");
  154. ((struct sockaddr_in*)lia)->sin_family = AF_INET;
  155. ((struct sockaddr_in*)lia)->sin_addr.s_addr = INADDR_ANY;
  156. return;
  157. }
  158. memcpy(lia, info->ai_addr, info->ai_addrlen);
  159. }
  160. return;
  161. }