]> git.proxmox.com Git - mirror_frr.git/blob - babeld/net.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / babeld / net.c
1 /*
2 Copyright (c) 2007, 2008 by Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <sys/uio.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <arpa/inet.h>
38 #include <errno.h>
39
40 #include "babeld.h"
41 #include "util.h"
42 #include "net.h"
43 #include "sockopt.h"
44
45 int
46 babel_socket(int port)
47 {
48 struct sockaddr_in6 sin6;
49 int s, rc;
50 int saved_errno;
51 int one = 1, zero = 0;
52
53 s = socket(PF_INET6, SOCK_DGRAM, 0);
54 if(s < 0)
55 return -1;
56
57 rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
58 if(rc < 0)
59 goto fail;
60
61 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
62 if(rc < 0)
63 goto fail;
64
65 rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
66 &zero, sizeof(zero));
67 if(rc < 0)
68 goto fail;
69
70 rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
71 &one, sizeof(one));
72 if(rc < 0)
73 goto fail;
74
75 rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
76 &one, sizeof(one));
77 if(rc < 0)
78 goto fail;
79
80 setsockopt_ipv6_tclass (s, IPTOS_PREC_INTERNETCONTROL);
81
82 rc = fcntl(s, F_GETFL, 0);
83 if(rc < 0)
84 goto fail;
85
86 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
87 if(rc < 0)
88 goto fail;
89
90 rc = fcntl(s, F_GETFD, 0);
91 if(rc < 0)
92 goto fail;
93
94 rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
95 if(rc < 0)
96 goto fail;
97
98 memset(&sin6, 0, sizeof(sin6));
99 sin6.sin6_family = AF_INET6;
100 sin6.sin6_port = htons(port);
101 rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
102 if(rc < 0)
103 goto fail;
104
105 return s;
106
107 fail:
108 saved_errno = errno;
109 close(s);
110 errno = saved_errno;
111 return -1;
112 }
113
114 int
115 babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen)
116 {
117 struct iovec iovec;
118 struct msghdr msg;
119 int rc;
120
121 memset(&msg, 0, sizeof(msg));
122 iovec.iov_base = buf;
123 iovec.iov_len = buflen;
124 msg.msg_name = sin;
125 msg.msg_namelen = slen;
126 msg.msg_iov = &iovec;
127 msg.msg_iovlen = 1;
128
129 rc = recvmsg(s, &msg, 0);
130 return rc;
131 }
132
133 int
134 babel_send(int s,
135 void *buf1, int buflen1, void *buf2, int buflen2,
136 struct sockaddr *sin, int slen)
137 {
138 struct iovec iovec[2];
139 struct msghdr msg;
140 int rc;
141
142 iovec[0].iov_base = buf1;
143 iovec[0].iov_len = buflen1;
144 iovec[1].iov_base = buf2;
145 iovec[1].iov_len = buflen2;
146 memset(&msg, 0, sizeof(msg));
147 msg.msg_name = (struct sockaddr*)sin;
148 msg.msg_namelen = slen;
149 msg.msg_iov = iovec;
150 msg.msg_iovlen = 2;
151
152 again:
153 rc = sendmsg(s, &msg, 0);
154 if(rc < 0) {
155 if(errno == EINTR)
156 goto again;
157 else if(errno == EAGAIN) {
158 int rc2;
159 rc2 = wait_for_fd(1, s, 5);
160 if(rc2 > 0)
161 goto again;
162 errno = EAGAIN;
163 }
164 }
165 return rc;
166 }
167
168 int
169 tcp_server_socket(int port, int local)
170 {
171 struct sockaddr_in6 sin6;
172 int s, rc, saved_errno;
173 int one = 1;
174
175 s = socket(PF_INET6, SOCK_STREAM, 0);
176 if(s < 0)
177 return -1;
178
179 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
180 if(rc < 0)
181 goto fail;
182
183 rc = fcntl(s, F_GETFL, 0);
184 if(rc < 0)
185 goto fail;
186
187 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
188 if(rc < 0)
189 goto fail;
190
191 rc = fcntl(s, F_GETFD, 0);
192 if(rc < 0)
193 goto fail;
194
195 rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
196 if(rc < 0)
197 goto fail;
198
199 memset(&sin6, 0, sizeof(sin6));
200 sin6.sin6_family = AF_INET6;
201 sin6.sin6_port = htons(port);
202 if(local) {
203 rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr);
204 if(rc < 0)
205 goto fail;
206 }
207 rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
208 if(rc < 0)
209 goto fail;
210
211 rc = listen(s, 2);
212 if(rc < 0)
213 goto fail;
214
215 return s;
216
217 fail:
218 saved_errno = errno;
219 close(s);
220 errno = saved_errno;
221 return -1;
222 }