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