if_ioctl_solaris.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * Interface looking up by ioctl () on Solaris.
  3. * Copyright (C) 1997, 98 Kunihiro Ishiguro
  4. *
  5. * This file is part of GNU Zebra.
  6. *
  7. * GNU Zebra is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2, or (at your option) any
  10. * later version.
  11. *
  12. * GNU Zebra is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  19. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. * 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "if.h"
  24. #include "sockunion.h"
  25. #include "prefix.h"
  26. #include "ioctl.h"
  27. #include "connected.h"
  28. #include "memory.h"
  29. #include "log.h"
  30. #include "privs.h"
  31. #include "vrf.h"
  32. #include "vty.h"
  33. #include "zebra/interface.h"
  34. #include "zebra/ioctl_solaris.h"
  35. #include "zebra/rib.h"
  36. static int if_get_addr (struct interface *, struct sockaddr *, const char *);
  37. static void interface_info_ioctl (struct interface *);
  38. extern struct zebra_privs_t zserv_privs;
  39. static int
  40. interface_list_ioctl (int af)
  41. {
  42. int ret;
  43. int sock;
  44. #define IFNUM_BASE 32
  45. struct lifnum lifn;
  46. int ifnum;
  47. struct lifreq *lifreq;
  48. struct lifconf lifconf;
  49. struct interface *ifp;
  50. int n;
  51. int save_errno;
  52. size_t needed, lastneeded = 0;
  53. char *buf = NULL;
  54. if (zserv_privs.change(ZPRIVS_RAISE))
  55. zlog (NULL, LOG_ERR, "Can't raise privileges");
  56. sock = socket (af, SOCK_DGRAM, 0);
  57. if (sock < 0)
  58. {
  59. zlog_warn ("Can't make %s socket stream: %s",
  60. (af == AF_INET ? "AF_INET" : "AF_INET6"), safe_strerror (errno));
  61. if (zserv_privs.change(ZPRIVS_LOWER))
  62. zlog (NULL, LOG_ERR, "Can't lower privileges");
  63. return -1;
  64. }
  65. calculate_lifc_len: /* must hold privileges to enter here */
  66. lifn.lifn_family = af;
  67. lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */
  68. ret = ioctl (sock, SIOCGLIFNUM, &lifn);
  69. save_errno = errno;
  70. if (zserv_privs.change(ZPRIVS_LOWER))
  71. zlog (NULL, LOG_ERR, "Can't lower privileges");
  72. if (ret < 0)
  73. {
  74. zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s",
  75. safe_strerror (save_errno));
  76. close (sock);
  77. return -1;
  78. }
  79. ifnum = lifn.lifn_count;
  80. /*
  81. * When calculating the buffer size needed, add a small number
  82. * of interfaces to those we counted. We do this to capture
  83. * the interface status of potential interfaces which may have
  84. * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
  85. */
  86. needed = (ifnum + 4) * sizeof (struct lifreq);
  87. if (needed > lastneeded || needed < lastneeded / 2)
  88. {
  89. if (buf != NULL)
  90. XFREE (MTYPE_TMP, buf);
  91. if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL)
  92. {
  93. zlog_warn ("interface_list_ioctl: malloc failed");
  94. close (sock);
  95. return -1;
  96. }
  97. }
  98. lastneeded = needed;
  99. lifconf.lifc_family = af;
  100. lifconf.lifc_flags = LIFC_NOXMIT;
  101. lifconf.lifc_len = needed;
  102. lifconf.lifc_buf = buf;
  103. if (zserv_privs.change(ZPRIVS_RAISE))
  104. zlog (NULL, LOG_ERR, "Can't raise privileges");
  105. ret = ioctl (sock, SIOCGLIFCONF, &lifconf);
  106. if (ret < 0)
  107. {
  108. if (errno == EINVAL)
  109. goto calculate_lifc_len; /* deliberately hold privileges */
  110. zlog_warn ("SIOCGLIFCONF: %s", safe_strerror (errno));
  111. if (zserv_privs.change(ZPRIVS_LOWER))
  112. zlog (NULL, LOG_ERR, "Can't lower privileges");
  113. goto end;
  114. }
  115. if (zserv_privs.change(ZPRIVS_LOWER))
  116. zlog (NULL, LOG_ERR, "Can't lower privileges");
  117. /* Allocate interface. */
  118. lifreq = lifconf.lifc_req;
  119. for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq))
  120. {
  121. /* we treat Solaris logical interfaces as addresses, because that is
  122. * how PF_ROUTE on Solaris treats them. Hence we can not directly use
  123. * the lifreq_name to get the ifp. We need to normalise the name
  124. * before attempting get.
  125. *
  126. * Solaris logical interface names are in the form of:
  127. * <interface name>:<logical interface id>
  128. */
  129. unsigned int normallen = 0;
  130. uint64_t lifflags;
  131. /* We should exclude ~IFF_UP interfaces, as we'll find out about them
  132. * coming up later through RTM_NEWADDR message on the route socket.
  133. */
  134. if (if_get_flags_direct (lifreq->lifr_name, &lifflags,
  135. lifreq->lifr_addr.ss_family)
  136. || !CHECK_FLAG (lifflags, IFF_UP))
  137. {
  138. lifreq++;
  139. continue;
  140. }
  141. /* Find the normalised name */
  142. while ( (normallen < sizeof(lifreq->lifr_name))
  143. && ( *(lifreq->lifr_name + normallen) != '\0')
  144. && ( *(lifreq->lifr_name + normallen) != ':') )
  145. normallen++;
  146. ifp = if_get_by_name_len(lifreq->lifr_name, normallen);
  147. if (lifreq->lifr_addr.ss_family == AF_INET)
  148. ifp->flags |= IFF_IPV4;
  149. if (lifreq->lifr_addr.ss_family == AF_INET6)
  150. {
  151. #ifdef HAVE_IPV6
  152. ifp->flags |= IFF_IPV6;
  153. #else
  154. lifreq++;
  155. continue;
  156. #endif /* HAVE_IPV6 */
  157. }
  158. if_add_update (ifp);
  159. interface_info_ioctl (ifp);
  160. /* If a logical interface pass the full name so it can be
  161. * as a label on the address
  162. */
  163. if ( *(lifreq->lifr_name + normallen) != '\0')
  164. if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr,
  165. lifreq->lifr_name);
  166. else
  167. if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL);
  168. /* Poke the interface flags. Lets IFF_UP mangling kick in */
  169. if_flags_update (ifp, ifp->flags);
  170. lifreq++;
  171. }
  172. end:
  173. close (sock);
  174. XFREE (MTYPE_TMP, lifconf.lifc_buf);
  175. return ret;
  176. }
  177. /* Get interface's index by ioctl. */
  178. static int
  179. if_get_index (struct interface *ifp)
  180. {
  181. int ret;
  182. struct lifreq lifreq;
  183. lifreq_set_name (&lifreq, ifp->name);
  184. if (ifp->flags & IFF_IPV4)
  185. ret = AF_IOCTL (AF_INET, SIOCGLIFINDEX, (caddr_t) & lifreq);
  186. else if (ifp->flags & IFF_IPV6)
  187. ret = AF_IOCTL (AF_INET6, SIOCGLIFINDEX, (caddr_t) & lifreq);
  188. else
  189. ret = -1;
  190. if (ret < 0)
  191. {
  192. zlog_warn ("SIOCGLIFINDEX(%s) failed", ifp->name);
  193. return ret;
  194. }
  195. /* OK we got interface index. */
  196. #ifdef ifr_ifindex
  197. ifp->ifindex = lifreq.lifr_ifindex;
  198. #else
  199. ifp->ifindex = lifreq.lifr_index;
  200. #endif
  201. return ifp->ifindex;
  202. }
  203. /* Interface address lookup by ioctl. This function only looks up
  204. IPv4 address. */
  205. #define ADDRLEN(sa) (((sa)->sa_family == AF_INET ? \
  206. sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)))
  207. #define SIN(s) ((struct sockaddr_in *)(s))
  208. #define SIN6(s) ((struct sockaddr_in6 *)(s))
  209. /* Retrieve address information for the given ifp */
  210. static int
  211. if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
  212. {
  213. int ret;
  214. struct lifreq lifreq;
  215. struct sockaddr_storage mask, dest;
  216. char *dest_pnt = NULL;
  217. u_char prefixlen = 0;
  218. afi_t af;
  219. int flags = 0;
  220. /* Interface's name and address family.
  221. * We need to use the logical interface name / label, if we've been
  222. * given one, in order to get the right address
  223. */
  224. strncpy (lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ);
  225. /* Interface's address. */
  226. memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr));
  227. af = addr->sa_family;
  228. /* Point to point or broad cast address pointer init. */
  229. dest_pnt = NULL;
  230. if (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0)
  231. {
  232. memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr));
  233. if (af == AF_INET)
  234. dest_pnt = (char *) &(SIN (&dest)->sin_addr);
  235. else
  236. dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr);
  237. flags = ZEBRA_IFA_PEER;
  238. }
  239. if (af == AF_INET)
  240. {
  241. ret = if_ioctl (SIOCGLIFNETMASK, (caddr_t) & lifreq);
  242. if (ret < 0)
  243. {
  244. if (errno != EADDRNOTAVAIL)
  245. {
  246. zlog_warn ("SIOCGLIFNETMASK (%s) fail: %s", ifp->name,
  247. safe_strerror (errno));
  248. return ret;
  249. }
  250. return 0;
  251. }
  252. memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr));
  253. prefixlen = ip_masklen (SIN (&mask)->sin_addr);
  254. if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0))
  255. {
  256. memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in));
  257. dest_pnt = (char *) &SIN (&dest)->sin_addr;
  258. }
  259. }
  260. #ifdef HAVE_IPV6
  261. else if (af == AF_INET6)
  262. {
  263. if (if_ioctl_ipv6 (SIOCGLIFSUBNET, (caddr_t) & lifreq) < 0)
  264. {
  265. if (ifp->flags & IFF_POINTOPOINT)
  266. prefixlen = IPV6_MAX_BITLEN;
  267. else
  268. zlog_warn ("SIOCGLIFSUBNET (%s) fail: %s",
  269. ifp->name, safe_strerror (errno));
  270. }
  271. else
  272. {
  273. prefixlen = lifreq.lifr_addrlen;
  274. }
  275. }
  276. #endif /* HAVE_IPV6 */
  277. /* Set address to the interface. */
  278. if (af == AF_INET)
  279. connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen,
  280. (struct in_addr *) dest_pnt, label);
  281. #ifdef HAVE_IPV6
  282. else if (af == AF_INET6)
  283. connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen,
  284. (struct in6_addr *) dest_pnt, label);
  285. #endif /* HAVE_IPV6 */
  286. return 0;
  287. }
  288. /* Fetch interface information via ioctl(). */
  289. static void
  290. interface_info_ioctl (struct interface *ifp)
  291. {
  292. if_get_index (ifp);
  293. if_get_flags (ifp);
  294. if_get_mtu (ifp);
  295. if_get_metric (ifp);
  296. }
  297. /* Lookup all interface information. */
  298. void
  299. interface_list (struct zebra_vrf *zvrf)
  300. {
  301. if (zvrf->vrf_id != VRF_DEFAULT)
  302. {
  303. zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id);
  304. return;
  305. }
  306. interface_list_ioctl (AF_INET);
  307. interface_list_ioctl (AF_INET6);
  308. interface_list_ioctl (AF_UNSPEC);
  309. }
  310. struct connected *
  311. if_lookup_linklocal (struct interface *ifp)
  312. {
  313. #ifdef HAVE_IPV6
  314. struct listnode *node;
  315. struct connected *ifc;
  316. if (ifp == NULL)
  317. return NULL;
  318. for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
  319. {
  320. if ((ifc->address->family == AF_INET6) &&
  321. (IN6_IS_ADDR_LINKLOCAL (&ifc->address->u.prefix6)))
  322. return ifc;
  323. }
  324. #endif /* HAVE_IPV6 */
  325. return NULL;
  326. }