PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/talk/get_addrs.c

#
C | 247 lines | 154 code | 32 blank | 61 comment | 25 complexity | dccc18c5c848a29283bf3c57042183f8 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
  3. 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
  4. Free Software Foundation, Inc.
  5. This file is part of GNU Inetutils.
  6. GNU Inetutils is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or (at
  9. your option) any later version.
  10. GNU Inetutils is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see `http://www.gnu.org/licenses/'. */
  16. /*
  17. * Copyright (c) 1983, 1993
  18. * The Regents of the University of California. All rights reserved.
  19. *
  20. * Redistribution and use in source and binary forms, with or without
  21. * modification, are permitted provided that the following conditions
  22. * are met:
  23. * 1. Redistributions of source code must retain the above copyright
  24. * notice, this list of conditions and the following disclaimer.
  25. * 2. Redistributions in binary form must reproduce the above copyright
  26. * notice, this list of conditions and the following disclaimer in the
  27. * documentation and/or other materials provided with the distribution.
  28. * 3. Neither the name of the University nor the names of its contributors
  29. * may be used to endorse or promote products derived from this software
  30. * without specific prior written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  33. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  36. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  40. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  42. * SUCH DAMAGE.
  43. */
  44. #include <config.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <sys/types.h>
  48. #include <sys/socket.h>
  49. #include <netinet/in.h>
  50. #include <protocols/talkd.h>
  51. #include <netdb.h>
  52. #include <stdio.h>
  53. #include <unistd.h>
  54. #ifdef HAVE_IDNA_H
  55. # include <idna.h>
  56. #endif
  57. #include "talk_ctl.h"
  58. int
  59. get_addrs (char *my_machine_name, char *his_machine_name)
  60. {
  61. #if HAVE_DECL_GETADDRINFO || defined HAVE_IDN
  62. int err;
  63. #endif
  64. char *lhost, *rhost;
  65. #if HAVE_DECL_GETADDRINFO
  66. struct addrinfo hints, *res, *ai;
  67. #else /* !HAVE_DECL_GETADDRINFO */
  68. struct hostent *hp;
  69. #endif
  70. struct servent *sp;
  71. #ifdef HAVE_IDN
  72. err = idna_to_ascii_lz (my_machine_name, &lhost, 0);
  73. if (err)
  74. {
  75. fprintf (stderr, "talk: %s: %s\n",
  76. my_machine_name, idna_strerror (err));
  77. exit (-1);
  78. }
  79. err = idna_to_ascii_lz (his_machine_name, &rhost, 0);
  80. if (err)
  81. {
  82. fprintf (stderr, "talk: %s: %s\n",
  83. his_machine_name, idna_strerror (err));
  84. exit (-1);
  85. }
  86. #else /* !HAVE_IDN */
  87. lhost = my_machine_name;
  88. rhost = his_machine_name;
  89. #endif
  90. msg.pid = htonl (getpid ());
  91. /* Look up the address of the local host. */
  92. #if HAVE_DECL_GETADDRINFO
  93. memset (&hints, 0, sizeof (hints));
  94. /* The talk-protocol is IPv4 only! */
  95. hints.ai_family = AF_INET;
  96. hints.ai_socktype = SOCK_DGRAM;
  97. # ifdef AI_IDN
  98. hints.ai_flags |= AI_IDN;
  99. # endif
  100. err = getaddrinfo (lhost, NULL, &hints, &res);
  101. if (err)
  102. {
  103. fprintf (stderr, "talk: %s: %s\n", lhost, gai_strerror (err));
  104. exit (-1);
  105. }
  106. /* Perform all sanity checks available.
  107. * Reduction of tests?
  108. */
  109. for (ai = res; ai; ai = ai->ai_next)
  110. {
  111. int f;
  112. if (ai->ai_family != AF_INET)
  113. continue;
  114. f = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  115. if (f < 0)
  116. continue;
  117. /* Attempt binding to this local address. */
  118. if (bind (f, ai->ai_addr, ai->ai_addrlen))
  119. {
  120. close (f);
  121. f = -1;
  122. continue;
  123. }
  124. /* We have a usable address. */
  125. close (f);
  126. break;
  127. }
  128. if (ai)
  129. memcpy (&my_machine_addr,
  130. &((struct sockaddr_in *) ai->ai_addr)->sin_addr,
  131. sizeof (my_machine_addr));
  132. freeaddrinfo (res);
  133. if (!ai)
  134. {
  135. fprintf (stderr, "talk: %s: %s\n", lhost, "address not found");
  136. exit (-1);
  137. }
  138. #else /* !HAVE_DECL_GETADDRINFO */
  139. hp = gethostbyname (lhost);
  140. if (hp == NULL)
  141. {
  142. fprintf (stderr, "talk: %s(%s): ", lhost, my_machine_name);
  143. herror ((char *) NULL);
  144. exit (-1);
  145. }
  146. memmove (&my_machine_addr, hp->h_addr, hp->h_length);
  147. #endif /* !HAVE_DECL_GETADDRINFO */
  148. /*
  149. * If the callee is on-machine, just copy the
  150. * network address, otherwise do a lookup...
  151. */
  152. if (strcmp (rhost, lhost))
  153. {
  154. #if HAVE_DECL_GETADDRINFO
  155. err = getaddrinfo (rhost, NULL, &hints, &res);
  156. if (err)
  157. {
  158. fprintf (stderr, "talk: %s: %s\n", rhost, gai_strerror (err));
  159. exit (-1);
  160. }
  161. /* Perform all sanity checks available. */
  162. for (ai = res; ai; ai = ai->ai_next)
  163. {
  164. int f;
  165. if (ai->ai_family != AF_INET)
  166. continue;
  167. f = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  168. if (f < 0)
  169. continue;
  170. /* We have a usable address family! */
  171. close (f);
  172. break;
  173. }
  174. if (ai)
  175. memcpy (&his_machine_addr,
  176. &((struct sockaddr_in *) ai->ai_addr)->sin_addr,
  177. sizeof (his_machine_addr));
  178. freeaddrinfo (res);
  179. if (!ai)
  180. {
  181. fprintf (stderr, "talk: %s: %s\n", rhost, "address not found");
  182. exit (-1);
  183. }
  184. #else /* !HAVE_DECL_GETADDRINFO */
  185. hp = gethostbyname (rhost);
  186. if (hp == NULL)
  187. {
  188. fprintf (stderr, "talk: %s(%s): ", rhost, his_machine_name);
  189. herror ((char *) NULL);
  190. exit (-1);
  191. }
  192. memmove (&his_machine_addr, hp->h_addr, hp->h_length);
  193. #endif /* !HAVE_DECL_GETADDRINFO */
  194. }
  195. else
  196. his_machine_addr = my_machine_addr;
  197. /* Find the server's port. */
  198. sp = getservbyname ("ntalk", "udp");
  199. if (sp == 0)
  200. {
  201. fprintf (stderr, "talk: %s/%s: service is not registered.\n",
  202. "ntalk", "udp");
  203. exit (-1);
  204. }
  205. daemon_port = ntohs (sp->s_port);
  206. #ifdef HAVE_IDN
  207. free (lhost);
  208. free (rhost);
  209. #endif
  210. return 0;
  211. }