This file is indexed.

/usr/include/ns3.26/ns3/tap-bridge.h is in libns3-dev 3.26+dfsg-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2009 University of Washington
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef TAP_BRIDGE_H
#define TAP_BRIDGE_H

#include <cstring>
#include "ns3/address.h"
#include "ns3/net-device.h"
#include "ns3/node.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/traced-callback.h"
#include "ns3/event-id.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ptr.h"
#include "ns3/mac48-address.h"
#include "ns3/unix-fd-reader.h"

namespace ns3 {

/**
 * \ingroup tap-bridge
 * Class to perform the actual reading from a socket
 */
class TapBridgeFdReader : public FdReader
{
private:
  FdReader::Data DoRead (void);
};

class Node;

/**
 * \ingroup tap-bridge
 * 
 * \brief A bridge to make it appear that a real host process is connected to 
 * an ns-3 net device.
 *
 * The Tap Bridge lives in a kind of a gray world somewhere between a
 * Linux host and an ns-3 bridge device.  From the Linux perspective,
 * this code appears as the user mode handler for a Tap net device.  That
 * is, when the Linux host writes to a /dev/tap device (that is either
 * manually or automatically created depending on basic operating mode 
 * -- more on this later), the write is redirected into the TapBridge that
 * lives in the ns-3 world; and from this perspective, becomes a read.
 * In other words, a Linux process writes a packet to a tap device and
 * this packet is redirected to an ns-3 process where it is received by
 * the TapBridge as a result of a read operation there.  The TapBridge
 * then sends the packet to the ns-3 net device to which it is bridged.
 * In the other direction, a packet received by an ns-3 net device is
 * bridged to the TapBridge (it appears via a callback from that net
 * device.  The TapBridge then takes that packet and writes it back to
 * the host using the Linux TAP mechanism.  This write to the device will
 * then appear to the Linux host as if a packet has arrived on its
 * device.
 * 
 * The upshot is that the Tap Bridge appears to bridge a tap device on a
 * Linux host in the "real world" to an ns-3 net device in the simulation
 * and make is appear that a ns-3 net device is actually installed in the
 * Linux host.  In order to do this on the ns-3 side, we need a "ghost
 * node" in the simulation to hold the bridged ns-3 net device and the
 * TapBridge.  This node should not actually do anything else in the
 * simulation since its job is simply to make the net device appear in
 * Linux.  This is not just arbitrary policy, it is because:
 *
 * - Bits sent to the Tap Bridge from higher layers in the ghost node (using
 *   the TapBridge Send() method) are completely ignored.  The Tap Bridge is 
 *   not, itself, connected to any network, neither in Linux nor in ns-3;
 * - The bridged ns-3 net device is has had its receive callback disconnected
 *   from the ns-3 node and reconnected to the Tap Bridge.  All data received 
 *   by a bridged device will be sent to the Linux host and will not be 
 *   received by the node.  From the perspective of the ghost node, you can 
 *   send over this device but you cannot ever receive.
 *
 * Of course, if you understand all of the issues you can take control of
 * your own destiny and do whatever you want -- we do not actively
 * prevent you from using the ghost node for anything you decide.  You
 * will be able to perform typical ns-3 operations on the ghost node if
 * you so desire.  The internet stack, for example, must be there and
 * functional on that node in order to participate in IP address
 * assignment and global routing.  However, as mentioned above,
 * interfaces talking any Tap Bridge or associated bridged net devices
 * will not work completely.  If you understand exactly what you are
 * doing, you can set up other interfaces and devices on the ghost node
 * and use them; or take advantage of the operational send side of the
 * bridged devices to create traffic generators.  We generally recommend
 * that you treat this node as a ghost of the Linux host and leave it to
 * itself, though.
 */
class TapBridge : public NetDevice
{
public:
  /**
   * \brief Get the type ID.
   * \return the object TypeId
   */
  static TypeId GetTypeId (void);

  /**
   * Enumeration of the operating modes supported in the class.
   *
   */
  enum Mode {
    ILLEGAL,         /**< mode not set */
    CONFIGURE_LOCAL, /**< ns-3 creates and configures tap device */
    USE_LOCAL,       /**< ns-3 uses a pre-created tap, without configuring it */
    USE_BRIDGE, /**< ns-3 uses a pre-created tap, and bridges to a bridging net device */
  };

  TapBridge ();
  virtual ~TapBridge ();

  /**
   * \brief Get the bridged net device.
   *
   * The bridged net device is the ns-3 device to which this bridge is connected,
   *
   * \returns the bridged net device.
   */
  Ptr<NetDevice> GetBridgedNetDevice (void);

  /**
   * \brief Set the ns-3 net device to bridge.
   *
   * This method tells the bridge which ns-3 net device it should use to connect
   * the simulation side of the bridge.
   *
   * \param bridgedDevice device to set
   *
   * \attention The ns-3 net device that is being set as the device must have an
   * an IP address assigned to it before the simulation is run.  This address 
   * will be used to set the hardware address of the host Linux device.
   */
  void SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice);

  /**
   * \brief Set a start time for the device.
   *
   * The tap bridge consumes a non-trivial amount of time to start.  It starts
   * up in the context of a scheduled event to ensure that all configuration
   * has been completed before extracting the configuration (IP addresses, etc.)
   * In order to allow a more reasonable start-up sequence than a thundering 
   * herd of devices, the time at which each device starts is also configurable
   * bot via the Attribute system and via this call.
   *
   * \param tStart the start time
   */
  void Start (Time tStart);

  /**
   * Set a stop time for the device.
   *
   * @param tStop the stop time
   *
   * \see TapBridge::Start
   */
  void Stop (Time tStop);

  /**
   * Set the operating mode of this device.
   *
   * \param mode The operating mode of this device.
   */
  void SetMode (TapBridge::Mode mode);

  /**
   * Get the operating mode of this device.
   *
   * \returns The operating mode of this device.
   */
  TapBridge::Mode  GetMode (void);

  //
  // The following methods are inherited from NetDevice base class and are
  // documented there.
  //
  virtual void SetIfIndex (const uint32_t index);
  virtual uint32_t GetIfIndex (void) const;
  virtual Ptr<Channel> GetChannel (void) const;
  virtual void SetAddress (Address address);
  virtual Address GetAddress (void) const;
  virtual bool SetMtu (const uint16_t mtu);
  virtual uint16_t GetMtu (void) const;
  virtual bool IsLinkUp (void) const;
  virtual void AddLinkChangeCallback (Callback<void> callback);
  virtual bool IsBroadcast (void) const;
  virtual Address GetBroadcast (void) const;
  virtual bool IsMulticast (void) const;
  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
  virtual bool IsPointToPoint (void) const;
  virtual bool IsBridge (void) const;
  virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
  virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
  virtual Ptr<Node> GetNode (void) const;
  virtual void SetNode (Ptr<Node> node);
  virtual bool NeedsArp (void) const;
  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
  virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
  virtual bool SupportsSendFrom () const;
  virtual Address GetMulticast (Ipv6Address addr) const;

protected:
  /**
   * Call out to a separate process running as suid root in order to get our
   * tap device created.  We do this to avoid having the entire simulation 
   * running as root.  If this method returns, we'll have a socket waiting 
   * for us in m_sock that we can use to talk to the tap device.
   */
  virtual void DoDispose (void);

  /**
   * Receives a packet from a bridged Device
   * \param device the originating port
   * \param packet the received packet
   * \param protocol the packet protocol (e.g., Ethertype)
   * \param src the packet source
   * \param dst the packet destination
   * \param packetType the packet type (e.g., host, broadcast, etc.)
   * \returns true on success
   */
  bool ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                 Address const &src, Address const &dst, PacketType packetType);

  /**
   * Receives a packet from a bridged Device
   * \param device the originating port
   * \param packet the received packet
   * \param protocol the packet protocol (e.g., Ethertype)
   * \param src the packet source
   * \returns true on success
   */
  bool DiscardFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                 Address const &src);

private:

  /**
   * Call out to a separate process running as suid root in order to get our
   * tap device created.  We do this to avoid having the entire simulation 
   * running as root.  If this method returns, we'll have a socket waiting 
   * for us in m_sock that we can use to talk to the tap device.
   */
  void CreateTap (void);

  /**
   * Spin up the device
   */
  void StartTapDevice (void);

  /**
   * Tear down the device
   */
  void StopTapDevice (void);

  /**
   * Callback to process packets that are read
   */
  void ReadCallback (uint8_t *buf, ssize_t len);

  /**
   * Forward a packet received from the tap device to the bridged ns-3 
   * device
   *
   * \param buf A character buffer containing the actual packet bits that were
   *            received from the host.
   * \param len The length of the buffer.
   */
  void ForwardToBridgedDevice (uint8_t *buf, ssize_t len);

  /**
   * The host we are bridged to is in the evil real world.  Do some sanity
   * checking on a received packet to make sure it isn't too evil for our
   * poor naive virginal simulator to handle.
   *
   * \param packet The packet we received from the host, and which we need 
   *               to check.
   * \param src    A pointer to the data structure that will get the source
   *               MAC address of the packet (extracted from the packet Ethernet
   *               header).
   * \param dst    A pointer to the data structure that will get the destination
   *               MAC address of the packet (extracted from the packet Ethernet 
   *               header).
   * \param type   A pointer to the variable that will get the packet type from 
   *               either the Ethernet header in the case of type interpretation
   *               (DIX framing) or from the 802.2 LLC header in the case of 
   *               length interpretation (802.3 framing).
   * \returns the packet, or null if the packet has been filtered.
   */
  Ptr<Packet> Filter (Ptr<Packet> packet, Address *src, Address *dst, uint16_t *type);

  /**
   * Notifies that the link is up and ready.
   */
  void NotifyLinkUp (void);

  /**
   * Callback used to hook the standard packet receive callback of the TapBridge
   * ns-3 net device.  This is never called, and therefore no packets will ever
   * be received forwarded up the IP stack on the ghost node through this device.
   */
  NetDevice::ReceiveCallback m_rxCallback;

  /**
   * Callback used to hook the promiscuous packet receive callback of the TapBridge
   * ns-3 net device.  This is never called, and therefore no packets will ever
   * be received forwarded up the IP stack on the ghost node through this device.
   *
   * Note that we intercept the similar callback in the bridged device in order to
   * do the actual bridging between the bridged ns-3 net device and the Tap device
   * on the host.
   */
  NetDevice::PromiscReceiveCallback m_promiscRxCallback;

  /**
   * Pointer to the (ghost) Node to which we are connected.
   */
  Ptr<Node> m_node;


  /**
   * The ns-3 interface index of this TapBridge net device.
   */
  uint32_t m_ifIndex;

  /**
   * The common mtu to use for the net devices
   */
  uint16_t m_mtu;

  /**
   * The socket (actually interpreted as fd) to use to talk to the Tap device on
   * the real internet host.
   */
  int m_sock;

  /**
   * The ID of the ns-3 event used to schedule the start up of the underlying
   * host Tap device and ns-3 read thread.
   */
  EventId m_startEvent;

  /**
   * The ID of the ns-3 event used to schedule the tear down of the underlying
   * host Tap device and ns-3 read thread.
   */
  EventId m_stopEvent;

  /**
   * Includes the ns-3 read thread used to do blocking reads on the fd
   * corresponding to the host device.
   */
  Ptr<TapBridgeFdReader> m_fdReader;

  /**
   * The operating mode of the bridge.  Tells basically who creates and
   * configures the underlying network tap.
   */
  Mode m_mode;

  /**
   * The (unused) MAC address of the TapBridge net device.  Since the TapBridge
   * is implemented as a ns-3 net device, it is required to implement certain
   * functionality.  In this case, the TapBridge is automatically assigned a
   * MAC address, but it is not used.
   */
  Mac48Address m_address;

  /**
   * Time to start spinning up the device
   */
  Time m_tStart;

  /**
   * Time to start tearing down the device
   */
  Time m_tStop;

  /**
   * The name of the device to create on the host.  If the device name is the
   * empty string, we allow the host kernel to choose a name.
   */
  std::string m_tapDeviceName;

  /**
   * The IP address to use as the device default gateway on the host.
   */
  Ipv4Address m_tapGateway;

  /**
   * The IP address to use as the device IP on the host.
   */
  Ipv4Address m_tapIp;
  /**
   * The MAC address to use as the hardware address on the host; only used
   * in UseLocal mode.  This value comes from the MAC
   * address assigned to the bridged ns-3 net device and matches the MAC 
   * address of the underlying network TAP which we configured to have the 
   * same value.
   */
  Mac48Address m_tapMac;

  /**
   * The network mask to assign to the device created on the host.
   */
  Ipv4Mask m_tapNetmask;

  /**
   * The ns-3 net device to which we are bridging.
   */
  Ptr<NetDevice> m_bridgedDevice;
  /**
   * Whether the MAC address of the underlying ns-3 device has already been
   * rewritten is stored in this variable (for UseLocal/UseBridge mode only).
   */
  bool m_ns3AddressRewritten;

  /**
   * A 64K buffer to hold packet data while it is being sent.
   */
  uint8_t *m_packetBuffer;

  /**
   * a copy of the node id so the read thread doesn't have to GetNode() in
   * in order to find the node ID.  Thread unsafe reference counting in 
   * multithreaded apps is not a good thing.
   */
  uint32_t m_nodeId;

  /**
   * Flag indicating whether or not the link is up.  In this case,
   * whether or not ns-3 is connected to the underlying TAP device
   * with a file descriptor.
   */
  bool m_linkUp;

  /**
   * Callbacks to fire if the link changes state (up or down).
   */
  TracedCallback<> m_linkChangeCallbacks;
};

} // namespace ns3

#endif /* TAP_BRIDGE_H */