PageRenderTime 62ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/babeld/net.c

#
C | 239 lines | 168 code | 34 blank | 37 comment | 29 complexity | ea751220a6fd9cb0f1dd0e10dae41ccc MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /*
  2. * This file is free software: you may copy, redistribute and/or modify it
  3. * under the terms of the GNU General Public License as published by the
  4. * Free Software Foundation, either version 2 of the License, or (at your
  5. * option) any later version.
  6. *
  7. * This file is distributed in the hope that it will be useful, but
  8. * WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. * General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. *
  15. * This file incorporates work covered by the following copyright and
  16. * permission notice:
  17. *
  18. Copyright (c) 2007, 2008 by Juliusz Chroboczek
  19. Permission is hereby granted, free of charge, to any person obtaining a copy
  20. of this software and associated documentation files (the "Software"), to deal
  21. in the Software without restriction, including without limitation the rights
  22. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  23. copies of the Software, and to permit persons to whom the Software is
  24. furnished to do so, subject to the following conditions:
  25. The above copyright notice and this permission notice shall be included in
  26. all copies or substantial portions of the Software.
  27. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  30. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  31. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  32. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  33. THE SOFTWARE.
  34. */
  35. #include <unistd.h>
  36. #include <fcntl.h>
  37. #include <string.h>
  38. #include <sys/ioctl.h>
  39. #include <sys/types.h>
  40. #include <sys/uio.h>
  41. #include <sys/socket.h>
  42. #include <netinet/in.h>
  43. #include <arpa/inet.h>
  44. #include <errno.h>
  45. #include "babeld.h"
  46. #include "util.h"
  47. #include "net.h"
  48. int
  49. babel_socket(int port)
  50. {
  51. struct sockaddr_in6 sin6;
  52. int s, rc;
  53. int saved_errno;
  54. int one = 1, zero = 0;
  55. const int ds = 0xc0; /* CS6 - Network Control */
  56. s = socket(PF_INET6, SOCK_DGRAM, 0);
  57. if(s < 0)
  58. return -1;
  59. rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
  60. if(rc < 0)
  61. goto fail;
  62. rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  63. if(rc < 0)
  64. goto fail;
  65. rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
  66. &zero, sizeof(zero));
  67. if(rc < 0)
  68. goto fail;
  69. rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  70. &one, sizeof(one));
  71. if(rc < 0)
  72. goto fail;
  73. rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
  74. &one, sizeof(one));
  75. if(rc < 0)
  76. goto fail;
  77. #ifdef IPV6_TCLASS
  78. rc = setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &ds, sizeof(ds));
  79. #else
  80. rc = -1;
  81. errno = ENOSYS;
  82. #endif
  83. if(rc < 0)
  84. perror("Couldn't set traffic class");
  85. rc = fcntl(s, F_GETFL, 0);
  86. if(rc < 0)
  87. goto fail;
  88. rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
  89. if(rc < 0)
  90. goto fail;
  91. rc = fcntl(s, F_GETFD, 0);
  92. if(rc < 0)
  93. goto fail;
  94. rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
  95. if(rc < 0)
  96. goto fail;
  97. memset(&sin6, 0, sizeof(sin6));
  98. sin6.sin6_family = AF_INET6;
  99. sin6.sin6_port = htons(port);
  100. rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
  101. if(rc < 0)
  102. goto fail;
  103. return s;
  104. fail:
  105. saved_errno = errno;
  106. close(s);
  107. errno = saved_errno;
  108. return -1;
  109. }
  110. int
  111. babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen)
  112. {
  113. struct iovec iovec;
  114. struct msghdr msg;
  115. int rc;
  116. memset(&msg, 0, sizeof(msg));
  117. iovec.iov_base = buf;
  118. iovec.iov_len = buflen;
  119. msg.msg_name = sin;
  120. msg.msg_namelen = slen;
  121. msg.msg_iov = &iovec;
  122. msg.msg_iovlen = 1;
  123. rc = recvmsg(s, &msg, 0);
  124. return rc;
  125. }
  126. int
  127. babel_send(int s,
  128. void *buf1, int buflen1, void *buf2, int buflen2,
  129. struct sockaddr *sin, int slen)
  130. {
  131. struct iovec iovec[2];
  132. struct msghdr msg;
  133. int rc;
  134. iovec[0].iov_base = buf1;
  135. iovec[0].iov_len = buflen1;
  136. iovec[1].iov_base = buf2;
  137. iovec[1].iov_len = buflen2;
  138. memset(&msg, 0, sizeof(msg));
  139. msg.msg_name = (struct sockaddr*)sin;
  140. msg.msg_namelen = slen;
  141. msg.msg_iov = iovec;
  142. msg.msg_iovlen = 2;
  143. again:
  144. rc = sendmsg(s, &msg, 0);
  145. if(rc < 0) {
  146. if(errno == EINTR)
  147. goto again;
  148. else if(errno == EAGAIN) {
  149. int rc2;
  150. rc2 = wait_for_fd(1, s, 5);
  151. if(rc2 > 0)
  152. goto again;
  153. errno = EAGAIN;
  154. }
  155. }
  156. return rc;
  157. }
  158. int
  159. tcp_server_socket(int port, int local)
  160. {
  161. struct sockaddr_in6 sin6;
  162. int s, rc, saved_errno;
  163. int one = 1;
  164. s = socket(PF_INET6, SOCK_STREAM, 0);
  165. if(s < 0)
  166. return -1;
  167. rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  168. if(rc < 0)
  169. goto fail;
  170. rc = fcntl(s, F_GETFL, 0);
  171. if(rc < 0)
  172. goto fail;
  173. rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
  174. if(rc < 0)
  175. goto fail;
  176. rc = fcntl(s, F_GETFD, 0);
  177. if(rc < 0)
  178. goto fail;
  179. rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
  180. if(rc < 0)
  181. goto fail;
  182. memset(&sin6, 0, sizeof(sin6));
  183. sin6.sin6_family = AF_INET6;
  184. sin6.sin6_port = htons(port);
  185. if(local) {
  186. rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr);
  187. if(rc < 0)
  188. goto fail;
  189. }
  190. rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
  191. if(rc < 0)
  192. goto fail;
  193. rc = listen(s, 2);
  194. if(rc < 0)
  195. goto fail;
  196. return s;
  197. fail:
  198. saved_errno = errno;
  199. close(s);
  200. errno = saved_errno;
  201. return -1;
  202. }