PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/uClinux-dist/user/zebra/ospf6d/ospf6_network.c

https://github.com/labx-technologies-llc/mb-linux-labx
C | 501 lines | 390 code | 69 blank | 42 comment | 33 complexity | 0b5b1dd036d624ec0e84349429780948 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, ISC, AGPL-1.0, LGPL-2.0, GPL-3.0, LGPL-3.0, 0BSD
  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. #if 0
  222. else
  223. zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
  224. #endif
  225. }
  226. void
  227. ospf6_join_alldrouters (u_int ifindex)
  228. {
  229. struct ipv6_mreq mreq6;
  230. assert (ifindex);
  231. mreq6.ipv6mr_interface = ifindex;
  232. memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
  233. sizeof (struct in6_addr));
  234. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  235. &mreq6, sizeof (mreq6)) < 0)
  236. zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
  237. ifindex, strerror (errno));
  238. #if 0
  239. else
  240. zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
  241. #endif
  242. }
  243. void
  244. ospf6_leave_alldrouters (u_int ifindex)
  245. {
  246. struct ipv6_mreq mreq6;
  247. assert (ifindex);
  248. mreq6.ipv6mr_interface = ifindex;
  249. memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
  250. sizeof (struct in6_addr));
  251. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  252. &mreq6, sizeof (mreq6)) < 0)
  253. zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
  254. #if 0
  255. else
  256. zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
  257. #endif
  258. }
  259. /* setsockopt ReUseAddr to on */
  260. void
  261. ospf6_set_reuseaddr ()
  262. {
  263. u_int on = 0;
  264. if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on,
  265. sizeof (u_int)) < 0)
  266. zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno));
  267. }
  268. /* setsockopt MulticastLoop to off */
  269. void
  270. ospf6_reset_mcastloop ()
  271. {
  272. u_int off = 0;
  273. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
  274. &off, sizeof (u_int)) < 0)
  275. zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
  276. strerror (errno));
  277. }
  278. void
  279. ospf6_set_pktinfo ()
  280. {
  281. u_int on = 1;
  282. #ifdef IPV6_RECVPKTINFO /*2292bis-01*/
  283. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  284. &on, sizeof (u_int)) < 0)
  285. zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno));
  286. #else /*RFC2292*/
  287. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO,
  288. &on, sizeof (u_int)) < 0)
  289. zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno));
  290. #endif
  291. }
  292. void
  293. ospf6_set_checksum ()
  294. {
  295. int offset = 12;
  296. #ifndef DISABLE_IPV6_CHECKSUM
  297. if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
  298. &offset, sizeof (offset)) < 0)
  299. zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
  300. #else
  301. zlog_warn ("Network: Don't set IPV6_CHECKSUM");
  302. #endif /* DISABLE_IPV6_CHECKSUM */
  303. }
  304. void
  305. ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
  306. unsigned int *ifindex, struct iovec *message)
  307. {
  308. int retval;
  309. struct msghdr smsghdr;
  310. struct cmsghdr *scmsgp;
  311. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  312. struct in6_pktinfo *pktinfo;
  313. struct sockaddr_in6 dst_sin6;
  314. assert (dst);
  315. assert (*ifindex);
  316. scmsgp = (struct cmsghdr *)cmsgbuf;
  317. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
  318. memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));
  319. /* source address */
  320. pktinfo->ipi6_ifindex = *ifindex;
  321. if (src)
  322. memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
  323. else
  324. memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));
  325. /* destination address */
  326. dst_sin6.sin6_family = AF_INET6;
  327. #ifdef SIN6_LEN
  328. dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
  329. #endif /*SIN6_LEN*/
  330. memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
  331. #ifdef HAVE_SIN6_SCOPE_ID
  332. dst_sin6.sin6_scope_id = *ifindex;
  333. #endif
  334. /* send control msg */
  335. scmsgp->cmsg_level = IPPROTO_IPV6;
  336. scmsgp->cmsg_type = IPV6_PKTINFO;
  337. scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  338. /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
  339. /* send msg hdr */
  340. smsghdr.msg_iov = message;
  341. smsghdr.msg_iovlen = iov_count (message);
  342. smsghdr.msg_name = (caddr_t) &dst_sin6;
  343. smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  344. smsghdr.msg_control = (caddr_t) cmsgbuf;
  345. smsghdr.msg_controllen = sizeof (cmsgbuf);
  346. retval = sendmsg (ospf6_sock, &smsghdr, 0);
  347. if (retval != iov_totallen (message))
  348. zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",
  349. *ifindex, strerror (errno), errno);
  350. }
  351. void
  352. ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
  353. unsigned int *ifindex, struct iovec *message)
  354. {
  355. int retval;
  356. struct msghdr rmsghdr;
  357. struct cmsghdr *rcmsgp;
  358. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  359. struct in6_pktinfo *pktinfo;
  360. struct sockaddr_in6 src_sin6;
  361. rcmsgp = (struct cmsghdr *)cmsgbuf;
  362. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
  363. memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
  364. /* receive control msg */
  365. rcmsgp->cmsg_level = IPPROTO_IPV6;
  366. rcmsgp->cmsg_type = IPV6_PKTINFO;
  367. rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  368. /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
  369. /* receive msg hdr */
  370. rmsghdr.msg_iov = message;
  371. rmsghdr.msg_iovlen = iov_count (message);
  372. rmsghdr.msg_name = (caddr_t) &src_sin6;
  373. rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  374. rmsghdr.msg_control = (caddr_t) cmsgbuf;
  375. rmsghdr.msg_controllen = sizeof (cmsgbuf);
  376. retval = recvmsg (ospf6_sock, &rmsghdr, 0);
  377. if (retval < 0)
  378. {
  379. zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
  380. }
  381. else if (retval == iov_totallen (message))
  382. {
  383. zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",
  384. retval, iov_totallen (message));
  385. }
  386. /* source address */
  387. assert (src);
  388. memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
  389. /* destination address */
  390. if (ifindex)
  391. *ifindex = pktinfo->ipi6_ifindex;
  392. if (dst)
  393. memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
  394. }
  395. void
  396. ospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,
  397. unsigned int *ifindex, struct iovec *message)
  398. {
  399. int retval;
  400. struct msghdr rmsghdr;
  401. struct cmsghdr *rcmsgp;
  402. u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  403. struct in6_pktinfo *pktinfo;
  404. struct sockaddr_in6 src_sin6;
  405. rcmsgp = (struct cmsghdr *)cmsgbuf;
  406. pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
  407. memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
  408. /* receive control msg */
  409. rcmsgp->cmsg_level = IPPROTO_IPV6;
  410. rcmsgp->cmsg_type = IPV6_PKTINFO;
  411. rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  412. /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
  413. /* receive msg hdr */
  414. rmsghdr.msg_iov = message;
  415. rmsghdr.msg_iovlen = iov_count (message);
  416. rmsghdr.msg_name = (caddr_t) &src_sin6;
  417. rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  418. rmsghdr.msg_control = (caddr_t) cmsgbuf;
  419. rmsghdr.msg_controllen = sizeof (cmsgbuf);
  420. retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);
  421. if (retval != iov_totallen (message))
  422. zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
  423. /* source address */
  424. assert (src);
  425. memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
  426. /* destination address */
  427. if (ifindex)
  428. *ifindex = pktinfo->ipi6_ifindex;
  429. if (dst)
  430. memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
  431. }