ioctl_solaris.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * Common ioctl functions for 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 "linklist.h"
  24. #include "if.h"
  25. #include "prefix.h"
  26. #include "ioctl.h"
  27. #include "log.h"
  28. #include "privs.h"
  29. #include "zebra/rib.h"
  30. #include "zebra/rt.h"
  31. #include "zebra/interface.h"
  32. extern struct zebra_privs_t zserv_privs;
  33. /* clear and set interface name string */
  34. void
  35. lifreq_set_name (struct lifreq *lifreq, const char *ifname)
  36. {
  37. strncpy (lifreq->lifr_name, ifname, IFNAMSIZ);
  38. }
  39. /* call ioctl system call */
  40. int
  41. if_ioctl (u_long request, caddr_t buffer)
  42. {
  43. int sock;
  44. int ret;
  45. int err;
  46. if (zserv_privs.change(ZPRIVS_RAISE))
  47. zlog (NULL, LOG_ERR, "Can't raise privileges");
  48. sock = socket (AF_INET, SOCK_DGRAM, 0);
  49. if (sock < 0)
  50. {
  51. int save_errno = errno;
  52. if (zserv_privs.change(ZPRIVS_LOWER))
  53. zlog (NULL, LOG_ERR, "Can't lower privileges");
  54. zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno));
  55. exit (1);
  56. }
  57. if ((ret = ioctl (sock, request, buffer)) < 0)
  58. err = errno;
  59. if (zserv_privs.change(ZPRIVS_LOWER))
  60. zlog (NULL, LOG_ERR, "Can't lower privileges");
  61. close (sock);
  62. if (ret < 0)
  63. {
  64. errno = err;
  65. return ret;
  66. }
  67. return 0;
  68. }
  69. int
  70. if_ioctl_ipv6 (u_long request, caddr_t buffer)
  71. {
  72. #ifdef HAVE_IPV6
  73. int sock;
  74. int ret;
  75. int err;
  76. if (zserv_privs.change(ZPRIVS_RAISE))
  77. zlog (NULL, LOG_ERR, "Can't raise privileges");
  78. sock = socket (AF_INET6, SOCK_DGRAM, 0);
  79. if (sock < 0)
  80. {
  81. int save_errno = errno;
  82. if (zserv_privs.change(ZPRIVS_LOWER))
  83. zlog (NULL, LOG_ERR, "Can't lower privileges");
  84. zlog_err("Cannot create IPv6 datagram socket: %s",
  85. safe_strerror(save_errno));
  86. exit (1);
  87. }
  88. if ((ret = ioctl (sock, request, buffer)) < 0)
  89. err = errno;
  90. if (zserv_privs.change(ZPRIVS_LOWER))
  91. zlog (NULL, LOG_ERR, "Can't lower privileges");
  92. close (sock);
  93. if (ret < 0)
  94. {
  95. errno = err;
  96. return ret;
  97. }
  98. #endif /* HAVE_IPV6 */
  99. return 0;
  100. }
  101. /*
  102. * get interface metric
  103. * -- if value is not avaliable set -1
  104. */
  105. void
  106. if_get_metric (struct interface *ifp)
  107. {
  108. struct lifreq lifreq;
  109. int ret;
  110. lifreq_set_name (&lifreq, ifp->name);
  111. if (ifp->flags & IFF_IPV4)
  112. ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq);
  113. #ifdef SOLARIS_IPV6
  114. else if (ifp->flags & IFF_IPV6)
  115. ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq);
  116. #endif /* SOLARIS_IPV6 */
  117. else
  118. ret = -1;
  119. if (ret < 0)
  120. return;
  121. ifp->metric = lifreq.lifr_metric;
  122. if (ifp->metric == 0)
  123. ifp->metric = 1;
  124. }
  125. /* get interface MTU */
  126. void
  127. if_get_mtu (struct interface *ifp)
  128. {
  129. struct lifreq lifreq;
  130. int ret;
  131. u_char changed = 0;
  132. if (ifp->flags & IFF_IPV4)
  133. {
  134. lifreq_set_name (&lifreq, ifp->name);
  135. ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq);
  136. if (ret < 0)
  137. {
  138. zlog_info ("Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)",
  139. ifp->name);
  140. ifp->mtu = -1;
  141. }
  142. else
  143. {
  144. ifp->mtu = lifreq.lifr_metric;
  145. changed = 1;
  146. }
  147. }
  148. #ifdef HAVE_IPV6
  149. if (ifp->flags & IFF_IPV6)
  150. {
  151. memset(&lifreq, 0, sizeof(lifreq));
  152. lifreq_set_name (&lifreq, ifp->name);
  153. ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq);
  154. if (ret < 0)
  155. {
  156. zlog_info ("Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", ifp->name);
  157. ifp->mtu6 = -1;
  158. }
  159. else
  160. {
  161. ifp->mtu6 = lifreq.lifr_metric;
  162. changed = 1;
  163. }
  164. }
  165. #endif /* HAVE_IPV6 */
  166. if (changed)
  167. zebra_interface_up_update(ifp);
  168. }
  169. /* Set up interface's address, netmask (and broadcast? ).
  170. Solaris uses ifname:number semantics to set IP address aliases. */
  171. int
  172. if_set_prefix (struct interface *ifp, struct connected *ifc)
  173. {
  174. int ret;
  175. struct ifreq ifreq;
  176. struct sockaddr_in addr;
  177. struct sockaddr_in broad;
  178. struct sockaddr_in mask;
  179. struct prefix_ipv4 ifaddr;
  180. struct prefix_ipv4 *p;
  181. p = (struct prefix_ipv4 *) ifc->address;
  182. ifaddr = *p;
  183. strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
  184. addr.sin_addr = p->prefix;
  185. addr.sin_family = p->family;
  186. memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
  187. ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq);
  188. if (ret < 0)
  189. return ret;
  190. /* We need mask for make broadcast addr. */
  191. masklen2ip (p->prefixlen, &mask.sin_addr);
  192. if (if_is_broadcast (ifp))
  193. {
  194. apply_mask_ipv4 (&ifaddr);
  195. addr.sin_addr = ifaddr.prefix;
  196. broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
  197. broad.sin_family = p->family;
  198. memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in));
  199. ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) & ifreq);
  200. if (ret < 0)
  201. return ret;
  202. }
  203. mask.sin_family = p->family;
  204. #ifdef SUNOS_5
  205. memcpy (&mask, &ifreq.ifr_addr, sizeof (mask));
  206. #else
  207. memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in));
  208. #endif /* SUNOS_5 */
  209. ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq);
  210. return ((ret < 0) ? ret : 0);
  211. }
  212. /* Set up interface's address, netmask (and broadcast).
  213. Solaris uses ifname:number semantics to set IP address aliases. */
  214. int
  215. if_unset_prefix (struct interface *ifp, struct connected *ifc)
  216. {
  217. int ret;
  218. struct ifreq ifreq;
  219. struct sockaddr_in addr;
  220. struct prefix_ipv4 *p;
  221. p = (struct prefix_ipv4 *) ifc->address;
  222. strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
  223. memset (&addr, 0, sizeof (struct sockaddr_in));
  224. addr.sin_family = p->family;
  225. memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
  226. ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq);
  227. if (ret < 0)
  228. return ret;
  229. return 0;
  230. }
  231. /* Get just the flags for the given name.
  232. * Used by the normal 'if_get_flags' function, as well
  233. * as the bootup interface-list code, which has to peek at per-address
  234. * flags in order to figure out which ones should be ignored..
  235. */
  236. int
  237. if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af)
  238. {
  239. struct lifreq lifreq;
  240. int ret;
  241. lifreq_set_name (&lifreq, ifname);
  242. ret = AF_IOCTL (af, SIOCGLIFFLAGS, (caddr_t) &lifreq);
  243. if (ret)
  244. zlog_debug ("%s: ifname %s, error %s (%d)",
  245. __func__, ifname, safe_strerror (errno), errno);
  246. *flags = lifreq.lifr_flags;
  247. return ret;
  248. }
  249. /* get interface flags */
  250. void
  251. if_get_flags (struct interface *ifp)
  252. {
  253. int ret4, ret6;
  254. uint64_t newflags = 0;
  255. uint64_t tmpflags;
  256. if (ifp->flags & IFF_IPV4)
  257. {
  258. ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET);
  259. if (!ret4)
  260. newflags |= tmpflags;
  261. else if (errno == ENXIO)
  262. {
  263. /* it's gone */
  264. UNSET_FLAG (ifp->flags, IFF_UP);
  265. if_flags_update (ifp, ifp->flags);
  266. }
  267. }
  268. if (ifp->flags & IFF_IPV6)
  269. {
  270. ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6);
  271. if (!ret6)
  272. newflags |= tmpflags;
  273. else if (errno == ENXIO)
  274. {
  275. /* it's gone */
  276. UNSET_FLAG (ifp->flags, IFF_UP);
  277. if_flags_update (ifp, ifp->flags);
  278. }
  279. }
  280. /* only update flags if one of above succeeded */
  281. if ( !(ret4 && ret6) )
  282. if_flags_update (ifp, newflags);
  283. }
  284. /* Set interface flags */
  285. int
  286. if_set_flags (struct interface *ifp, uint64_t flags)
  287. {
  288. int ret;
  289. struct lifreq lifreq;
  290. lifreq_set_name (&lifreq, ifp->name);
  291. lifreq.lifr_flags = ifp->flags;
  292. lifreq.lifr_flags |= flags;
  293. if (ifp->flags & IFF_IPV4)
  294. ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq);
  295. else if (ifp->flags & IFF_IPV6)
  296. ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq);
  297. else
  298. ret = -1;
  299. if (ret < 0)
  300. zlog_info ("can't set interface flags on %s: %s", ifp->name,
  301. safe_strerror (errno));
  302. else
  303. ret = 0;
  304. return ret;
  305. }
  306. /* Unset interface's flag. */
  307. int
  308. if_unset_flags (struct interface *ifp, uint64_t flags)
  309. {
  310. int ret;
  311. struct lifreq lifreq;
  312. lifreq_set_name (&lifreq, ifp->name);
  313. lifreq.lifr_flags = ifp->flags;
  314. lifreq.lifr_flags &= ~flags;
  315. if (ifp->flags & IFF_IPV4)
  316. ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq);
  317. else if (ifp->flags & IFF_IPV6)
  318. ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq);
  319. else
  320. ret = -1;
  321. if (ret < 0)
  322. zlog_info ("can't unset interface flags");
  323. else
  324. ret = 0;
  325. return ret;
  326. }
  327. #ifdef HAVE_IPV6
  328. /* Interface's address add/delete functions. */
  329. int
  330. if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
  331. {
  332. char addrbuf[INET_ADDRSTRLEN];
  333. inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix),
  334. addrbuf, sizeof (addrbuf));
  335. zlog_warn ("Can't set %s on interface %s", addrbuf, ifp->name);
  336. return 0;
  337. }
  338. int
  339. if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
  340. {
  341. char addrbuf[INET_ADDRSTRLEN];
  342. inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix),
  343. addrbuf, sizeof (addrbuf));
  344. zlog_warn ("Can't delete %s on interface %s", addrbuf, ifp->name);
  345. return 0;
  346. }
  347. #endif /* HAVE_IPV6 */