/src/openweave-core/src/inet/TunEndPoint.cpp
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2014-2017 Nest Labs, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | */ |
18 | | |
19 | | /** |
20 | | * @file |
21 | | * This file implements the TunnelEndPoint abstraction APIs in the Inet |
22 | | * Layer for creation and management of tunnel interfaces instantiated |
23 | | * within either Linux Sockets or LwIP. |
24 | | * |
25 | | */ |
26 | | |
27 | | #ifndef __STDC_LIMIT_MACROS |
28 | | #define __STDC_LIMIT_MACROS |
29 | | #endif |
30 | | |
31 | | #include <InetLayer/TunEndPoint.h> |
32 | | #include <InetLayer/InetLayer.h> |
33 | | |
34 | | #include <string.h> |
35 | | #include <stdio.h> |
36 | | |
37 | | #include <Weave/Core/WeaveEncoding.h> |
38 | | #include <Weave/Support/CodeUtils.h> |
39 | | |
40 | | #include "arpa-inet-compatibility.h" |
41 | | |
42 | | namespace nl { |
43 | | namespace Inet { |
44 | | |
45 | | using Weave::System::PacketBuffer; |
46 | | |
47 | | Weave::System::ObjectPool<TunEndPoint, INET_CONFIG_NUM_TUN_ENDPOINTS> TunEndPoint::sPool; |
48 | | |
49 | | using namespace nl::Weave::Encoding; |
50 | | |
51 | | /** |
52 | | * Initialize the Tunnel EndPoint object. |
53 | | * |
54 | | * @note |
55 | | * By convention, the \c Init method on \c EndPointBasis |
56 | | * subclasses is \c private. It should not be used outside \c InetLayer. |
57 | | * |
58 | | * @param[in] inetLayer A pointer to the Inet layer object that |
59 | | * created the Tunnel EndPoint. |
60 | | * |
61 | | */ |
62 | | void TunEndPoint::Init(InetLayer *inetLayer) |
63 | 0 | { |
64 | 0 | InitEndPointBasis(*inetLayer); |
65 | 0 | } |
66 | | |
67 | | /** |
68 | | * Open a tunnel pseudo interface and create a handle to it. |
69 | | * |
70 | | * @note |
71 | | * This method has different signatures on LwIP systems and |
72 | | * POSIX systems. On LwIP, there is an argument for specifying the name |
73 | | * of the tunnel interface. On POSIX, the method has no arguments and the |
74 | | * name of the tunnel device is implied. |
75 | | * |
76 | | * @return INET_NO_ERROR on success, else a corresponding INET mapped OS error. |
77 | | */ |
78 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
79 | | INET_ERROR TunEndPoint::Open (void) |
80 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
81 | | |
82 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
83 | | INET_ERROR TunEndPoint::Open (const char *intfName) |
84 | | #endif //WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
85 | 0 | { |
86 | 0 | INET_ERROR err = INET_NO_ERROR; |
87 | |
|
88 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
89 | | struct netif *tNetif = NULL; |
90 | | // Lock LwIP stack |
91 | | LOCK_TCPIP_CORE(); |
92 | | |
93 | | tNetif = netif_add(&mTunNetIf, NULL, NULL, NULL, this, TunInterfaceNetifInit, tcpip_input); |
94 | | |
95 | | // UnLock LwIP stack |
96 | | UNLOCK_TCPIP_CORE(); |
97 | | |
98 | | VerifyOrExit(tNetif != NULL, err = INET_ERROR_INTERFACE_INIT_FAILURE); |
99 | | |
100 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
101 | |
|
102 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
103 | | |
104 | | //Create the tunnel device |
105 | 0 | err = TunDevOpen(intfName); |
106 | 0 | SuccessOrExit(err); |
107 | | |
108 | 0 | printf("Opened tunnel device: %s\n", intfName); |
109 | |
|
110 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
111 | |
|
112 | 0 | if (err == INET_NO_ERROR) |
113 | 0 | mState = kState_Open; |
114 | |
|
115 | 0 | exit: |
116 | |
|
117 | 0 | return err; |
118 | 0 | } |
119 | | |
120 | | /** |
121 | | * Close the tunnel pseudo interface device. |
122 | | * |
123 | | */ |
124 | | void TunEndPoint::Close (void) |
125 | 0 | { |
126 | 0 | if (mState != kState_Closed) |
127 | 0 | { |
128 | | |
129 | | // For LwIP, we do not remove the netif as it would have |
130 | | // an impact on the interface iterator in Weave which |
131 | | // might lose reference to a particular netif index that |
132 | | // it might be holding on to. |
133 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
134 | 0 | if (mSocket >= 0) |
135 | 0 | { |
136 | 0 | Weave::System::Layer& lSystemLayer = SystemLayer(); |
137 | | |
138 | | // Wake the thread calling select so that it recognizes the socket is closed. |
139 | 0 | lSystemLayer.WakeSelect(); |
140 | 0 | TunDevClose(); |
141 | 0 | } |
142 | | |
143 | | // Clear any results from select() that indicate pending I/O for the socket. |
144 | 0 | mPendingIO.Clear(); |
145 | |
|
146 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
147 | 0 | mState = kState_Closed; |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | | /** |
152 | | * Close the tunnel pseudo interface device and decrement the reference count |
153 | | * of the InetLayer object. |
154 | | * |
155 | | */ |
156 | | void TunEndPoint::Free() |
157 | 0 | { |
158 | 0 | Close(); |
159 | |
|
160 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
161 | | DeferredFree(kReleaseDeferralErrorTactic_Release); |
162 | | #else // !WEAVE_SYSTEM_CONFIG_USE_LWIP |
163 | 0 | Release(); |
164 | 0 | #endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * Send an IPv6 packet to the tun device to be sent out. |
169 | | * |
170 | | * @note |
171 | | * This method performs a couple of minimal sanity checks on the packet to |
172 | | * be sure it is IP version 6 then dispatches it for encapsulation in a |
173 | | * Weave tunneling message. |
174 | | * |
175 | | * @param[in] message the IPv6 packet to send. |
176 | | * |
177 | | * @retval INET_NO_ERROR success: packet encapsulated and queued to send |
178 | | * @retval INET_ERROR_NOT_SUPPORTED packet not IP version 6 |
179 | | * @retval INET_ERROR_BAD_ARGS \c message is a \c NULL pointer |
180 | | * |
181 | | */ |
182 | | INET_ERROR TunEndPoint::Send (PacketBuffer *msg) |
183 | 0 | { |
184 | 0 | INET_ERROR ret = INET_NO_ERROR; |
185 | |
|
186 | 0 | ret = CheckV6Sanity(msg); |
187 | |
|
188 | 0 | if (ret == INET_NO_ERROR) |
189 | 0 | { |
190 | 0 | ret = TunDevSendMessage(msg); |
191 | 0 | } |
192 | |
|
193 | 0 | return ret; |
194 | 0 | } |
195 | | |
196 | | /** |
197 | | * Extract the activation state of the tunnel interface. |
198 | | * |
199 | | * @returns \c true if the tunnel interface is active, |
200 | | * otherwise \c false. |
201 | | */ |
202 | | bool TunEndPoint::IsInterfaceUp (void) const |
203 | 0 | { |
204 | 0 | bool ret = false; |
205 | |
|
206 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
207 | | // Lock LwIP stack |
208 | | LOCK_TCPIP_CORE(); |
209 | | |
210 | | ret = netif_is_up(&mTunNetIf); |
211 | | |
212 | | // UnLock LwIP stack |
213 | | UNLOCK_TCPIP_CORE(); |
214 | | |
215 | | ExitNow(); |
216 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
217 | |
|
218 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
219 | 0 | int sockfd = INET_INVALID_SOCKET_FD; |
220 | 0 | struct ::ifreq ifr; |
221 | |
|
222 | 0 | memset(&ifr, 0, sizeof(ifr)); |
223 | | |
224 | | //Get interface |
225 | 0 | if (TunGetInterface(mSocket, &ifr) < 0) |
226 | 0 | { |
227 | 0 | ExitNow(); |
228 | 0 | } |
229 | | |
230 | 0 | sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); |
231 | 0 | if (sockfd < 0) |
232 | 0 | { |
233 | 0 | ExitNow(); |
234 | 0 | } |
235 | | |
236 | | //Get interface flags |
237 | 0 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) |
238 | 0 | { |
239 | 0 | ExitNow(); |
240 | 0 | } |
241 | | |
242 | 0 | ret = ((ifr.ifr_flags & IFF_UP) == IFF_UP); |
243 | |
|
244 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
245 | |
|
246 | 0 | exit: |
247 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
248 | 0 | if (sockfd >= 0) |
249 | 0 | { |
250 | 0 | close(sockfd); |
251 | 0 | } |
252 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
253 | |
|
254 | 0 | return ret; |
255 | 0 | } |
256 | | |
257 | | /** |
258 | | * Activate the tunnel interface. |
259 | | * |
260 | | * @retval INET_NO_ERROR success: tunnel interface is activated. |
261 | | * @retval other another system or platform error |
262 | | */ |
263 | | INET_ERROR TunEndPoint::InterfaceUp (void) |
264 | 0 | { |
265 | 0 | INET_ERROR err = INET_NO_ERROR; |
266 | |
|
267 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
268 | | // Lock LwIP stack |
269 | | LOCK_TCPIP_CORE(); |
270 | | |
271 | | netif_set_up(&mTunNetIf); |
272 | | |
273 | | // UnLock LwIP stack |
274 | | UNLOCK_TCPIP_CORE(); |
275 | | |
276 | | ExitNow(); |
277 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
278 | |
|
279 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
280 | 0 | int sockfd = INET_INVALID_SOCKET_FD; |
281 | 0 | struct ::ifreq ifr; |
282 | |
|
283 | 0 | memset(&ifr, 0, sizeof(ifr)); |
284 | | |
285 | | //Get interface |
286 | 0 | if (TunGetInterface(mSocket, &ifr) < 0) |
287 | 0 | { |
288 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
289 | 0 | } |
290 | | |
291 | 0 | sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); |
292 | 0 | if (sockfd < 0) |
293 | 0 | { |
294 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
295 | 0 | } |
296 | | |
297 | | //Get interface flags |
298 | 0 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) |
299 | 0 | { |
300 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
301 | 0 | } |
302 | | |
303 | | //Set flag to activate interface |
304 | 0 | ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); |
305 | 0 | if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) |
306 | 0 | { |
307 | 0 | err = Weave::System::MapErrorPOSIX(errno); |
308 | 0 | } |
309 | | |
310 | | //Set the MTU |
311 | 0 | ifr.ifr_mtu = WEAVE_CONFIG_TUNNEL_INTERFACE_MTU; |
312 | 0 | if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) |
313 | 0 | { |
314 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
315 | 0 | } |
316 | | |
317 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
318 | | |
319 | 0 | exit: |
320 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
321 | 0 | if (sockfd >= 0) |
322 | 0 | { |
323 | 0 | close(sockfd); |
324 | 0 | } |
325 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
326 | |
|
327 | 0 | return err; |
328 | 0 | } |
329 | | |
330 | | /** |
331 | | * @brief Deactivate the tunnel interface. |
332 | | * |
333 | | * @retval INET_NO_ERROR success: tunnel interface is deactivated. |
334 | | * @retval other another system or platform error |
335 | | */ |
336 | | INET_ERROR TunEndPoint::InterfaceDown (void) |
337 | 0 | { |
338 | 0 | INET_ERROR err = INET_NO_ERROR; |
339 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
340 | 0 | int sockfd = INET_INVALID_SOCKET_FD; |
341 | 0 | struct ::ifreq ifr; |
342 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
343 | |
|
344 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
345 | | // Lock LwIP stack |
346 | | LOCK_TCPIP_CORE(); |
347 | | |
348 | | //Remove the link local address from the netif |
349 | | memset(&(mTunNetIf.ip6_addr[0]), 0, sizeof(ip6_addr_t)); |
350 | | |
351 | | netif_set_down(&mTunNetIf); |
352 | | |
353 | | // UnLock LwIP stack |
354 | | UNLOCK_TCPIP_CORE(); |
355 | | |
356 | | ExitNow(); |
357 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
358 | |
|
359 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
360 | 0 | memset(&ifr, 0, sizeof(ifr)); |
361 | | |
362 | | //Get interface |
363 | 0 | if (TunGetInterface(mSocket, &ifr) < 0) |
364 | 0 | { |
365 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
366 | 0 | } |
367 | | |
368 | 0 | sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); |
369 | 0 | if (sockfd < 0) |
370 | 0 | { |
371 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
372 | 0 | } |
373 | | |
374 | | //Get interface flags |
375 | 0 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) |
376 | 0 | { |
377 | 0 | ExitNow(err = Weave::System::MapErrorPOSIX(errno)); |
378 | 0 | } |
379 | | |
380 | | //Set flag to deactivate interface |
381 | 0 | ifr.ifr_flags &= ~(IFF_UP); |
382 | 0 | if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) |
383 | 0 | { |
384 | 0 | err = Weave::System::MapErrorPOSIX(errno); |
385 | 0 | } |
386 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
387 | |
|
388 | 0 | exit: |
389 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
390 | 0 | if (sockfd >= 0) |
391 | 0 | { |
392 | 0 | close(sockfd); |
393 | 0 | } |
394 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
395 | |
|
396 | 0 | return err; |
397 | 0 | } |
398 | | |
399 | | /** |
400 | | * @brief Get the tunnel interface identifier. |
401 | | * |
402 | | * @return The tunnel interface identifier. |
403 | | */ |
404 | | InterfaceId TunEndPoint::GetTunnelInterfaceId(void) |
405 | 0 | { |
406 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
407 | | return &mTunNetIf; |
408 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
409 | |
|
410 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
411 | 0 | INET_ERROR err = INET_NO_ERROR; |
412 | 0 | InterfaceId tunIntfId = INET_NULL_INTERFACEID; |
413 | 0 | const char *tunIntfPtr = &tunIntfName[0]; |
414 | |
|
415 | 0 | err = InterfaceNameToId(tunIntfPtr, tunIntfId); |
416 | 0 | if (err != INET_NO_ERROR) |
417 | 0 | { |
418 | 0 | tunIntfId = INET_NULL_INTERFACEID; |
419 | 0 | } |
420 | |
|
421 | 0 | return tunIntfId; |
422 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
423 | 0 | } |
424 | | |
425 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
426 | | /* Function for sending the IPv6 packets over LwIP */ |
427 | | INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg) |
428 | | { |
429 | | INET_ERROR ret = INET_NO_ERROR; |
430 | | struct pbuf *p = NULL; |
431 | | err_t err = ERR_OK; |
432 | | |
433 | | // no packet could be read, silently ignore this |
434 | | VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS); |
435 | | |
436 | | p = (struct pbuf *)msg; |
437 | | |
438 | | //Call the input function for the netif object in LWIP. |
439 | | //This essentially creates a TCP_IP msg and puts into |
440 | | //the mbox message queue for processing by the TCP/IP |
441 | | //stack. |
442 | | |
443 | | if ((err = tcpip_input(p, &mTunNetIf)) != ERR_OK) |
444 | | { |
445 | | LWIP_DEBUGF(NETIF_DEBUG, ("tunNetif_input: IP input error\n")); |
446 | | ExitNow(ret = Weave::System::MapErrorLwIP(err)); |
447 | | } |
448 | | |
449 | | exit: |
450 | | return (ret); |
451 | | } |
452 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
453 | | |
454 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
455 | | /* Function for sending the IPv6 packets over Linux sockets */ |
456 | | INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg) |
457 | 0 | { |
458 | 0 | INET_ERROR ret = INET_NO_ERROR; |
459 | 0 | ssize_t lenSent = 0; |
460 | 0 | uint8_t *p = NULL; |
461 | | |
462 | | // no packet could be read, silently ignore this |
463 | 0 | VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS); |
464 | | |
465 | 0 | p = msg->Start(); |
466 | |
|
467 | 0 | lenSent = write(mSocket, p, msg->DataLength()); |
468 | 0 | if (lenSent < 0) |
469 | 0 | { |
470 | 0 | ExitNow(ret = Weave::System::MapErrorPOSIX(errno)); |
471 | 0 | } |
472 | 0 | else if (lenSent < msg->DataLength()) |
473 | 0 | { |
474 | 0 | ExitNow(ret = INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED); |
475 | 0 | } |
476 | | |
477 | 0 | exit: |
478 | 0 | if (msg != NULL) |
479 | 0 | { |
480 | 0 | PacketBuffer::Free(msg); |
481 | 0 | } |
482 | |
|
483 | 0 | return (ret); |
484 | 0 | } |
485 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
486 | | |
487 | | /* Function that performs some basic sanity checks for IPv6 packets */ |
488 | | INET_ERROR TunEndPoint::CheckV6Sanity (PacketBuffer *msg) |
489 | 0 | { |
490 | 0 | INET_ERROR err = INET_NO_ERROR; |
491 | 0 | uint8_t *p = NULL; |
492 | 0 | struct ip6_hdr *ip6hdr = NULL; |
493 | |
|
494 | 0 | p = msg->Start(); |
495 | |
|
496 | 0 | ip6hdr = (struct ip6_hdr *)p; |
497 | |
|
498 | 0 | VerifyOrExit(ip6hdr != NULL, err = INET_ERROR_BAD_ARGS); |
499 | | |
500 | | //Do some IPv6 sanity checks |
501 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
502 | | if (IP6H_V(ip6hdr) != 6) |
503 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
504 | | |
505 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
506 | 0 | if ((ip6hdr->ip6_vfc >> 4) != 6) |
507 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
508 | 0 | { |
509 | 0 | ExitNow(err = INET_ERROR_NOT_SUPPORTED); |
510 | 0 | } |
511 | | |
512 | 0 | exit: |
513 | |
|
514 | 0 | return err; |
515 | 0 | } |
516 | | |
517 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
518 | | /* Handler to send received packet to upper layer callback */ |
519 | | void TunEndPoint::HandleDataReceived (PacketBuffer *msg) |
520 | | { |
521 | | INET_ERROR err = INET_NO_ERROR; |
522 | | if (mState == kState_Open && OnPacketReceived != NULL) |
523 | | { |
524 | | err = CheckV6Sanity(msg); |
525 | | if (err == INET_NO_ERROR) |
526 | | { |
527 | | OnPacketReceived(this, msg); |
528 | | } |
529 | | else |
530 | | { |
531 | | if (OnReceiveError != NULL) |
532 | | { |
533 | | OnReceiveError(this, err); |
534 | | } |
535 | | |
536 | | PacketBuffer::Free(msg); |
537 | | } |
538 | | } |
539 | | else |
540 | | { |
541 | | PacketBuffer::Free(msg); |
542 | | } |
543 | | } |
544 | | |
545 | | /* Post an event to the Inet layer event queue from LwIP */ |
546 | | err_t TunEndPoint::LwIPPostToInetEventQ (struct netif *netif, struct pbuf *p) |
547 | | { |
548 | | err_t lwipErr = ERR_OK; |
549 | | INET_ERROR err = INET_NO_ERROR; |
550 | | TunEndPoint* ep = static_cast<TunEndPoint *>(netif->state); |
551 | | Weave::System::Layer& lSystemLayer = ep->SystemLayer(); |
552 | | |
553 | | // Allocate space for the tunneled IP packet. The reserved space will be the |
554 | | // default for the Weave and underlying TCP/IP headers (WEAVE_SYSTEM_CONFIG_HEADER_RESERVE_SIZE). |
555 | | // The requested data size will include the full pbuf received from LwIP plus |
556 | | // WEAVE_TRAILER_RESERVE_SIZE for holding the HMAC. |
557 | | PacketBuffer* buf = PacketBuffer::NewWithAvailableSize(p->tot_len + WEAVE_TRAILER_RESERVE_SIZE); |
558 | | VerifyOrExit(buf != NULL, lwipErr = ERR_MEM); |
559 | | |
560 | | buf->SetDataLength(p->tot_len); |
561 | | |
562 | | // Make a pbuf alloc and copy to post to Inetlayer queue because LwIP would free the |
563 | | // passed pbuf as it made a down-call to send it out the tunnel netif. |
564 | | |
565 | | lwipErr = pbuf_copy((struct pbuf *)buf, p); |
566 | | VerifyOrExit(lwipErr == ERR_OK, (void)lwipErr); |
567 | | |
568 | | err = lSystemLayer.PostEvent(*ep, kInetEvent_TunDataReceived, (uintptr_t)buf); |
569 | | VerifyOrExit(err == INET_NO_ERROR, lwipErr = ERR_MEM); |
570 | | |
571 | | buf = NULL; |
572 | | |
573 | | exit: |
574 | | if (buf != NULL) |
575 | | { |
576 | | PacketBuffer::Free(buf); |
577 | | } |
578 | | |
579 | | return lwipErr; |
580 | | } |
581 | | |
582 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
583 | | #if LWIP_IPV4 |
584 | | /* Output handler for netif */ |
585 | | err_t TunEndPoint::LwIPOutputIPv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) |
586 | | { |
587 | | LWIP_UNUSED_ARG(addr); |
588 | | |
589 | | return LwIPPostToInetEventQ(netif, p); |
590 | | } |
591 | | #endif // LWIP_IPV4 |
592 | | |
593 | | #if LWIP_IPV6 |
594 | | /* Output handler for netif */ |
595 | | err_t TunEndPoint::LwIPOutputIPv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) |
596 | | { |
597 | | LWIP_UNUSED_ARG(addr); |
598 | | |
599 | | return LwIPPostToInetEventQ(netif, p); |
600 | | } |
601 | | #endif // LWIP_IPV4 |
602 | | #else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
603 | | /* Receive message in LwIP */ |
604 | | err_t TunEndPoint::LwIPReceiveTunMessage (struct netif *netif, struct pbuf *p, ip4_addr_t *addr) |
605 | | { |
606 | | LWIP_UNUSED_ARG(addr); |
607 | | |
608 | | return LwIPPostToInetEventQ(netif, p); |
609 | | } |
610 | | |
611 | | #if LWIP_IPV6 |
612 | | err_t TunEndPoint::LwIPReceiveTunV6Message (struct netif *netif, struct pbuf *p, ip6_addr_t *addr) |
613 | | { |
614 | | LWIP_UNUSED_ARG(addr); |
615 | | |
616 | | return LwIPPostToInetEventQ(netif, p); |
617 | | } |
618 | | #endif // LWIP_IPV6 |
619 | | #endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
620 | | |
621 | | /* Initialize the LwIP tunnel netif interface */ |
622 | | err_t TunEndPoint::TunInterfaceNetifInit (struct netif *netif) |
623 | | { |
624 | | netif->name[0] = 't'; |
625 | | netif->name[1] = 'n'; |
626 | | #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 |
627 | | #if LWIP_IPV4 |
628 | | netif->output = LwIPOutputIPv4; |
629 | | #endif /* LWIP_IPV6 */ |
630 | | #if LWIP_IPV6 |
631 | | netif->output_ip6 = LwIPOutputIPv6; |
632 | | #endif /* LWIP_IPV6 */ |
633 | | #else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
634 | | netif->output = LwIPReceiveTunMessage; |
635 | | #if LWIP_IPV6 |
636 | | netif->output_ip6 = LwIPReceiveTunV6Message; |
637 | | #endif /* LWIP_IPV6 */ |
638 | | #endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 |
639 | | netif->linkoutput = NULL; |
640 | | |
641 | | netif->mtu = WEAVE_CONFIG_TUNNEL_INTERFACE_MTU; |
642 | | |
643 | | netif->hwaddr_len = 6; |
644 | | memset(netif->hwaddr, 0, NETIF_MAX_HWADDR_LEN); |
645 | | netif->hwaddr[5] = 1; |
646 | | |
647 | | #if LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR < 5 |
648 | | /* device capabilities */ |
649 | | netif->flags |= NETIF_FLAG_POINTTOPOINT; |
650 | | #endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 |
651 | | |
652 | | return ERR_OK; |
653 | | } |
654 | | |
655 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
656 | | |
657 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
658 | | /* Open a tun device in linux */ |
659 | | INET_ERROR TunEndPoint::TunDevOpen (const char *intfName) |
660 | 0 | { |
661 | 0 | struct ::ifreq ifr; |
662 | 0 | int fd = INET_INVALID_SOCKET_FD; |
663 | 0 | INET_ERROR ret = INET_NO_ERROR; |
664 | |
|
665 | 0 | if ((fd = open(INET_CONFIG_TUNNEL_DEVICE_NAME, O_RDWR | NL_O_CLOEXEC)) < 0) |
666 | 0 | { |
667 | 0 | ExitNow(ret = Weave::System::MapErrorPOSIX(errno)); |
668 | 0 | } |
669 | | |
670 | | //Keep copy of open device fd |
671 | 0 | mSocket = fd; |
672 | |
|
673 | 0 | memset(&ifr, 0, sizeof(ifr)); |
674 | |
|
675 | 0 | ifr.ifr_flags = IFF_TUN | IFF_NO_PI; |
676 | |
|
677 | 0 | if (*intfName) |
678 | 0 | { |
679 | 0 | strncpy(ifr.ifr_name, intfName, sizeof(ifr.ifr_name) - 1); |
680 | 0 | } |
681 | |
|
682 | 0 | if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) |
683 | 0 | { |
684 | 0 | ExitNow(ret = Weave::System::MapErrorPOSIX(errno)); |
685 | 0 | } |
686 | | |
687 | | //Verify name |
688 | 0 | memset(&ifr, 0, sizeof(ifr)); |
689 | 0 | if (TunGetInterface(fd, &ifr) < 0) |
690 | 0 | { |
691 | 0 | ExitNow(ret = Weave::System::MapErrorPOSIX(errno)); |
692 | 0 | } |
693 | | |
694 | 0 | if (ifr.ifr_name[0] != '\0') |
695 | 0 | { |
696 | | //Keep member copy of interface name and Id |
697 | 0 | strncpy(tunIntfName, ifr.ifr_name, sizeof(tunIntfName) - 1); |
698 | 0 | tunIntfName[sizeof(tunIntfName) - 1] = '\0'; |
699 | 0 | } |
700 | 0 | else |
701 | 0 | { |
702 | 0 | ExitNow(ret = Weave::System::MapErrorPOSIX(errno)); |
703 | 0 | } |
704 | | |
705 | 0 | exit: |
706 | |
|
707 | 0 | if (ret != INET_NO_ERROR) |
708 | 0 | { |
709 | 0 | TunDevClose(); |
710 | 0 | } |
711 | |
|
712 | 0 | return ret; |
713 | 0 | } |
714 | | |
715 | | /* Close a tun device */ |
716 | | void TunEndPoint::TunDevClose (void) |
717 | 0 | { |
718 | 0 | if (mSocket >= 0) |
719 | 0 | { |
720 | 0 | close(mSocket); |
721 | 0 | } |
722 | 0 | mSocket = INET_INVALID_SOCKET_FD; |
723 | 0 | } |
724 | | |
725 | | /* Get the tun device interface in Linux */ |
726 | | int TunEndPoint::TunGetInterface (int fd, |
727 | | struct ::ifreq *ifr) |
728 | 0 | { |
729 | 0 | return ioctl(fd, TUNGETIFF, (void*)ifr); |
730 | 0 | } |
731 | | |
732 | | /* Read packets from TUN device in Linux */ |
733 | | INET_ERROR TunEndPoint::TunDevRead (PacketBuffer *msg) |
734 | 0 | { |
735 | 0 | ssize_t rcvLen; |
736 | 0 | INET_ERROR err = INET_NO_ERROR; |
737 | 0 | uint8_t *p = NULL; |
738 | 0 | p = msg->Start(); |
739 | |
|
740 | 0 | rcvLen = read(mSocket, p, msg->AvailableDataLength()); |
741 | 0 | if (rcvLen < 0) |
742 | 0 | { |
743 | 0 | err = Weave::System::MapErrorPOSIX(errno); |
744 | 0 | } |
745 | 0 | else if (rcvLen > msg->AvailableDataLength()) |
746 | 0 | { |
747 | 0 | err = INET_ERROR_INBOUND_MESSAGE_TOO_BIG; |
748 | 0 | } |
749 | 0 | else |
750 | 0 | { |
751 | 0 | msg->SetDataLength((uint16_t)rcvLen); |
752 | 0 | } |
753 | |
|
754 | 0 | return err; |
755 | 0 | } |
756 | | |
757 | | /* Prepare socket for reading */ |
758 | | SocketEvents TunEndPoint::PrepareIO () |
759 | 0 | { |
760 | 0 | SocketEvents res; |
761 | |
|
762 | 0 | if (mState == kState_Open && OnPacketReceived != NULL) |
763 | 0 | { |
764 | 0 | res.SetRead(); |
765 | 0 | } |
766 | |
|
767 | 0 | return res; |
768 | 0 | } |
769 | | |
770 | | /* Read from the Tun device in Linux and pass up to upper layer callback */ |
771 | | void TunEndPoint::HandlePendingIO () |
772 | 0 | { |
773 | 0 | INET_ERROR err = INET_NO_ERROR; |
774 | |
|
775 | 0 | if (mState == kState_Open && OnPacketReceived != NULL && mPendingIO.IsReadable()) |
776 | 0 | { |
777 | |
|
778 | 0 | PacketBuffer *buf = PacketBuffer::New(0); |
779 | |
|
780 | 0 | if (buf != NULL) |
781 | 0 | { |
782 | | //Read data from Tun Device |
783 | 0 | err = TunDevRead(buf); |
784 | 0 | if (err == INET_NO_ERROR) |
785 | 0 | { |
786 | 0 | err = CheckV6Sanity(buf); |
787 | 0 | } |
788 | 0 | } |
789 | 0 | else |
790 | 0 | { |
791 | 0 | err = INET_ERROR_NO_MEMORY; |
792 | 0 | } |
793 | |
|
794 | 0 | if (err == INET_NO_ERROR) |
795 | 0 | { |
796 | 0 | OnPacketReceived(this, buf); |
797 | 0 | } |
798 | 0 | else |
799 | 0 | { |
800 | 0 | PacketBuffer::Free(buf); |
801 | 0 | if (OnReceiveError != NULL) |
802 | 0 | { |
803 | 0 | OnReceiveError(this, err); |
804 | 0 | } |
805 | 0 | } |
806 | 0 | } |
807 | |
|
808 | 0 | mPendingIO.Clear(); |
809 | 0 | } |
810 | | |
811 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
812 | | |
813 | | } // namespace Inet |
814 | | } // namespace nl |