]> git.proxmox.com Git - mirror_frr.git/blame - babeld/net.c
Merge pull request #13386 from donaldsharp/bgp_received_routes
[mirror_frr.git] / babeld / net.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: MIT
ca10883e
DS
2/*
3Copyright (c) 2007, 2008 by Juliusz Chroboczek
ca10883e
DS
4*/
5
b45ac5f5
DL
6#ifdef HAVE_CONFIG_H
7#include "config.h"
8#endif
9
ca10883e
DS
10#include <unistd.h>
11#include <fcntl.h>
12#include <string.h>
13#include <sys/ioctl.h>
14#include <sys/types.h>
15#include <sys/uio.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <netinet/in_systm.h>
19#include <netinet/ip.h>
20#include <arpa/inet.h>
21#include <errno.h>
22
23#include "babeld.h"
24#include "util.h"
25#include "net.h"
26#include "sockopt.h"
27
28int
29babel_socket(int port)
30{
31 struct sockaddr_in6 sin6;
32 int s, rc;
33 int saved_errno;
34 int one = 1, zero = 0;
35
36 s = socket(PF_INET6, SOCK_DGRAM, 0);
37 if(s < 0)
38 return -1;
39
40 rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
41 if(rc < 0)
42 goto fail;
43
44 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
45 if(rc < 0)
46 goto fail;
47
48 rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
49 &zero, sizeof(zero));
50 if(rc < 0)
51 goto fail;
52
53 rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
54 &one, sizeof(one));
55 if(rc < 0)
56 goto fail;
57
58 rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
59 &one, sizeof(one));
60 if(rc < 0)
61 goto fail;
62
63 setsockopt_ipv6_tclass (s, IPTOS_PREC_INTERNETCONTROL);
64
65 rc = fcntl(s, F_GETFL, 0);
66 if(rc < 0)
67 goto fail;
68
69 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
70 if(rc < 0)
71 goto fail;
72
73 rc = fcntl(s, F_GETFD, 0);
74 if(rc < 0)
75 goto fail;
76
77 rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
78 if(rc < 0)
79 goto fail;
80
81 memset(&sin6, 0, sizeof(sin6));
82 sin6.sin6_family = AF_INET6;
83 sin6.sin6_port = htons(port);
84 rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
85 if(rc < 0)
86 goto fail;
87
88 return s;
89
90 fail:
91 saved_errno = errno;
92 close(s);
93 errno = saved_errno;
94 return -1;
95}
96
97int
98babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen)
99{
100 struct iovec iovec;
101 struct msghdr msg;
102 int rc;
103
104 memset(&msg, 0, sizeof(msg));
105 iovec.iov_base = buf;
106 iovec.iov_len = buflen;
107 msg.msg_name = sin;
108 msg.msg_namelen = slen;
109 msg.msg_iov = &iovec;
110 msg.msg_iovlen = 1;
111
112 rc = recvmsg(s, &msg, 0);
113 return rc;
114}
115
116int
117babel_send(int s,
118 void *buf1, int buflen1, void *buf2, int buflen2,
119 struct sockaddr *sin, int slen)
120{
121 struct iovec iovec[2];
122 struct msghdr msg;
123 int rc;
124
125 iovec[0].iov_base = buf1;
126 iovec[0].iov_len = buflen1;
127 iovec[1].iov_base = buf2;
128 iovec[1].iov_len = buflen2;
129 memset(&msg, 0, sizeof(msg));
c4efd0f4 130 msg.msg_name = sin;
ca10883e
DS
131 msg.msg_namelen = slen;
132 msg.msg_iov = iovec;
133 msg.msg_iovlen = 2;
134
135 again:
136 rc = sendmsg(s, &msg, 0);
137 if(rc < 0) {
138 if(errno == EINTR)
139 goto again;
140 else if(errno == EAGAIN) {
141 int rc2;
142 rc2 = wait_for_fd(1, s, 5);
143 if(rc2 > 0)
144 goto again;
145 errno = EAGAIN;
146 }
147 }
148 return rc;
149}
150
151int
152tcp_server_socket(int port, int local)
153{
154 struct sockaddr_in6 sin6;
155 int s, rc, saved_errno;
156 int one = 1;
157
158 s = socket(PF_INET6, SOCK_STREAM, 0);
159 if(s < 0)
160 return -1;
161
162 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
163 if(rc < 0)
164 goto fail;
165
166 rc = fcntl(s, F_GETFL, 0);
167 if(rc < 0)
168 goto fail;
169
170 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
171 if(rc < 0)
172 goto fail;
173
174 rc = fcntl(s, F_GETFD, 0);
175 if(rc < 0)
176 goto fail;
177
178 rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
179 if(rc < 0)
180 goto fail;
181
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
194 rc = listen(s, 2);
195 if(rc < 0)
196 goto fail;
197
198 return s;
199
200 fail:
201 saved_errno = errno;
202 close(s);
203 errno = saved_errno;
204 return -1;
205}