su_localinfo.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@ingroup su_socket
  25. * @CFILE su_localinfo.c
  26. *
  27. * Obtain list of local addresses.
  28. *
  29. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  30. * @author Martti Mela <Martti.Mela@nokia.com>
  31. *
  32. * @date Created: Wed Oct 4 14:09:29 EET 2000 ppessi
  33. */
  34. #include "config.h"
  35. #if HAVE_SYS_SOCKIO_H
  36. #include <sys/sockio.h>
  37. #endif
  38. #include <sofia-sip/su.h>
  39. #include <sofia-sip/su_localinfo.h>
  40. #include <sofia-sip/su_string.h>
  41. #include "su_module_debug.h"
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <assert.h>
  46. #include <stddef.h>
  47. #include <sys/types.h>
  48. #if HAVE_SYS_SOCKET_H
  49. #include <sys/socket.h>
  50. #endif
  51. #if HAVE_NETINET_IN_H
  52. #include <netinet/in.h>
  53. #endif
  54. #if HAVE_SYS_IOCTL_H
  55. #include <sys/ioctl.h>
  56. #endif
  57. #if HAVE_NET_IF_H
  58. #include <net/if.h>
  59. #endif
  60. #if HAVE_NET_IF_TYPES_H
  61. #include <net/if_types.h>
  62. #endif
  63. #if SU_LOCALINFO_TEST
  64. #undef USE_LOCALINFO0
  65. #elif HAVE_GETIFADDRS
  66. #define USE_LOCALINFO0 1
  67. #define localinfo0 bsd_localinfo
  68. static int bsd_localinfo(su_localinfo_t const *, su_localinfo_t **);
  69. #elif HAVE_IPHLPAPI_H
  70. #include <iphlpapi.h>
  71. #define USE_LOCALINFO0 1
  72. #define localinfo0 win_localinfo
  73. static int win_localinfo(su_localinfo_t const *, su_localinfo_t **);
  74. #else
  75. /* No localinfo0(), use localinfo4() and localinfo6() */
  76. #undef USE_LOCALINFO0
  77. static int localinfo4(su_localinfo_t const *, su_localinfo_t **);
  78. # if SU_HAVE_IN6
  79. static int localinfo6(su_localinfo_t const *, su_localinfo_t **);
  80. # endif
  81. #endif
  82. static int li_scope4(uint32_t ip4);
  83. #if SU_HAVE_IN6
  84. static int li_scope6(struct in6_addr const *ip6);
  85. #endif
  86. #if !SU_LOCALINFO_TEST
  87. static int li_name(su_localinfo_t const*, int, su_sockaddr_t const*, char **);
  88. static void li_sort(su_localinfo_t *i, su_localinfo_t **rresult);
  89. /** @brief Request local address information.
  90. *
  91. * Gather the network interfaces and the addresses corresponding to them,
  92. * check if they match to the search criteria specifed by @a hints and
  93. * return a list of matching local address information in the @a
  94. * return_localinfo. The local address information may include IPv4/IPv6
  95. * addresses, interface name, interface index, address scope, and domain
  96. * names corresponding to the local addresses.
  97. *
  98. * @param[in] hints specifies selection criteria
  99. * @param[out] return_localinfo return list of local addresses
  100. *
  101. * @par Selection criteria - hints
  102. *
  103. * The selection criteria @a hints is used to select which addresses are
  104. * returned and what kind of information is included in the @a res list.
  105. *
  106. * @par Selection by flags - hints->li_flags
  107. *
  108. * The @a hints->li_flags contain flags, which can be combined with bit-wise
  109. * or. The currently defined flags are as follows:
  110. *
  111. * - #LI_V4MAPPED: when returning IPv4 addresses, map them as IPv6
  112. * addresses. If this flag is specified, IPv4 addresses are returned even
  113. * if @a hints->li_family is set to @c AF_INET6.
  114. * - #LI_CANONNAME: return the domain name (DNS PTR) corresponding to the
  115. * local address in @a li_canonname.
  116. * - #LI_NAMEREQD: Do not return addresses not in DNS.
  117. * - #LI_NUMERIC: instead of domain name, return the text presentation of
  118. * the addresss in @a li_canonname.
  119. * - #LI_DOWN: include interfaces and their addresses even if the interfaces
  120. * are down. New in @VERSION_1_12_2.
  121. * - #LI_IFNAME: return the interface name in @a li_ifname.
  122. *
  123. * @par Selection by address family - hints->li_family
  124. *
  125. * The address family can have three values: 0, AF_INET and AF_INET6. If
  126. * address family @a hints->li_family, both IPv4 and IPv6 addresses are
  127. * returned.
  128. *
  129. * @par Selection by interface index - hints->li_index
  130. *
  131. * If the field @a hints->li_index is non-zero, only the addresses assigned
  132. * to the interface with given index are returned. The list of interface
  133. * indices and names can be obtained by the function @c su_if_names().
  134. *
  135. * @par Selection by interface name - hints->li_ifname
  136. *
  137. * If the field @a hints->li_ifname is not NULL, only the addresses assigned
  138. * to the named interface are returned. The list of interface names can be
  139. * obtained by the function @c su_if_names().
  140. *
  141. * @par Selection by address scope - hints->li_scope
  142. *
  143. * If the field @a hints->li_scope is nonzero, only the addresses with
  144. * matching scope are returned. The different address scopes can be combined
  145. * with bitwise or. They are defined as follows
  146. * - #LI_SCOPE_HOST: host-local address, valid within host (::1, 127.0.0.1/8)
  147. * - #LI_SCOPE_LINK: link-local address, valid within link
  148. * (IP6 addresses with prefix fe80::/10,
  149. * IP4 addresses in net 169.254.0.0/16).
  150. * - #LI_SCOPE_SITE: site-local address, addresses valid within organization
  151. * (IPv6 addresses with prefix fec::/10,
  152. * private IPv4 addresses in nets 10.0.0.0/8, 172.16.0.0/12,
  153. * and 192.168.0.0/16 as defined in @RFC1918)
  154. * - #LI_SCOPE_GLOBAL: global address.
  155. *
  156. * For instance, setting @a hints->li_scope to @c LI_SCOPE_GLOBAL | @c
  157. * LI_SCOPE_SITE, both the @e global and @e site-local addresses are
  158. * returned.
  159. *
  160. * @sa @RFC1918, @RFC4291, su_sockaddr_scope()
  161. *
  162. * @par Selection by domain name - hints->li_canonname
  163. *
  164. * If this field is non-null, the domain name (DNS PTR) corresponding to
  165. * local IP addresses should match to the name given in this field.
  166. *
  167. * @return Zero (#ELI_NOERROR) when successful, or negative error code when
  168. * failed.
  169. *
  170. * @par Diagnostics
  171. * Use su_gli_strerror() in order to obtain a string describing the error
  172. * code returned by su_getlocalinfo().
  173. *
  174. */
  175. int su_getlocalinfo(su_localinfo_t const *hints,
  176. su_localinfo_t **return_localinfo)
  177. {
  178. int error = 0, ip4 = 0;
  179. int ip6 = 0;
  180. su_localinfo_t *result = NULL, **rr = &result;
  181. su_localinfo_t hh[1] = {{ 0 }};
  182. assert(return_localinfo);
  183. *return_localinfo = NULL;
  184. if (hints) {
  185. /* Copy hints so that it can be modified */
  186. *hh = *hints;
  187. if (hh->li_canonname)
  188. hh->li_flags |= LI_CANONNAME;
  189. #if 0
  190. /* hints->li_ifname is used to select by interface,
  191. li_ifname is returned with LI_IFNAME flag
  192. */
  193. if ((hh->li_flags & LI_IFNAME) && hh->li_ifname == NULL)
  194. return ELI_BADHINTS;
  195. #endif
  196. }
  197. switch (hh->li_family) {
  198. #if SU_HAVE_IN6
  199. case AF_INET6:
  200. if (hh->li_flags & LI_V4MAPPED)
  201. ip6 = ip4 = 1, hh->li_family = 0;
  202. else
  203. ip6 = 1;
  204. break;
  205. #endif
  206. case AF_INET:
  207. #ifndef USE_LOCALINFO0
  208. ip4 = 1;
  209. #endif
  210. break;
  211. case 0:
  212. #ifndef USE_LOCALINFO0
  213. ip4 = 1;
  214. #endif
  215. #if SU_HAVE_IN6
  216. ip6 = 1;
  217. #endif
  218. break;
  219. default:
  220. return -1;
  221. }
  222. #if USE_LOCALINFO0
  223. error = localinfo0(hh, rr);
  224. #else
  225. # if SU_HAVE_IN6
  226. if (ip6) {
  227. error = localinfo6(hh, rr);
  228. if (error == ELI_NOADDRESS && ip4)
  229. error = 0;
  230. if (!error)
  231. /* Search end of list */
  232. for (; *rr; rr = &(*rr)->li_next)
  233. ;
  234. }
  235. # endif
  236. if (ip4 && !error) {
  237. /* Append IPv4 addresses */
  238. error = localinfo4(hh, rr);
  239. }
  240. #endif
  241. if (ip6 && ip4) {
  242. /* Required to make compiler happy */
  243. }
  244. if (!result)
  245. error = ELI_NOADDRESS;
  246. if (!error)
  247. li_sort(result, return_localinfo);
  248. else
  249. su_freelocalinfo(result);
  250. return error;
  251. }
  252. #endif
  253. /** Free local address information.
  254. *
  255. * Free a list of su_localinfo_t structures obtained with su_getlocalinfo()
  256. * or su_copylocalinfo() along with socket addresses and strings associated
  257. * with them.
  258. *
  259. * @sa su_getlocalinfo(), su_copylocalinfo(), #su_localinfo_t
  260. */
  261. void su_freelocalinfo(su_localinfo_t *tbf)
  262. {
  263. su_localinfo_t *li;
  264. for (li = tbf; li; li = tbf) {
  265. tbf = li->li_next;
  266. if (li->li_canonname)
  267. free(li->li_canonname);
  268. free(li);
  269. }
  270. }
  271. /** Describe su_localinfo errors.
  272. *
  273. * The function su_gli_strerror() returns a string describing the error
  274. * condition indicated by the code that was returned by the function
  275. * su_getlocalinfo().
  276. *
  277. * @param error error code returned by su_getlocalinfo()
  278. *
  279. * @return
  280. * A pointer to string describing the error condition.
  281. */
  282. char const *su_gli_strerror(int error)
  283. {
  284. switch (error) {
  285. case ELI_NOERROR: return "No error";
  286. case ELI_NOADDRESS: return "No matching address";
  287. case ELI_MEMORY: return "Memory allocation error";
  288. case ELI_FAMILY: return "Unknown address family";
  289. case ELI_RESOLVER: return "Error when resolving address";
  290. case ELI_SYSTEM: return "System error";
  291. case ELI_BADHINTS: return "Invalid value for hints";
  292. default: return "Unknown error";
  293. }
  294. }
  295. /** Duplicate su_localinfo structure.
  296. */
  297. su_localinfo_t *su_copylocalinfo(su_localinfo_t const *li0)
  298. {
  299. size_t n;
  300. su_localinfo_t *li, *retval = NULL, **lli = &retval;
  301. # define SLEN(s) ((s) ? strlen(s) + 1 : 0)
  302. for (; li0 ; li0 = li0->li_next) {
  303. n = sizeof(*li0) + li0->li_addrlen + SLEN(li0->li_ifname);
  304. if (!(li = calloc(1, n))) {
  305. su_freelocalinfo(retval);
  306. return NULL;
  307. }
  308. *lli = li;
  309. lli = &li->li_next;
  310. li->li_flags = li0->li_flags;
  311. li->li_family = li0->li_family;
  312. li->li_index = li0->li_index;
  313. li->li_scope = li0->li_scope;
  314. li->li_addrlen = li0->li_addrlen;
  315. li->li_addr = memcpy(li + 1, li0->li_addr, li0->li_addrlen);
  316. if (li0->li_canonname) {
  317. if (!(li->li_canonname = malloc(SLEN(li0->li_canonname)))) {
  318. su_freelocalinfo(retval);
  319. return NULL;
  320. }
  321. strcpy(li->li_canonname, li0->li_canonname);
  322. }
  323. if (li0->li_ifname)
  324. li->li_ifname = strcpy(li->li_addrlen + (char *)li->li_addr,
  325. li0->li_ifname);
  326. }
  327. return retval;
  328. }
  329. /** Return IPv4 address scope */
  330. static int
  331. li_scope4(uint32_t ip4)
  332. {
  333. ip4 = ntohl(ip4);
  334. if (0x7f000000 == (ip4 & 0xff000000))
  335. return LI_SCOPE_HOST;
  336. /* draft-ietf-zeroconf-ipv4-linklocal-02.txt - 169.254/16. */
  337. else if (0xa9fe0000 == (ip4 & 0xffff0000))
  338. return LI_SCOPE_LINK;
  339. /* RFC1918 - 10/8, 172.16/12, 192.168/16. */
  340. else if (0x0a000000 == (ip4 & 0xff000000) ||
  341. 0xac100000 == (ip4 & 0xfff00000) ||
  342. 0xc0a80000 == (ip4 & 0xffff0000))
  343. return LI_SCOPE_SITE;
  344. else
  345. return LI_SCOPE_GLOBAL;
  346. }
  347. #if SU_HAVE_IN6
  348. #if HAVE_WINSOCK2_H
  349. #define IN6_IS_ADDR_LOOPBACK SU_IN6_IS_ADDR_LOOPBACK
  350. su_inline int
  351. IN6_IS_ADDR_LOOPBACK(void const *ip6)
  352. {
  353. uint8_t const *u = ip6;
  354. return
  355. u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0 &&
  356. u[4] == 0 && u[5] == 0 && u[6] == 0 && u[7] == 0 &&
  357. u[8] == 0 && u[9] == 0 && u[10] == 0 && u[11] == 0 &&
  358. u[12] == 0 && u[13] == 0 && u[14] == 0 && u[15] == 1;
  359. }
  360. #endif
  361. /** Return IPv6 address scope */
  362. static int
  363. li_scope6(struct in6_addr const *ip6)
  364. {
  365. if (IN6_IS_ADDR_V4MAPPED(ip6) || IN6_IS_ADDR_V4COMPAT(ip6)) {
  366. uint32_t *u = (uint32_t *)(ip6->s6_addr + 12);
  367. uint32_t ip4 = *u;
  368. return li_scope4(ip4);
  369. }
  370. else if (IN6_IS_ADDR_LOOPBACK(ip6))
  371. return LI_SCOPE_HOST;
  372. else if (IN6_IS_ADDR_LINKLOCAL(ip6))
  373. return LI_SCOPE_LINK;
  374. else if (IN6_IS_ADDR_SITELOCAL(ip6))
  375. return LI_SCOPE_SITE;
  376. else
  377. return LI_SCOPE_GLOBAL;
  378. }
  379. #endif
  380. /** Return the scope of address in the sockaddr structure */
  381. int su_sockaddr_scope(su_sockaddr_t const *su, socklen_t sulen)
  382. {
  383. if (sulen >= (sizeof su->su_sin) && su->su_family == AF_INET)
  384. return li_scope4(su->su_sin.sin_addr.s_addr);
  385. #if SU_HAVE_IN6
  386. if (sulen >= (sizeof su->su_sin6) && su->su_family == AF_INET6)
  387. return li_scope6(&su->su_sin6.sin6_addr);
  388. #endif
  389. return 0;
  390. }
  391. #if HAVE_OPEN_C
  392. extern int su_get_local_ip_addr(su_sockaddr_t *su);
  393. #endif
  394. #if SU_LOCALINFO_TEST
  395. #elif USE_LOCALINFO0
  396. /* no localinfo4 */
  397. #elif HAVE_IFCONF
  398. #if __APPLE_CC__
  399. /** Build a list of local IPv4 addresses and append it to *rresult. */
  400. static
  401. int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
  402. {
  403. su_localinfo_t *li = NULL;
  404. su_sockaddr_t *su;
  405. int error = ELI_NOADDRESS;
  406. char *canonname = NULL;
  407. su_socket_t s;
  408. #if SU_HAVE_IN6
  409. int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
  410. #else
  411. int const su_xtra = 0;
  412. #endif
  413. struct ifconf ifc;
  414. int numifs;
  415. char *buffer;
  416. struct ifreq *ifr, *ifr_next;
  417. su_sockaddr_t *sa;
  418. socklen_t salen = sizeof(*sa);
  419. int scope = 0, gni_flags = 0;
  420. s = su_socket(AF_INET, SOCK_DGRAM, 0);
  421. if (s == -1) {
  422. SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",
  423. su_strerror(su_errno())));
  424. return ELI_SYSTEM;
  425. }
  426. li = calloc(1, (sizeof *li) + (sizeof *sa));
  427. sa = (void *)(li + 1);
  428. error = getsockname(s, (struct sockaddr *) sa, &salen);
  429. if (error < 0 && errno == SOCKET_ERROR) {
  430. SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
  431. su_strerror(su_errno())));
  432. }
  433. error = bind(s, (struct sockaddr *) sa, salen);
  434. if (error < 0) {
  435. SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
  436. su_strerror(su_errno())));
  437. goto err;
  438. }
  439. su_close(s);
  440. scope = li_scope4(sa->su_sin.sin_addr.s_addr);
  441. if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
  442. gni_flags = NI_NUMERICHOST;
  443. if (su_xtra) {
  444. /* Map IPv4 address to IPv6 address */
  445. memset(sa, 0, sizeof(*sa));
  446. sa->su_family = AF_INET6;
  447. ((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
  448. ((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff);
  449. }
  450. li->li_family = sa->su_family;
  451. li->li_scope = scope;
  452. li->li_index = 0;
  453. li->li_addrlen = su_sockaddr_size(sa);
  454. li->li_addr = sa;
  455. if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
  456. goto err;
  457. if (canonname) {
  458. if (strchr(canonname, ':') ||
  459. strspn(canonname, "0123456789.") == strlen(canonname))
  460. li->li_flags |= LI_NUMERIC;
  461. }
  462. else
  463. li->li_flags = 0;
  464. li->li_canonname = canonname;
  465. canonname = NULL;
  466. *rresult = li;
  467. return 0;
  468. err:
  469. if (canonname) free(canonname);
  470. if (li) free(li);
  471. su_close(s);
  472. return error;
  473. }
  474. #else /* !__APPLE_CC__ */
  475. /** Build a list of local IPv4 addresses and append it to *rresult. */
  476. static
  477. int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
  478. {
  479. su_localinfo_t *tbf = NULL, **lli = &tbf;
  480. su_localinfo_t *li = NULL, *li_first = NULL;
  481. su_sockaddr_t *su;
  482. int error = ELI_NOADDRESS;
  483. char *canonname = NULL;
  484. su_socket_t s;
  485. #if SU_HAVE_IN6
  486. int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
  487. #else
  488. int const su_xtra = 0;
  489. #endif
  490. struct ifconf ifc;
  491. int numifs;
  492. char *buffer;
  493. struct ifreq *ifr, *ifr_next;
  494. #if HAVE_OPEN_C
  495. su_sockaddr_t *sa;
  496. socklen_t salen = sizeof(*sa);
  497. #endif
  498. s = su_socket(AF_INET, SOCK_DGRAM, 0);
  499. if (s == -1) {
  500. SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",
  501. su_strerror(su_errno())));
  502. return ELI_SYSTEM;
  503. }
  504. # if HAVE_IFNUM
  505. /* Get the list of known IP address from the kernel */
  506. if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) {
  507. /* can't get number of interfaces -- fall back */
  508. SU_DEBUG_1(("su_localinfo: SIOCGIFNUM failed: %s\n",
  509. su_strerror(su_errno())));
  510. error = ELI_SYSTEM;
  511. goto err;
  512. }
  513. SU_DEBUG_9(("su_localinfo: %d active interfaces according to SIOCGIFNUM\n",
  514. numifs));
  515. if (numifs < 0)
  516. # endif
  517. /* Default to 64 interfaces. Enough? */
  518. numifs = 64;
  519. if (numifs == 0)
  520. return 0;
  521. /*
  522. * Allocate memory for SIOCGIFCONF ioctl buffer. This memory block is also
  523. * used as li_first, first localinfo struct that is returned, so it can be
  524. * freed by freelocalinfo() without any complications.
  525. */
  526. ifc.ifc_len = numifs * sizeof (struct ifreq);
  527. buffer = malloc(sizeof(su_localinfo_t) + ifc.ifc_len + su_xtra);
  528. if (!buffer) {
  529. SU_DEBUG_1(("su_localinfo: memory exhausted\n" VA_NONE));
  530. error = ELI_MEMORY;
  531. goto err;
  532. }
  533. li_first = (su_localinfo_t *)buffer;
  534. memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra);
  535. ifc.ifc_buf = buffer + sizeof(su_localinfo_t) + su_xtra;
  536. #if HAVE_OPEN_C
  537. if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) {
  538. SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",
  539. su_strerror(su_errno())));
  540. error = ELI_SYSTEM;
  541. goto err;
  542. }
  543. #else
  544. if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
  545. SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",
  546. su_strerror(su_errno())));
  547. error = ELI_SYSTEM;
  548. goto err;
  549. }
  550. #endif
  551. buffer = ifc.ifc_buf + ifc.ifc_len;
  552. for (ifr = ifc.ifc_req;
  553. (void *)ifr < (void *)buffer;
  554. ifr = ifr_next) {
  555. struct ifreq ifreq[1];
  556. int scope, if_index, flags = 0, gni_flags = 0;
  557. char *if_name;
  558. #if SU_HAVE_IN6
  559. su_sockaddr_t su2[1];
  560. #endif
  561. #if SA_LEN
  562. if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
  563. ifr_next = (struct ifreq *)
  564. (ifr->ifr_addr.sa_len + (char *)(&ifr->ifr_addr));
  565. else
  566. #else
  567. ifr_next = ifr + 1;
  568. #endif
  569. if_name = ifr->ifr_name;
  570. #if defined(SIOCGIFINDEX)
  571. ifreq[0] = *ifr;
  572. if (ioctl(s, SIOCGIFINDEX, ifreq) < 0) {
  573. SU_DEBUG_1(("su_localinfo: SIOCGIFINDEX failed: %s\n",
  574. su_strerror(su_errno())));
  575. error = ELI_SYSTEM;
  576. goto err;
  577. }
  578. #if HAVE_IFR_INDEX
  579. if_index = ifreq->ifr_index;
  580. #elif HAVE_IFR_IFINDEX
  581. if_index = ifreq->ifr_ifindex;
  582. #else
  583. #error Unknown index field in struct ifreq
  584. #endif
  585. #else
  586. #warning su_localinfo() cannot map interface name to number
  587. if_index = 0;
  588. #endif
  589. SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index));
  590. #if HAVE_OPEN_C
  591. su_close(s);
  592. li = calloc(1, sizeof(su_localinfo_t));
  593. sa = calloc(1, sizeof(su_sockaddr_t));
  594. if (su_get_local_ip_addr(sa) < 0)
  595. goto err;
  596. li->li_family = sa->su_family;
  597. li->li_scope = LI_SCOPE_GLOBAL /* scope */;
  598. li->li_index = if_index;
  599. li->li_addrlen = su_sockaddr_size(sa);
  600. li->li_addr = sa;
  601. if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
  602. goto err;
  603. if (canonname) {
  604. if (strchr(canonname, ':') ||
  605. strspn(canonname, "0123456789.") == strlen(canonname))
  606. li->li_flags |= LI_NUMERIC;
  607. }
  608. else
  609. li->li_flags = 0;
  610. li->li_canonname = canonname;
  611. canonname = NULL;
  612. *rresult = li;
  613. return 0;
  614. #endif
  615. #if defined(SIOCGIFFLAGS)
  616. ifreq[0] = *ifr;
  617. if (ioctl(s, SIOCGIFFLAGS, ifreq) < 0) {
  618. SU_DEBUG_1(("su_localinfo: SIOCGIFFLAGS failed: %s\n",
  619. su_strerror(su_errno())));
  620. error = ELI_SYSTEM;
  621. goto err;
  622. }
  623. /* Do not include interfaces that are down unless explicitly asked */
  624. if ((ifreq->ifr_flags & IFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0) {
  625. SU_DEBUG_9(("su_localinfo: if %s with index %d is down\n",
  626. if_name, if_index));
  627. continue;
  628. }
  629. #elif defined(SIOCGIFACTIVECONF)
  630. /* Handled above in SIOCGIFACTIVECONF vs. SIOCGIFCONF*/
  631. #else
  632. #error su_localinfo() cannot determine interface status
  633. #endif
  634. #if 0
  635. *ifreq = *ifr;
  636. ifreq->ifr_addr.sa_family = AF_INET;
  637. if (ioctl(s, SIOCGIFADDR, ifreq) < 0) {
  638. SU_DEBUG_1(("su_localinfo: SIOCGIFADDR failed: %s\n",
  639. su_strerror(su_errno())));
  640. error = ELI_SYSTEM;
  641. goto err;
  642. }
  643. ifr->ifr_addr = ifreq->ifr_addr;
  644. #endif
  645. su = (su_sockaddr_t *)&ifr->ifr_addr;
  646. if (SU_HAS_INADDR_ANY(su))
  647. continue;
  648. scope = li_scope4(su->su_sin.sin_addr.s_addr);
  649. if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
  650. (hints->li_ifname && strcmp(hints->li_ifname, if_name) != 0) ||
  651. (hints->li_index && hints->li_index != if_index))
  652. continue;
  653. #if SU_HAVE_IN6
  654. if (su_xtra) {
  655. /* Map IPv4 address to IPv6 address */
  656. memset(su2, 0, sizeof(*su2));
  657. su2->su_family = AF_INET6;
  658. ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
  659. ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
  660. su = su2;
  661. }
  662. #endif
  663. if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
  664. gni_flags = NI_NUMERICHOST;
  665. if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
  666. goto err;
  667. else if (error > 0)
  668. continue;
  669. if (canonname)
  670. if (strchr(canonname, ':') ||
  671. strspn(canonname, "0123456789.") == strlen(canonname))
  672. flags |= LI_NUMERIC;
  673. if (li_first)
  674. li = li_first; /* Use li_first with all ifr structs to be freed */
  675. else if (!(li = calloc(1, (sizeof *li) + su_xtra))) {
  676. error = ELI_MEMORY;
  677. goto err;
  678. }
  679. if (!tbf) tbf = li;
  680. *lli = li; lli = &li->li_next;
  681. if (su_xtra)
  682. su = (su_sockaddr_t *)memcpy(li + 1, su, su_xtra);
  683. li->li_flags = flags;
  684. li->li_family = su->su_family;
  685. li->li_scope = scope;
  686. li->li_index = if_index;
  687. li->li_addrlen = su_sockaddr_size(su);
  688. li->li_addr = su;
  689. li->li_canonname = canonname;
  690. li->li_ifname = if_name;
  691. canonname = NULL;
  692. li_first = NULL;
  693. }
  694. if (canonname) free(canonname);
  695. if (li_first) free(li_first);
  696. su_close(s);
  697. if (tbf) *rresult = tbf;
  698. return 0;
  699. err:
  700. if (canonname) free(canonname);
  701. if (li_first) free(li_first);
  702. su_freelocalinfo(tbf);
  703. su_close(s);
  704. return error;
  705. }
  706. #endif /* __APPLE_CC__ */
  707. #else
  708. static
  709. int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
  710. {
  711. /* Kikka #3: resolve hostname */
  712. char hostname[SU_MAXHOST] = "";
  713. char *name, *ifname;
  714. struct hostent *h;
  715. int i, flags, error, gni_flags = 0;
  716. su_localinfo_t *tbf = NULL;
  717. su_localinfo_t *li = NULL, **lli = &tbf;
  718. su_sockaddr_t *su;
  719. #if SU_HAVE_IN6
  720. socklen_t su_sockaddr_size =
  721. (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : sizeof(struct sockaddr_in);
  722. flags = hints->li_flags & (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
  723. #else
  724. socklen_t su_sockaddr_size = sizeof(struct sockaddr_in);
  725. flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
  726. #endif
  727. error = ELI_NOERROR;
  728. if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
  729. if (hints->li_canonname)
  730. name = hints->li_canonname;
  731. else if (gethostname(name = hostname, sizeof(hostname)) != 0)
  732. return ELI_SYSTEM;
  733. h = gethostbyname(name);
  734. if (name)
  735. if (strchr(name, ':') ||
  736. strspn(name, "0123456789.") == strlen(name))
  737. flags |= LI_NUMERIC;
  738. for (i = 0; h && h->h_addr_list[i]; i++) {
  739. if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {
  740. error = ELI_MEMORY;
  741. goto err;
  742. }
  743. li->li_flags = flags;
  744. li->li_scope = li_scope4(*(uint32_t *)h->h_addr_list[i]);
  745. if (li->li_scope == LI_SCOPE_HOST)
  746. li->li_index = 1, ifname = "lo";
  747. else
  748. li->li_index = 2, ifname = "eth";
  749. li->li_addrlen = su_sockaddr_size;
  750. li->li_addr = su = (su_sockaddr_t *)(li + 1);
  751. su->su_family = li->li_family =
  752. li->li_flags & LI_V4MAPPED ? AF_INET6 : AF_INET;
  753. #if SU_HAVE_IN6
  754. if (li->li_flags & LI_V4MAPPED) {
  755. ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);
  756. memcpy(&((int32_t*)&su->su_sin6.sin6_addr)[3],
  757. h->h_addr_list[i], h->h_length);
  758. }
  759. else
  760. #endif
  761. memcpy(&su->su_sin.sin_addr.s_addr, h->h_addr_list[i], h->h_length);
  762. if (li->li_flags & LI_IFNAME)
  763. li->li_ifname = ifname;
  764. if (li->li_scope == LI_SCOPE_HOST || li->li_scope == LI_SCOPE_LINK)
  765. gni_flags = NI_NUMERICHOST;
  766. if ((error = li_name(hints, gni_flags, su, &li->li_canonname)) < 0)
  767. goto err;
  768. else if (error > 0) {
  769. free(li); li = NULL; continue;
  770. } else
  771. error = ELI_NOADDRESS;
  772. *lli = li; lli = &li->li_next; li = NULL;
  773. }
  774. }
  775. if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_HOST)) {
  776. if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {
  777. error = ELI_MEMORY;
  778. goto err;
  779. }
  780. li->li_flags = hints->li_flags &
  781. (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
  782. li->li_scope = LI_SCOPE_HOST, li->li_index = 1;
  783. if (li->li_flags & LI_IFNAME)
  784. li->li_ifname = "lo";
  785. li->li_addrlen = su_sockaddr_size;
  786. li->li_addr = su = (su_sockaddr_t *)(li + 1);
  787. #if SU_HAVE_IN6
  788. if (li->li_flags & LI_V4MAPPED) {
  789. su->su_family = li->li_family = AF_INET6;
  790. ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);
  791. ((int32_t*)&su->su_sin6.sin6_addr)[3] = htonl(0x7f000001);
  792. }
  793. else
  794. #endif
  795. su->su_family = li->li_family = AF_INET,
  796. su->su_sin.sin_addr.s_addr = htonl(0x7f000001);
  797. if ((error = li_name(hints, NI_NUMERICHOST, su, &li->li_canonname)) < 0) {
  798. goto err;
  799. } else if (error > 0) {
  800. free(li); li = NULL;
  801. } else {
  802. *lli = li; lli = &li->li_next; li = NULL;
  803. }
  804. }
  805. *rresult = tbf;
  806. return 0;
  807. err:
  808. if (li) su_freelocalinfo(li);
  809. su_freelocalinfo(tbf);
  810. return error;
  811. }
  812. #endif
  813. #if USE_LOCALINFO0 || !SU_HAVE_IN6 || SU_LOCALINFO_TEST
  814. /* No localinfo6() */
  815. #elif HAVE_PROC_NET_IF_INET6
  816. /** Build a list of local IPv6 addresses and append it to *return_result. */
  817. static
  818. int localinfo6(su_localinfo_t const *hints, su_localinfo_t **return_result)
  819. {
  820. su_localinfo_t *li = NULL;
  821. su_sockaddr_t su[1] = {{ 0 }}, *addr;
  822. int error = ELI_NOADDRESS;
  823. char *canonname = NULL;
  824. char line[80];
  825. FILE *f;
  826. if ((f = fopen("/proc/net/if_inet6", "r"))) {
  827. for (;error;) {
  828. struct in6_addr in6;
  829. unsigned if_index, prefix_len, scope, flags;
  830. int addrlen, if_namelen;
  831. char ifname[16];
  832. if (!fgets(line, sizeof(line), f)) {
  833. if (feof(f))
  834. error = ELI_NOERROR;
  835. break;
  836. }
  837. if (sscanf(line, "%08x%08x%08x%08x %2x %2x %2x %02x %016s\n",
  838. &in6.s6_addr32[0],
  839. &in6.s6_addr32[1],
  840. &in6.s6_addr32[2],
  841. &in6.s6_addr32[3],
  842. &if_index, &prefix_len, &scope, &flags, ifname) != 9)
  843. break;
  844. flags = 0;
  845. /* Fix global scope (it is 0) */
  846. if (!scope) scope = LI_SCOPE_GLOBAL;
  847. in6.s6_addr32[0] = htonl(in6.s6_addr32[0]);
  848. in6.s6_addr32[1] = htonl(in6.s6_addr32[1]);
  849. in6.s6_addr32[2] = htonl(in6.s6_addr32[2]);
  850. in6.s6_addr32[3] = htonl(in6.s6_addr32[3]);
  851. if (IN6_IS_ADDR_V4MAPPED(&in6) || IN6_IS_ADDR_V4COMPAT(&in6)) {
  852. uint32_t ip4 = *(uint32_t *)(in6.s6_addr + 12);
  853. scope = li_scope4(ip4);
  854. }
  855. if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
  856. (hints->li_index && hints->li_index != if_index) ||
  857. (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0))
  858. continue;
  859. su->su_family = AF_INET6;
  860. su->su_sin6.sin6_addr = in6;
  861. addrlen = su_sockaddr_size(su);
  862. if ((error = li_name(hints, 0, su, &canonname)) < 0)
  863. break;
  864. else if (error > 0)
  865. continue;
  866. else
  867. error = ELI_NOADDRESS;
  868. if (canonname &&
  869. (strchr(canonname, ':') ||
  870. strspn(canonname, "0123456789.") == strlen(canonname)))
  871. flags |= LI_NUMERIC;
  872. if (hints->li_flags & LI_IFNAME)
  873. if_namelen = strlen(ifname) + 1;
  874. else
  875. if_namelen = 0;
  876. if ((li = calloc(1, sizeof *li + addrlen + if_namelen)) == NULL) {
  877. error = ELI_MEMORY;
  878. break;
  879. }
  880. addr = (su_sockaddr_t*)memcpy((li + 1), su, addrlen);
  881. *return_result = li; return_result = &li->li_next;
  882. li->li_flags = flags;
  883. li->li_family = AF_INET6;
  884. li->li_scope = scope;
  885. li->li_index = if_index;
  886. li->li_addr = addr;
  887. li->li_addrlen = addrlen;
  888. li->li_canonname = canonname;
  889. if (if_namelen)
  890. li->li_ifname = memcpy(addrlen + (char *)addr, ifname, if_namelen);
  891. canonname = NULL;
  892. }
  893. fclose(f);
  894. }
  895. if (canonname)
  896. free(canonname);
  897. return error;
  898. }
  899. #else
  900. /* Use HOSTADDR6 */
  901. static
  902. int localinfo6(su_localinfo_t const *hints, su_localinfo_t **rresult)
  903. {
  904. char *addr, *ifname;
  905. int flags, error;
  906. su_localinfo_t *li = NULL;
  907. su_sockaddr_t *su;
  908. int const su_sockaddr_size = sizeof(*su);
  909. error = ELI_NOADDRESS;
  910. #if defined(__APPLE_CC__)
  911. {
  912. su_sockaddr_t *sa;
  913. int salen = sizeof(*sa);
  914. int s;
  915. if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
  916. if ((addr = getenv("HOSTADDR6"))) {
  917. li = calloc(1, sizeof(su_localinfo_t));
  918. sa = calloc(1, sizeof(su_sockaddr_t));
  919. sa->su_family = AF_INET6;
  920. if (su_inet_pton(AF_INET6, addr, &sa->su_sin6.sin6_addr) <= 0)
  921. goto err;
  922. s = su_socket(AF_INET6, SOCK_DGRAM, 0);
  923. if (s == -1) {
  924. SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",
  925. su_strerror(su_errno())));
  926. return ELI_SYSTEM;
  927. }
  928. error = getsockname(s, (struct sockaddr *) sa, &salen);
  929. if (error < 0 && errno == SOCKET_ERROR) {
  930. SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
  931. su_strerror(su_errno())));
  932. }
  933. error = bind(s, (struct sockaddr *) sa, salen);
  934. if (error < 0) {
  935. SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
  936. su_strerror(su_errno())));
  937. goto err;
  938. }
  939. su_close(s);
  940. li->li_family = sa->su_family;
  941. li->li_scope = LI_SCOPE_GLOBAL;
  942. li->li_index = 0;
  943. li->li_addrlen = su_sockaddr_size(sa);
  944. li->li_addr = sa;
  945. if ((error = li_name(hints, NI_NUMERICHOST, sa, &li->li_canonname)) < 0)
  946. goto err;
  947. li->li_flags = NI_NUMERICHOST;
  948. }
  949. }
  950. *rresult = li;
  951. return 0;
  952. }
  953. #endif
  954. if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
  955. if ((addr = getenv("HOSTADDR6"))) {
  956. flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
  957. if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) {
  958. error = ELI_MEMORY;
  959. goto err;
  960. }
  961. li->li_flags = flags;
  962. li->li_scope = LI_SCOPE_GLOBAL, li->li_index = 2, ifname = "eth";
  963. li->li_addrlen = sizeof(*su);
  964. li->li_addr = su = (su_sockaddr_t *)(li + 1);
  965. su->su_family = li->li_family = AF_INET6;
  966. if (su_inet_pton(AF_INET6, addr, &su->su_sin6.sin6_addr) <= 0)
  967. goto err;
  968. if (li->li_flags & LI_IFNAME)
  969. li->li_ifname = ifname;
  970. if ((error = li_name(hints, NI_NUMERICHOST, su, &li->li_canonname)) < 0)
  971. goto err;
  972. else if (error > 0) {
  973. free(li); li = NULL;
  974. }
  975. }
  976. }
  977. *rresult = li;
  978. return 0;
  979. err:
  980. if (li) su_freelocalinfo(li);
  981. return error;
  982. }
  983. #endif
  984. #if !USE_LOCALINFO0
  985. /* no localinfo0() or bsd_localinfo() */
  986. #elif HAVE_GETIFADDRS
  987. #include <ifaddrs.h>
  988. static
  989. int bsd_localinfo(su_localinfo_t const hints[1],
  990. su_localinfo_t **return_result)
  991. {
  992. struct ifaddrs *ifa, *results;
  993. int error = 0;
  994. #if SU_HAVE_IN6
  995. int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
  996. #endif
  997. char *canonname = NULL;
  998. if (getifaddrs(&results) < 0) {
  999. if (errno == ENOMEM)
  1000. return ELI_MEMORY;
  1001. else
  1002. return ELI_SYSTEM;
  1003. }
  1004. for (ifa = results; ifa; ifa = ifa->ifa_next) {
  1005. su_localinfo_t *li;
  1006. su_sockaddr_t *su;
  1007. #if SU_HAVE_IN6
  1008. su_sockaddr_t su2[1];
  1009. #endif
  1010. socklen_t sulen;
  1011. int scope, flags = 0, gni_flags = 0, if_index = 0;
  1012. char const *ifname = 0;
  1013. size_t ifnamelen = 0;
  1014. /* no ip address from if that is down */
  1015. if ((ifa->ifa_flags & IFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0)
  1016. continue;
  1017. su = (su_sockaddr_t *)ifa->ifa_addr;
  1018. if (!su)
  1019. continue;
  1020. if (su->su_family == AF_INET) {
  1021. sulen = sizeof(su->su_sin);
  1022. scope = li_scope4(su->su_sin.sin_addr.s_addr);
  1023. #if SU_HAVE_IN6
  1024. if (v4_mapped)
  1025. sulen = sizeof(su->su_sin6);
  1026. #endif
  1027. }
  1028. #if SU_HAVE_IN6
  1029. else if (su->su_family == AF_INET6) {
  1030. if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr))
  1031. continue;
  1032. sulen = sizeof(su->su_sin6);
  1033. scope = li_scope6(&su->su_sin6.sin6_addr);
  1034. }
  1035. #endif
  1036. else
  1037. continue;
  1038. if (hints->li_flags & LI_IFNAME) {
  1039. ifname = ifa->ifa_name;
  1040. if (ifname)
  1041. ifnamelen = strlen(ifname) + 1;
  1042. }
  1043. if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
  1044. (hints->li_family && hints->li_family != su->su_family) ||
  1045. (hints->li_ifname && (!ifname || strcmp(hints->li_ifname, ifname))) ||
  1046. (hints->li_index && hints->li_index != if_index))
  1047. continue;
  1048. if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
  1049. gni_flags = NI_NUMERICHOST;
  1050. #if SU_HAVE_IN6
  1051. if (v4_mapped && su->su_family == AF_INET) {
  1052. /* Map IPv4 address to IPv6 address */
  1053. memset(su2, 0, sizeof(*su2));
  1054. su2->su_family = AF_INET6;
  1055. ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
  1056. ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
  1057. su = su2;
  1058. }
  1059. #endif
  1060. if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
  1061. break;
  1062. if (error > 0) {
  1063. error = 0;
  1064. continue;
  1065. }
  1066. if (canonname)
  1067. if (strchr(canonname, ':') ||
  1068. canonname[strspn(canonname, "0123456789.")] == '\0')
  1069. flags |= LI_NUMERIC;
  1070. if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {
  1071. SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n" VA_NONE));
  1072. error = ELI_MEMORY;
  1073. break;
  1074. }
  1075. *return_result = li, return_result = &li->li_next;
  1076. li->li_flags = flags;
  1077. li->li_family = su->su_family;
  1078. li->li_scope = scope;
  1079. li->li_index = if_index;
  1080. li->li_addrlen = sulen;
  1081. li->li_addr = memcpy(li + 1, su, sulen);
  1082. li->li_canonname = canonname;
  1083. if (ifnamelen) {
  1084. li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);
  1085. }
  1086. canonname = NULL;
  1087. }
  1088. if (canonname)
  1089. free(canonname);
  1090. freeifaddrs(results);
  1091. return error;
  1092. }
  1093. #elif USE_LOCALINFO0 && HAVE_IPHLPAPI_H && SU_HAVE_IN6
  1094. static
  1095. char const *ws2ifname(DWORD iftype)
  1096. {
  1097. switch (iftype) {
  1098. case IF_TYPE_ETHERNET_CSMACD: return "eth";
  1099. case IF_TYPE_IEEE80212: return "eth";
  1100. case IF_TYPE_FASTETHER: return "eth";
  1101. case IF_TYPE_GIGABITETHERNET: return "eth";
  1102. case IF_TYPE_ISO88025_TOKENRING: return "token";
  1103. case IF_TYPE_FDDI: return "fddi";
  1104. case IF_TYPE_PPP: return "ppp";
  1105. case IF_TYPE_SOFTWARE_LOOPBACK: return "lo";
  1106. case IF_TYPE_SLIP: return "sl";
  1107. case IF_TYPE_FRAMERELAY: return "fr";
  1108. case IF_TYPE_ATM: return "atm";
  1109. case IF_TYPE_HIPPI: return "hippi";
  1110. case IF_TYPE_ISDN: return "isdn";
  1111. case IF_TYPE_IEEE80211: return "wlan";
  1112. case IF_TYPE_ADSL: return "adsl";
  1113. case IF_TYPE_RADSL: return "radsl";
  1114. case IF_TYPE_SDSL: return "sdsl";
  1115. case IF_TYPE_VDSL: return "vdsl";
  1116. case IF_TYPE_TUNNEL: return "tunnel";
  1117. case IF_TYPE_IEEE1394: return "fw";
  1118. case IF_TYPE_OTHER:
  1119. default: return "other";
  1120. }
  1121. }
  1122. static
  1123. int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
  1124. {
  1125. /* This is Windows XP code, for both IPv6 and IPv4. */
  1126. ULONG iaa_size = 2048;
  1127. IP_ADAPTER_ADDRESSES *iaa0, *iaa;
  1128. int error, loopback_seen = 0;
  1129. int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
  1130. char *canonname = NULL;
  1131. su_localinfo_t *li, **next;
  1132. int flags = GAA_FLAG_SKIP_MULTICAST;
  1133. *rresult = NULL; next = rresult;
  1134. iaa0 = malloc((size_t)iaa_size);
  1135. if (!iaa0) {
  1136. SU_DEBUG_1(("su_localinfo: memory exhausted\n"));
  1137. error = ELI_MEMORY;
  1138. goto err;
  1139. }
  1140. error = GetAdaptersAddresses(hints->li_family, flags, NULL, iaa0, &iaa_size);
  1141. if (error == ERROR_BUFFER_OVERFLOW) {
  1142. if ((iaa0 = realloc(iaa0, iaa_size)))
  1143. error = GetAdaptersAddresses(hints->li_family, flags, NULL, iaa0, &iaa_size);
  1144. }
  1145. if (error) {
  1146. char const *empty = "";
  1147. LPTSTR msg = empty;
  1148. if (error == ERROR_NO_DATA) {
  1149. error = ELI_NOADDRESS;
  1150. goto err;
  1151. }
  1152. if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1153. FORMAT_MESSAGE_FROM_SYSTEM |
  1154. FORMAT_MESSAGE_IGNORE_INSERTS,
  1155. NULL,
  1156. error,
  1157. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1158. msg, 0, NULL))
  1159. msg = empty;
  1160. SU_DEBUG_1(("su_localinfo: GetAdaptersAddresses: %s (%d)\n", msg, error));
  1161. if (msg != empty) LocalFree((LPVOID)msg);
  1162. error = ELI_SYSTEM;
  1163. goto err;
  1164. }
  1165. for (iaa = iaa0; iaa; iaa = iaa->Next) {
  1166. IP_ADAPTER_UNICAST_ADDRESS *ua;
  1167. IP_ADAPTER_UNICAST_ADDRESS lua[1];
  1168. int if_index = iaa->IfIndex;
  1169. size_t ifnamelen = 0;
  1170. char ifname[16];
  1171. for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {
  1172. su_sockaddr_t *su;
  1173. socklen_t sulen;
  1174. su_sockaddr_t su2[1];
  1175. int scope, flags = 0, gni_flags = 0;
  1176. if (ua == NULL) {
  1177. /* There is no loopback interface in windows */
  1178. if (!loopback_seen && iaa->Next == NULL) {
  1179. struct sockaddr_in loopback_sin = { AF_INET, 0, {{ 127, 0, 0, 1 }}};
  1180. lua->Address.lpSockaddr = (struct sockaddr *)&loopback_sin;
  1181. lua->Address.iSockaddrLength = sizeof(loopback_sin);
  1182. lua->Next = NULL;
  1183. iaa->IfType = IF_TYPE_SOFTWARE_LOOPBACK;
  1184. if_index = 1;
  1185. ua = lua;
  1186. }
  1187. else
  1188. break;
  1189. }
  1190. su = (su_sockaddr_t *)ua->Address.lpSockaddr;
  1191. sulen = ua->Address.iSockaddrLength;
  1192. if (su->su_family == AF_INET) {
  1193. scope = li_scope4(su->su_sin.sin_addr.s_addr);
  1194. if (v4_mapped)
  1195. sulen = sizeof(su->su_sin6);
  1196. if (scope == LI_SCOPE_HOST)
  1197. loopback_seen = 1;
  1198. }
  1199. else if (su->su_family == AF_INET6) {
  1200. if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr))
  1201. continue;
  1202. scope = li_scope6(&su->su_sin6.sin6_addr);
  1203. }
  1204. else
  1205. continue;
  1206. if (hints->li_flags & LI_IFNAME) {
  1207. snprintf(ifname, sizeof(ifname), "%s%u",
  1208. ws2ifname(iaa->IfType), if_index);
  1209. ifnamelen = strlen(ifname) + 1;
  1210. }
  1211. if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
  1212. (hints->li_family && hints->li_family != su->su_family) ||
  1213. /* (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0) || */
  1214. (hints->li_index && hints->li_index != if_index))
  1215. continue;
  1216. if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
  1217. gni_flags = NI_NUMERICHOST;
  1218. if (v4_mapped && su->su_family == AF_INET) {
  1219. /* Map IPv4 address to IPv6 address */
  1220. memset(su2, 0, sizeof(*su2));
  1221. su2->su_family = AF_INET6;
  1222. ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
  1223. ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
  1224. su = su2;
  1225. }
  1226. if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
  1227. goto err;
  1228. else if (error > 0)
  1229. continue;
  1230. if (canonname)
  1231. if (strchr(canonname, ':') ||
  1232. strspn(canonname, "0123456789.") == strlen(canonname))
  1233. flags |= LI_NUMERIC;
  1234. if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {
  1235. SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"));
  1236. error = ELI_MEMORY; goto err;
  1237. }
  1238. *next = li, next = &li->li_next;
  1239. li->li_flags = flags;
  1240. li->li_family = su->su_family;
  1241. li->li_scope = scope;
  1242. li->li_index = if_index;
  1243. li->li_addrlen = sulen;
  1244. li->li_addr = memcpy(li + 1, su, sulen);
  1245. li->li_canonname = canonname;
  1246. if (ifnamelen) {
  1247. li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);
  1248. /* WideCharToMultiByte(CP_ACP, 0,
  1249. ifname, -1, (char *)(li + 1) + sulen, ifnamelen,
  1250. NULL, NULL); */
  1251. }
  1252. canonname = NULL;
  1253. }
  1254. }
  1255. if (iaa0) free(iaa0);
  1256. return 0;
  1257. err:
  1258. if (iaa0) free(iaa0);
  1259. if (canonname) free(canonname);
  1260. su_freelocalinfo(*rresult), *rresult = NULL;
  1261. return error;
  1262. }
  1263. #elif HAVE_SIO_ADDRESS_LIST_QUERY
  1264. static
  1265. int localinfo0(su_localinfo_t const *hints, su_localinfo_t **rresult)
  1266. {
  1267. /* This is Windows IPv4 code */
  1268. short family = AF_INET;
  1269. su_socket_t s;
  1270. union {
  1271. SOCKET_ADDRESS_LIST sal[1];
  1272. #if HAVE_INTERFACE_INFO_EX
  1273. INTERFACE_INFO_EX ii[1];
  1274. #else
  1275. INTERFACE_INFO ii[1];
  1276. #endif
  1277. char buffer[2048];
  1278. } b = {{ 1 }};
  1279. DWORD salen = sizeof(b);
  1280. int i, error = -1;
  1281. #if SU_HAVE_IN6
  1282. int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
  1283. #endif
  1284. su_localinfo_t *li, *head = NULL, **next = &head;
  1285. char *canonname = NULL, *if_name = NULL;
  1286. *rresult = NULL;
  1287. s = su_socket(family, SOCK_DGRAM, 0);
  1288. if (s == INVALID_SOCKET) {
  1289. SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "su_socket",
  1290. su_strerror(su_errno())));
  1291. return -1;
  1292. }
  1293. /* get the list of known IP address (NT5 and up) */
  1294. if (WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0,
  1295. &b, sizeof(b), &salen, NULL, NULL) == SOCKET_ERROR) {
  1296. SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "SIO_ADDRESS_LIST_QUERY",
  1297. su_strerror(su_errno())));
  1298. error = -1; goto err;
  1299. }
  1300. if (b.sal->iAddressCount < 1) {
  1301. SU_DEBUG_1(("su_getlocalinfo: no local addresses\n"));
  1302. error = -1; goto err;
  1303. }
  1304. for (i = 0; i < b.sal->iAddressCount; i++) {
  1305. su_sockaddr_t *su = (su_sockaddr_t *)b.sal->Address[i].lpSockaddr;
  1306. #if SU_HAVE_IN6
  1307. socklen_t sulen = v4_mapped ? sizeof(*su) : b.sal->Address[i].iSockaddrLength;
  1308. su_sockaddr_t su2[1];
  1309. #else
  1310. socklen_t sulen = b.sal->Address[i].iSockaddrLength;
  1311. #endif
  1312. int scope, flags = 0, gni_flags = 0;
  1313. scope = li_scope4(su->su_sin.sin_addr.s_addr);
  1314. if (hints->li_scope && (hints->li_scope & scope) == 0)
  1315. continue;
  1316. if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
  1317. gni_flags = NI_NUMERICHOST;
  1318. if (!(li = calloc(1, sizeof(*li) + sulen))) {
  1319. SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"));
  1320. error = -1; goto err;
  1321. }
  1322. *next = li, next = &li->li_next;
  1323. #if SU_HAVE_IN6
  1324. if (v4_mapped) {
  1325. /* Map IPv4 address to IPv6 address */
  1326. memset(su2, 0, sizeof(*su2));
  1327. su2->su_family = AF_INET6;
  1328. ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
  1329. ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
  1330. su = su2;
  1331. }
  1332. #endif
  1333. if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
  1334. goto err;
  1335. else if (error > 0)
  1336. continue;
  1337. if (canonname)
  1338. if (strchr(canonname, ':') ||
  1339. strspn(canonname, "0123456789.") == strlen(canonname))
  1340. flags |= LI_NUMERIC;
  1341. li->li_flags = flags;
  1342. li->li_family = su->su_family;
  1343. li->li_scope = scope;
  1344. li->li_index = i;
  1345. li->li_addrlen = su_sockaddr_size(su);
  1346. li->li_addr = su;
  1347. li->li_canonname = canonname, canonname = NULL;
  1348. if (hints->li_flags & LI_IFNAME)
  1349. li->li_ifname = if_name;
  1350. li->li_addr = (su_sockaddr_t *)(li + 1);
  1351. li->li_addrlen = sulen;
  1352. memcpy(li->li_addr, su, sulen);
  1353. }
  1354. *rresult = head;
  1355. su_close(s);
  1356. return 0;
  1357. err:
  1358. if (canonname) free(canonname);
  1359. su_freelocalinfo(head);
  1360. su_close(s);
  1361. return error;
  1362. }
  1363. #endif
  1364. #if !SU_LOCALINFO_TEST
  1365. static
  1366. int li_name(su_localinfo_t const *hints,
  1367. int gni_flags,
  1368. su_sockaddr_t const *su,
  1369. char **ccanonname)
  1370. {
  1371. char name[SU_MAXHOST];
  1372. int error;
  1373. int flags = hints->li_flags;
  1374. *ccanonname = NULL;
  1375. if ((flags & LI_CANONNAME) || hints->li_canonname) {
  1376. if ((flags & LI_NAMEREQD) == LI_NAMEREQD)
  1377. gni_flags |= NI_NAMEREQD;
  1378. if (flags & LI_NUMERIC)
  1379. gni_flags |= NI_NUMERICHOST;
  1380. error = su_getnameinfo(su, su_sockaddr_size(su),
  1381. name, sizeof(name), NULL, 0,
  1382. gni_flags);
  1383. if (error) {
  1384. if ((flags & LI_NAMEREQD) == LI_NAMEREQD)
  1385. return 1;
  1386. SU_DEBUG_7(("li_name: getnameinfo() failed\n" VA_NONE));
  1387. if (!su_inet_ntop(su->su_family, SU_ADDR(su), name, sizeof name))
  1388. return ELI_RESOLVER;
  1389. }
  1390. if (hints->li_canonname && !su_casematch(name, hints->li_canonname))
  1391. return 1;
  1392. if (!(flags & LI_CANONNAME))
  1393. return 0;
  1394. if (!(*ccanonname = strdup(name)))
  1395. return ELI_MEMORY;
  1396. }
  1397. return 0;
  1398. }
  1399. static
  1400. void li_sort(su_localinfo_t *i, su_localinfo_t **rresult)
  1401. {
  1402. su_localinfo_t *li, **lli;
  1403. #define LI_MAPPED(li) \
  1404. ((li)->li_family == AF_INET6 && \
  1405. (IN6_IS_ADDR_V4MAPPED(&(li)->li_addr->su_sin6.sin6_addr) || \
  1406. IN6_IS_ADDR_V4COMPAT(&(li)->li_addr->su_sin6.sin6_addr)))
  1407. /* Sort addresses according to scope (and mappedness) */
  1408. for (li = i; li; li = i) {
  1409. i = li->li_next;
  1410. for (lli = rresult; *lli; lli = &(*lli)->li_next) {
  1411. if ((*lli)->li_scope < li->li_scope)
  1412. break;
  1413. #if SU_HAVE_IN6
  1414. if (LI_MAPPED(*lli) > LI_MAPPED(li))
  1415. break;
  1416. #endif
  1417. }
  1418. li->li_next = *lli;
  1419. *lli = li;
  1420. }
  1421. }
  1422. #endif
  1423. /**Get local IP address.
  1424. *
  1425. * @deprecated
  1426. * Use su_getlocalinfo() instead.
  1427. */
  1428. int su_getlocalip(su_sockaddr_t *sa)
  1429. {
  1430. su_localinfo_t *li = NULL, hints[1] = {{ 0 }};
  1431. hints->li_family = sa->su_sa.sa_family ? sa->su_sa.sa_family : AF_INET;
  1432. if (su_getlocalinfo(hints, &li) == 0) {
  1433. memcpy(sa, li->li_addr, li->li_addrlen);
  1434. su_freelocalinfo(li);
  1435. return 0;
  1436. }
  1437. else
  1438. return -1;
  1439. }