PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/release/src/router/zebra/zebra/ioctl.c

https://github.com/SgtPepperKSU/TomatoVPN
C | 539 lines | 403 code | 91 blank | 45 comment | 23 complexity | f6335ee3cfe78028182e2e70a354a34e MD5 | raw file
  1. /*
  2. * Common ioctl functions.
  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 "zebra/rib.h"
  29. #include "zebra/rt.h"
  30. /* clear and set interface name string */
  31. void
  32. ifreq_set_name (struct ifreq *ifreq, struct interface *ifp)
  33. {
  34. strncpy (ifreq->ifr_name, ifp->name, IFNAMSIZ);
  35. }
  36. /* call ioctl system call */
  37. int
  38. if_ioctl (u_long request, caddr_t buffer)
  39. {
  40. int sock;
  41. int ret = 0;
  42. int err = 0;
  43. sock = socket (AF_INET, SOCK_DGRAM, 0);
  44. if (sock < 0)
  45. {
  46. perror ("socket");
  47. exit (1);
  48. }
  49. ret = ioctl (sock, request, buffer);
  50. if (ret < 0)
  51. {
  52. err = errno;
  53. }
  54. close (sock);
  55. if (ret < 0)
  56. {
  57. errno = err;
  58. return ret;
  59. }
  60. return 0;
  61. }
  62. #ifdef HAVE_IPV6
  63. int
  64. if_ioctl_ipv6 (u_long request, caddr_t buffer)
  65. {
  66. int sock;
  67. int ret = 0;
  68. int err = 0;
  69. sock = socket (AF_INET6, SOCK_DGRAM, 0);
  70. if (sock < 0)
  71. {
  72. perror ("socket");
  73. exit (1);
  74. }
  75. ret = ioctl (sock, request, buffer);
  76. if (ret < 0)
  77. {
  78. err = errno;
  79. }
  80. close (sock);
  81. if (ret < 0)
  82. {
  83. errno = err;
  84. return ret;
  85. }
  86. return 0;
  87. }
  88. #endif /* HAVE_IPV6 */
  89. /*
  90. * get interface metric
  91. * -- if value is not avaliable set -1
  92. */
  93. void
  94. if_get_metric (struct interface *ifp)
  95. {
  96. #ifdef SIOCGIFMETRIC
  97. struct ifreq ifreq;
  98. ifreq_set_name (&ifreq, ifp);
  99. if (if_ioctl (SIOCGIFMETRIC, (caddr_t) &ifreq) < 0)
  100. return;
  101. ifp->metric = ifreq.ifr_metric;
  102. if (ifp->metric == 0)
  103. ifp->metric = 1;
  104. #else /* SIOCGIFMETRIC */
  105. ifp->metric = -1;
  106. #endif /* SIOCGIFMETRIC */
  107. }
  108. /* get interface MTU */
  109. void
  110. if_get_mtu (struct interface *ifp)
  111. {
  112. struct ifreq ifreq;
  113. ifreq_set_name (&ifreq, ifp);
  114. #if defined(SIOCGIFMTU)
  115. if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0)
  116. {
  117. zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)");
  118. ifp->mtu = -1;
  119. return;
  120. }
  121. #ifdef SUNOS_5
  122. ifp->mtu = ifreq.ifr_metric;
  123. #else
  124. ifp->mtu = ifreq.ifr_mtu;
  125. #endif /* SUNOS_5 */
  126. #else
  127. zlog (NULL, LOG_INFO, "Can't lookup mtu on this system");
  128. ifp->mtu = -1;
  129. #endif
  130. }
  131. #ifdef HAVE_NETLINK
  132. /* Interface address setting via netlink interface. */
  133. int
  134. if_set_prefix (struct interface *ifp, struct connected *ifc)
  135. {
  136. return kernel_address_add_ipv4 (ifp, ifc);
  137. }
  138. /* Interface address is removed using netlink interface. */
  139. int
  140. if_unset_prefix (struct interface *ifp, struct connected *ifc)
  141. {
  142. return kernel_address_delete_ipv4 (ifp, ifc);
  143. }
  144. #else /* ! HAVE_NETLINK */
  145. #ifdef HAVE_IFALIASREQ
  146. /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
  147. has ifaliasreq structure. */
  148. int
  149. if_set_prefix (struct interface *ifp, struct connected *ifc)
  150. {
  151. int ret;
  152. struct ifaliasreq addreq;
  153. struct sockaddr_in addr;
  154. struct sockaddr_in mask;
  155. struct prefix_ipv4 *p;
  156. p = (struct prefix_ipv4 *) ifc->address;
  157. bzero (&addreq, sizeof addreq);
  158. strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
  159. bzero (&addr, sizeof (struct sockaddr_in));
  160. addr.sin_addr = p->prefix;
  161. addr.sin_family = p->family;
  162. #ifdef HAVE_SIN_LEN
  163. addr.sin_len = sizeof (struct sockaddr_in);
  164. #endif
  165. memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
  166. bzero (&mask, sizeof (struct sockaddr_in));
  167. masklen2ip (p->prefixlen, &mask.sin_addr);
  168. mask.sin_family = p->family;
  169. #ifdef HAVE_SIN_LEN
  170. mask.sin_len = sizeof (struct sockaddr_in);
  171. #endif
  172. memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
  173. ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq);
  174. if (ret < 0)
  175. return ret;
  176. return 0;
  177. }
  178. /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
  179. has ifaliasreq structure. */
  180. int
  181. if_unset_prefix (struct interface *ifp, struct connected *ifc)
  182. {
  183. int ret;
  184. struct ifaliasreq addreq;
  185. struct sockaddr_in addr;
  186. struct sockaddr_in mask;
  187. struct prefix_ipv4 *p;
  188. p = (struct prefix_ipv4 *)ifc->address;
  189. bzero (&addreq, sizeof addreq);
  190. strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
  191. bzero (&addr, sizeof (struct sockaddr_in));
  192. addr.sin_addr = p->prefix;
  193. addr.sin_family = p->family;
  194. #ifdef HAVE_SIN_LEN
  195. addr.sin_len = sizeof (struct sockaddr_in);
  196. #endif
  197. memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
  198. bzero (&mask, sizeof (struct sockaddr_in));
  199. masklen2ip (p->prefixlen, &mask.sin_addr);
  200. mask.sin_family = p->family;
  201. #ifdef HAVE_SIN_LEN
  202. mask.sin_len = sizeof (struct sockaddr_in);
  203. #endif
  204. memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
  205. ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq);
  206. if (ret < 0)
  207. return ret;
  208. return 0;
  209. }
  210. #else
  211. /* Set up interface's address, netmask (and broadcas? ). Linux or
  212. Solaris uses ifname:number semantics to set IP address aliases. */
  213. int
  214. if_set_prefix (struct interface *ifp, struct connected *ifc)
  215. {
  216. int ret;
  217. struct ifreq ifreq;
  218. struct sockaddr_in addr;
  219. struct sockaddr_in broad;
  220. struct sockaddr_in mask;
  221. struct prefix_ipv4 ifaddr;
  222. struct prefix_ipv4 *p;
  223. p = (struct prefix_ipv4 *) ifc->address;
  224. ifaddr = *p;
  225. ifreq_set_name (&ifreq, ifp);
  226. addr.sin_addr = p->prefix;
  227. addr.sin_family = p->family;
  228. memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
  229. ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq);
  230. if (ret < 0)
  231. return ret;
  232. /* We need mask for make broadcast addr. */
  233. masklen2ip (p->prefixlen, &mask.sin_addr);
  234. if (if_is_broadcast (ifp))
  235. {
  236. apply_mask_ipv4 (&ifaddr);
  237. addr.sin_addr = ifaddr.prefix;
  238. broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
  239. broad.sin_family = p->family;
  240. memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in));
  241. ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) &ifreq);
  242. if (ret < 0)
  243. return ret;
  244. }
  245. mask.sin_family = p->family;
  246. #ifdef SUNOS_5
  247. memcpy (&mask, &ifreq.ifr_addr, sizeof (mask));
  248. #else
  249. memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in));
  250. #endif /* SUNOS5 */
  251. ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) &ifreq);
  252. if (ret < 0)
  253. return ret;
  254. /* Linux version before 2.1.0 need to interface route setup. */
  255. #if defined(GNU_LINUX) && LINUX_VERSION_CODE < 131328
  256. {
  257. apply_mask_ipv4 (&ifaddr);
  258. kernel_add_route (&ifaddr, NULL, ifp->ifindex, 0, 0);
  259. }
  260. #endif /* ! (GNU_LINUX && LINUX_VERSION_CODE) */
  261. return 0;
  262. }
  263. /* Set up interface's address, netmask (and broadcas? ). Linux or
  264. Solaris uses ifname:number semantics to set IP address aliases. */
  265. int
  266. if_unset_prefix (struct interface *ifp, struct connected *ifc)
  267. {
  268. int ret;
  269. struct ifreq ifreq;
  270. struct sockaddr_in addr;
  271. struct prefix_ipv4 *p;
  272. p = (struct prefix_ipv4 *) ifc->address;
  273. ifreq_set_name (&ifreq, ifp);
  274. bzero (&addr, sizeof (struct sockaddr_in));
  275. addr.sin_family = p->family;
  276. memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
  277. ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq);
  278. if (ret < 0)
  279. return ret;
  280. return 0;
  281. }
  282. #endif /* HAVE_IFALIASREQ */
  283. #endif /* HAVE_NETLINK */
  284. /* get interface flags */
  285. void
  286. if_get_flags (struct interface *ifp)
  287. {
  288. int ret;
  289. struct ifreq ifreq;
  290. ifreq_set_name (&ifreq, ifp);
  291. ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq);
  292. if (ret < 0)
  293. {
  294. perror ("ioctl");
  295. return;
  296. }
  297. ifp->flags = ifreq.ifr_flags & 0x0000ffff;
  298. }
  299. /* Set interface flags */
  300. int
  301. if_set_flags (struct interface *ifp, unsigned long flags)
  302. {
  303. int ret;
  304. struct ifreq ifreq;
  305. ifreq_set_name (&ifreq, ifp);
  306. ifreq.ifr_flags = ifp->flags;
  307. ifreq.ifr_flags |= flags;
  308. ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq);
  309. if (ret < 0)
  310. {
  311. zlog_info ("can't set interface flags");
  312. return ret;
  313. }
  314. return 0;
  315. }
  316. /* Unset interface's flag. */
  317. int
  318. if_unset_flags (struct interface *ifp, unsigned long flags)
  319. {
  320. int ret;
  321. struct ifreq ifreq;
  322. ifreq_set_name (&ifreq, ifp);
  323. ifreq.ifr_flags = ifp->flags;
  324. ifreq.ifr_flags &= ~flags;
  325. ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq);
  326. if (ret < 0)
  327. {
  328. zlog_info ("can't unset interface flags");
  329. return ret;
  330. }
  331. return 0;
  332. }
  333. #ifdef HAVE_IPV6
  334. #ifdef LINUX_IPV6
  335. #ifndef _LINUX_IN6_H
  336. /* linux/include/net/ipv6.h */
  337. struct in6_ifreq
  338. {
  339. struct in6_addr ifr6_addr;
  340. u_int32_t ifr6_prefixlen;
  341. int ifr6_ifindex;
  342. };
  343. #endif /* _LINUX_IN6_H */
  344. /* Interface's address add/delete functions. */
  345. int
  346. if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
  347. {
  348. int ret;
  349. struct prefix_ipv6 *p;
  350. struct in6_ifreq ifreq;
  351. p = (struct prefix_ipv6 *) ifc->address;
  352. memset (&ifreq, 0, sizeof (struct in6_ifreq));
  353. memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr));
  354. ifreq.ifr6_ifindex = ifp->ifindex;
  355. ifreq.ifr6_prefixlen = p->prefixlen;
  356. ret = if_ioctl_ipv6 (SIOCSIFADDR, (caddr_t) &ifreq);
  357. return ret;
  358. }
  359. int
  360. if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
  361. {
  362. int ret;
  363. struct prefix_ipv6 *p;
  364. struct in6_ifreq ifreq;
  365. p = (struct prefix_ipv6 *) ifc->address;
  366. memset (&ifreq, 0, sizeof (struct in6_ifreq));
  367. memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr));
  368. ifreq.ifr6_ifindex = ifp->ifindex;
  369. ifreq.ifr6_prefixlen = p->prefixlen;
  370. ret = if_ioctl_ipv6 (SIOCDIFADDR, (caddr_t) &ifreq);
  371. return ret;
  372. }
  373. #else /* LINUX_IPV6 */
  374. #ifdef HAVE_IN6_ALIASREQ
  375. int
  376. if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
  377. {
  378. int ret;
  379. struct in6_aliasreq addreq;
  380. struct sockaddr_in6 addr;
  381. struct sockaddr_in6 mask;
  382. struct prefix_ipv6 *p;
  383. p = (struct prefix_ipv6 * ) ifc->address;
  384. bzero (&addreq, sizeof addreq);
  385. strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
  386. bzero (&addr, sizeof (struct sockaddr_in6));
  387. addr.sin6_addr = p->prefix;
  388. addr.sin6_family = p->family;
  389. #ifdef HAVE_SIN_LEN
  390. addr.sin6_len = sizeof (struct sockaddr_in6);
  391. #endif
  392. memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
  393. bzero (&mask, sizeof (struct sockaddr_in6));
  394. masklen2ip6 (p->prefixlen, &mask.sin6_addr);
  395. mask.sin6_family = p->family;
  396. #ifdef HAVE_SIN_LEN
  397. mask.sin6_len = sizeof (struct sockaddr_in6);
  398. #endif
  399. memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
  400. ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq);
  401. if (ret < 0)
  402. return ret;
  403. return 0;
  404. }
  405. int
  406. if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
  407. {
  408. int ret;
  409. struct in6_aliasreq addreq;
  410. struct sockaddr_in6 addr;
  411. struct sockaddr_in6 mask;
  412. struct prefix_ipv6 *p;
  413. p = (struct prefix_ipv6 *) ifc->address;
  414. bzero (&addreq, sizeof addreq);
  415. strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
  416. bzero (&addr, sizeof (struct sockaddr_in6));
  417. addr.sin6_addr = p->prefix;
  418. addr.sin6_family = p->family;
  419. #ifdef HAVE_SIN_LEN
  420. addr.sin6_len = sizeof (struct sockaddr_in6);
  421. #endif
  422. memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
  423. bzero (&mask, sizeof (struct sockaddr_in6));
  424. masklen2ip6 (p->prefixlen, &mask.sin6_addr);
  425. mask.sin6_family = p->family;
  426. #ifdef HAVE_SIN_LEN
  427. mask.sin6_len = sizeof (struct sockaddr_in6);
  428. #endif
  429. memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
  430. ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq);
  431. if (ret < 0)
  432. return ret;
  433. return 0;
  434. }
  435. #else
  436. int
  437. if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
  438. {
  439. return 0;
  440. }
  441. int
  442. if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
  443. {
  444. return 0;
  445. }
  446. #endif /* HAVE_IN6_ALIASREQ */
  447. #endif /* LINUX_IPV6 */
  448. #endif /* HAVE_IPV6 */