Coverage Report

Created: 2025-12-11 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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