ospf6_network.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /*
  2. * Copyright (C) 1999 Yasuhiro Ohara
  3. *
  4. * This file is part of GNU Zebra.
  5. *
  6. * GNU Zebra is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2, or (at your option) any
  9. * later version.
  10. *
  11. * GNU Zebra is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GNU Zebra; see the file COPYING. If not, write to the
  18. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "memory.h"
  23. #include "log.h"
  24. #include "sockunion.h"
  25. #include "ospf6d.h"
  26. #include "ospf6_proto.h"
  27. extern int errno;
  28. extern struct sockaddr_in6 allspfrouters6;
  29. extern struct sockaddr_in6 alldrouters6;
  30. extern int ospf6_sock;
  31. extern struct thread_master *master;
  32. /* iovec functions */
  33. void
  34. iov_clear (struct iovec *iov, size_t iovlen)
  35. {
  36. int i;
  37. for (i = 0; i < iovlen; i++)
  38. {
  39. iov[i].iov_base = NULL;
  40. iov[i].iov_len = 0;
  41. }
  42. }
  43. int
  44. iov_count (struct iovec *iov)
  45. {
  46. int i;
  47. for (i = 0; iov[i].iov_base; i++)
  48. ;
  49. return i;
  50. }
  51. int
  52. iov_totallen (struct iovec *iov)
  53. {
  54. int i;
  55. int totallen = 0;
  56. for (i = 0; iov[i].iov_base; i++)
  57. totallen += iov[i].iov_len;
  58. return totallen;
  59. }
  60. void *
  61. iov_prepend (int mtype, struct iovec *iov, size_t len)
  62. {
  63. int i, iovlen;
  64. void *base;
  65. base = (void *) XMALLOC (mtype, len);
  66. if (!base)
  67. {
  68. zlog_warn ("Network: iov_prepend failed");
  69. return NULL;
  70. }
  71. memset (base, 0, len);
  72. iovlen = iov_count (iov);
  73. for (i = iovlen; i; i--)
  74. {
  75. iov[i].iov_base = iov[i - 1].iov_base;
  76. iov[i].iov_len = iov[i - 1].iov_len;
  77. }
  78. iov[0].iov_base = (char *)base;
  79. iov[0].iov_len = len;
  80. return base;
  81. }
  82. void *
  83. iov_append (int mtype, struct iovec *iov, size_t len)
  84. {
  85. int i;
  86. void *base;
  87. base = (void *)XMALLOC (mtype, len);
  88. if (!base)
  89. {
  90. zlog_warn ("Network: iov_append failed");
  91. return NULL;
  92. }
  93. memset (base, 0, len);
  94. /* proceed to the end */
  95. i = iov_count (iov);
  96. iov[i].iov_base = (char *)base;
  97. iov[i].iov_len = len;
  98. return base;
  99. }
  100. void *
  101. iov_attach_last (struct iovec *iov, void *base, size_t len)
  102. {
  103. int i;
  104. i = iov_count (iov);
  105. iov[i].iov_base = (char *)base;
  106. iov[i].iov_len = len;
  107. return base;
  108. }
  109. void *
  110. iov_detach_first (struct iovec *iov)
  111. {
  112. int i, iovlen;
  113. void *base;
  114. size_t len;
  115. base = iov[0].iov_base;
  116. len = iov[0].iov_len;
  117. iovlen = iov_count (iov);
  118. for (i = 0; i < iovlen; i++)
  119. {
  120. iov[i].iov_base = iov[i + 1].iov_base;
  121. iov[i].iov_len = iov[i + 1].iov_len;
  122. }
  123. return base;
  124. }
  125. int
  126. iov_free (int mtype, struct iovec *iov, u_int begin, u_int end)
  127. {
  128. int i;
  129. for (i = begin; i < end; i++)
  130. {
  131. XFREE (mtype, iov[i].iov_base);
  132. iov[i].iov_base = NULL;
  133. iov[i].iov_len = 0;
  134. }
  135. return 0;
  136. }
  137. void
  138. iov_trim_head (int mtype, struct iovec *iov)
  139. {
  140. void *base;
  141. base = iov_detach_first (iov);
  142. XFREE (mtype, base);
  143. return;
  144. }
  145. void
  146. iov_free_all (int mtype, struct iovec *iov)
  147. {
  148. int i, end = iov_count (iov);
  149. for (i = 0; i < end; i++)
  150. {
  151. XFREE (mtype, iov[i].iov_base);
  152. iov[i].iov_base = NULL;
  153. iov[i].iov_len = 0;
  154. }
  155. }
  156. void
  157. iov_copy_all (struct iovec *dst, struct iovec *src, size_t size)
  158. {
  159. int i;
  160. for (i = 0; i < size; i++)
  161. {
  162. dst[i].iov_base = src[i].iov_base;
  163. dst[i].iov_len = src[i].iov_len;
  164. }
  165. }
  166. /* Make ospf6d's server socket. */
  167. int
  168. ospf6_serv_sock ()
  169. {
  170. ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
  171. if (ospf6_sock < 0)
  172. {
  173. zlog_warn ("Network: can't create OSPF6 socket.");
  174. return -1;
  175. }
  176. sockopt_reuseaddr (ospf6_sock);
  177. /* setup global sockaddr_in6, allspf6 & alldr6 for later use */
  178. allspfrouters6.sin6_family = AF_INET6;
  179. alldrouters6.sin6_family = AF_INET6;
  180. #ifdef SIN6_LEN
  181. allspfrouters6.sin6_len = sizeof (struct sockaddr_in6);
  182. alldrouters6.sin6_len = sizeof (struct sockaddr_in6);
  183. #endif /* SIN6_LEN */
  184. inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6.sin6_addr);
  185. inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6.sin6_addr);
  186. return 0;
  187. }
  188. /* returns 0 if succeed, else returns -1 */
  189. int
  190. ospf6_join_allspfrouters (u_int ifindex)
  191. {
  192. struct ipv6_mreq mreq6;
  193. int retval;
  194. assert (ifindex);
  195. mreq6.ipv6mr_interface = ifindex;
  196. memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
  197. sizeof (struct in6_addr));
  198. retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  199. &mreq6, sizeof (mreq6));
  200. if (retval < 0)
  201. zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
  202. ifindex, strerror (errno));
  203. #if 0
  204. else
  205. zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
  206. #endif
  207. return retval;
  208. }
  209. void
  210. ospf6_leave_allspfrouters (u_int ifindex)
  211. {
  212. struct ipv6_mreq mreq6;
  213. assert (ifindex);
  214. mreq6.ipv6mr_interface = ifindex;
  215. memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
  216. sizeof (struct in6_addr));
  217. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  218. &mreq6, sizeof (mreq6)) < 0)
  219. zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
  220. ifindex, strerror (errno));
  221. else
  222. zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
  223. }
  224. void
  225. ospf6_join_alldrouters (u_int ifindex)
  226. {
  227. struct ipv6_mreq mreq6;
  228. assert (ifindex);
  229. mreq6.ipv6mr_interface = ifindex;
  230. memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
  231. sizeof (struct in6_addr));
  232. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  233. &mreq6, sizeof (mreq6)) < 0)
  234. zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
  235. ifindex, strerror (errno));
  236. else
  237. zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
  238. }
  239. void
  240. ospf6_leave_alldrouters (u_int ifindex)
  241. {
  242. struct ipv6_mreq mreq6;
  243. assert (ifindex);
  244. mreq6.ipv6mr_interface = ifindex;
  245. memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
  246. sizeof (struct in6_addr));
  247. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  248. &mreq6, sizeof (mreq6)) < 0)
  249. zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
  250. else
  251. zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
  252. }
  253. /* setsockopt ReUseAddr to on */
  254. void
  255. ospf6_set_reuseaddr ()
  256. {
  257. u_int on = 0;
  258. if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on,
  259. sizeof (u_int)) < 0)
  260. zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno));
  261. }
  262. /* setsockopt MulticastLoop to off */
  263. void
  264. ospf6_reset_mcastloop ()
  265. {
  266. u_int off = 0;
  267. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
  268. &off, sizeof (u_int)) < 0)
  269. zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
  270. strerror (errno));
  271. }
  272. void
  273. ospf6_set_pktinfo ()
  274. {
  275. u_int on = 1;
  276. #ifdef IPV6_RECVPKTINFO /*2292bis-01*/
  277. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  278. &on, sizeof (u_int)) < 0)
  279. zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno));
  280. #else /*RFC2292*/
  281. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO,
  282. &on, sizeof (u_int)) < 0)
  283. zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno));
  284. #endif
  285. }
  286. void
  287. ospf6_set_checksum ()
  288. {
  289. int offset = 12;
  290. #if !defined(DISABLE_IPV6_CHECKSUM)
  291. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
  292. &offset, sizeof (offset)) < 0)
  293. zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
  294. #else
  295. zlog_warn ("Network: Don't set IPV6_CHECKSUM");
  296. #endif /* DISABLE_IPV6_CHECKSUM */
  297. }
  298. void
  299. ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
  300. unsigned int *ifindex, struct iovec *message)
  301. {
  302. int retval;
  303. struct msghdr smsghdr;
  304. struct cmsghdr *scmsgp;
  305. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  306. struct in6_pktinfo *pktinfo;
  307. struct sockaddr_in6 dst_sin6;
  308. assert (dst);
  309. assert (*ifindex);
  310. scmsgp = (struct cmsghdr *)cmsgbuf;
  311. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
  312. memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));
  313. /* source address */
  314. pktinfo->ipi6_ifindex = *ifindex;
  315. if (src)
  316. memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
  317. else
  318. memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));
  319. /* destination address */
  320. dst_sin6.sin6_family = AF_INET6;
  321. #ifdef SIN6_LEN
  322. dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
  323. #endif /*SIN6_LEN*/
  324. memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
  325. #ifdef HAVE_SIN6_SCOPE_ID
  326. dst_sin6.sin6_scope_id = *ifindex;
  327. #endif
  328. /* send control msg */
  329. scmsgp->cmsg_level = IPPROTO_IPV6;
  330. scmsgp->cmsg_type = IPV6_PKTINFO;
  331. scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  332. /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
  333. /* send msg hdr */
  334. smsghdr.msg_iov = message;
  335. smsghdr.msg_iovlen = iov_count (message);
  336. smsghdr.msg_name = (caddr_t) &dst_sin6;
  337. smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  338. smsghdr.msg_control = (caddr_t) cmsgbuf;
  339. smsghdr.msg_controllen = sizeof (cmsgbuf);
  340. retval = sendmsg (ospf6_sock, &smsghdr, 0);
  341. if (retval != iov_totallen (message))
  342. zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",
  343. *ifindex, strerror (errno), errno);
  344. }
  345. void
  346. ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
  347. unsigned int *ifindex, struct iovec *message)
  348. {
  349. int retval;
  350. struct msghdr rmsghdr;
  351. struct cmsghdr *rcmsgp;
  352. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  353. struct in6_pktinfo *pktinfo;
  354. struct sockaddr_in6 src_sin6;
  355. rcmsgp = (struct cmsghdr *)cmsgbuf;
  356. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
  357. memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
  358. /* receive control msg */
  359. rcmsgp->cmsg_level = IPPROTO_IPV6;
  360. rcmsgp->cmsg_type = IPV6_PKTINFO;
  361. rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  362. /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
  363. /* receive msg hdr */
  364. rmsghdr.msg_iov = message;
  365. rmsghdr.msg_iovlen = iov_count (message);
  366. rmsghdr.msg_name = (caddr_t) &src_sin6;
  367. rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  368. rmsghdr.msg_control = (caddr_t) cmsgbuf;
  369. rmsghdr.msg_controllen = sizeof (cmsgbuf);
  370. retval = recvmsg (ospf6_sock, &rmsghdr, 0);
  371. if (retval < 0)
  372. {
  373. zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
  374. }
  375. else if (retval == iov_totallen (message))
  376. {
  377. zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",
  378. retval, iov_totallen (message));
  379. }
  380. /* source address */
  381. assert (src);
  382. memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
  383. /* destination address */
  384. if (ifindex)
  385. *ifindex = pktinfo->ipi6_ifindex;
  386. if (dst)
  387. memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
  388. }
  389. void
  390. ospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,
  391. unsigned int *ifindex, struct iovec *message)
  392. {
  393. int retval;
  394. struct msghdr rmsghdr;
  395. struct cmsghdr *rcmsgp;
  396. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  397. struct in6_pktinfo *pktinfo;
  398. struct sockaddr_in6 src_sin6;
  399. rcmsgp = (struct cmsghdr *)cmsgbuf;
  400. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
  401. memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
  402. /* receive control msg */
  403. rcmsgp->cmsg_level = IPPROTO_IPV6;
  404. rcmsgp->cmsg_type = IPV6_PKTINFO;
  405. rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  406. /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
  407. /* receive msg hdr */
  408. rmsghdr.msg_iov = message;
  409. rmsghdr.msg_iovlen = iov_count (message);
  410. rmsghdr.msg_name = (caddr_t) &src_sin6;
  411. rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  412. rmsghdr.msg_control = (caddr_t) cmsgbuf;
  413. rmsghdr.msg_controllen = sizeof (cmsgbuf);
  414. retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);
  415. if (retval != iov_totallen (message))
  416. zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
  417. /* source address */
  418. assert (src);
  419. memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
  420. /* destination address */
  421. if (ifindex)
  422. *ifindex = pktinfo->ipi6_ifindex;
  423. if (dst)
  424. memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
  425. }