netlink/netlink-socket.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 05 May 2011 09:28:21 +0200
changeset 66 2fe1f3e576c9
parent 63 model/netlink-socket.cc@e89dca438df6
permissions -rw-r--r--
make it somewhat build sanely
mathieu@0
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@0
     2
/*
mathieu@0
     3
 * Copyright (c) 2008 Liu Jian
mathieu@0
     4
 *
mathieu@0
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@0
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@0
     7
 * published by the Free Software Foundation;
mathieu@0
     8
 *
mathieu@0
     9
 * This program is distributed in the hope that it will be useful,
mathieu@0
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@0
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@0
    12
 * GNU General Public License for more details.
mathieu@0
    13
 *
mathieu@0
    14
 * You should have received a copy of the GNU General Public License
mathieu@0
    15
 * along with this program; if not, write to the Free Software
mathieu@0
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@0
    17
 *
mathieu@0
    18
 * Author: Liu Jian <liujatp@gmail.com>
mathieu@0
    19
 *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
mathieu@0
    20
 */
mathieu@0
    21
mathieu@0
    22
#include "netlink-socket.h"
mathieu@0
    23
#include "netlink-socket-address.h"
mathieu@0
    24
#include "netlink-message.h"
mathieu@0
    25
#include "netlink-message-route.h"
mathieu@0
    26
#include "ns3/log.h"
mathieu@0
    27
#include "ns3/node.h"
mathieu@0
    28
#include "ns3/packet.h"
mathieu@0
    29
#include "ns3/ipv4-address.h"
mathieu@0
    30
#include "ns3/ipv4.h"
mathieu@0
    31
#include "ns3/simple-net-device.h"
mathieu@0
    32
#include "ns3/uinteger.h"
mathieu@0
    33
#include "ns3/trace-source-accessor.h"
mathieu@0
    34
#include <iostream>
mathieu@0
    35
#include <sstream>
mathieu@0
    36
#include "ns3/ipv6-address.h"
mathieu@0
    37
#include "ns3/ipv6.h"
mathieu@0
    38
#include "ns3/ipv4-l3-protocol.h"
mathieu@0
    39
#include "ns3/ipv4-static-routing-helper.h"
mathieu@0
    40
#include "ns3/ipv4-routing-table-entry.h"
mathieu@0
    41
#include "ns3/ipv6-l3-protocol.h"
mathieu@0
    42
#include "ns3/ipv6-interface.h"
mathieu@0
    43
#include "ns3/ipv6-static-routing-helper.h"
mathieu@0
    44
#include "ns3/ipv6-routing-table-entry.h"
mathieu@0
    45
#include "ns3/socket.h"
mathieu@0
    46
#include "ns3/mac48-address.h"
mathieu@0
    47
#include <sys/socket.h>
mathieu@0
    48
#include <linux/if.h>
mathieu@0
    49
#include <errno.h>
mathieu@0
    50
mathieu@0
    51
NS_LOG_COMPONENT_DEFINE ("NetlinkSocket");
mathieu@0
    52
mathieu@0
    53
namespace ns3 {
mathieu@0
    54
mathieu@0
    55
// GroupSockets store the netlinksocket with noero group value
mathieu@0
    56
// it was due to the mulitcast netlink messages.
mathieu@0
    57
class GroupSockets
mathieu@0
    58
{
mathieu@0
    59
public:
mathieu@0
    60
  static uint32_t GetNSockets(void)
mathieu@0
    61
  { 
mathieu@0
    62
    return m_Sockets.size();
mathieu@0
    63
  }
mathieu@0
    64
  static Ptr<NetlinkSocket> GetSocket(uint32_t index)
mathieu@0
    65
  {
mathieu@0
    66
    NS_ASSERT(index < m_Sockets.size());
mathieu@0
    67
    return m_Sockets[index];
mathieu@0
    68
  }
mathieu@0
    69
  static void AddSocket(Ptr<NetlinkSocket>sock)
mathieu@0
    70
  {
mathieu@0
    71
    m_Sockets.push_back(sock);
mathieu@0
    72
  }
mathieu@0
    73
private:
mathieu@0
    74
   /*use a std::vector to store the sockets with nozero group value*/
mathieu@0
    75
  static std::vector<Ptr<NetlinkSocket> >m_Sockets;
mathieu@0
    76
};
mathieu@0
    77
std::vector<Ptr<NetlinkSocket> >GroupSockets::m_Sockets;
mathieu@0
    78
mathieu@0
    79
NS_OBJECT_ENSURE_REGISTERED (NetlinkSocket);
mathieu@0
    80
mathieu@0
    81
/*
mathieu@0
    82
Netlink Socket
mathieu@0
    83
*/
mathieu@0
    84
TypeId
mathieu@0
    85
NetlinkSocket::GetTypeId (void)
mathieu@0
    86
{
mathieu@0
    87
  static TypeId tid = TypeId ("ns3::NetlinkSocket")
mathieu@0
    88
    .SetParent<Socket> ()
mathieu@0
    89
    .AddConstructor<NetlinkSocket> ()
mathieu@0
    90
    .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
mathieu@0
    91
                     MakeTraceSourceAccessor (&NetlinkSocket::m_dropTrace))
mathieu@0
    92
    .AddAttribute ("RcvBufSize",
mathieu@0
    93
                   "NetlinkSocket maximum receive buffer size (bytes)",
mathieu@0
    94
                   UintegerValue (0xffffffffl),
mathieu@0
    95
                   MakeUintegerAccessor (&NetlinkSocket::m_rcvBufSize),
mathieu@0
    96
                   MakeUintegerChecker<uint32_t> ())
mathieu@0
    97
    .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
mathieu@0
    98
                   CallbackValue (),
mathieu@0
    99
                   MakeCallbackAccessor (&NetlinkSocket::m_icmpCallback),
mathieu@0
   100
                   MakeCallbackChecker ())
mathieu@0
   101
    ;
mathieu@0
   102
  return tid;
mathieu@0
   103
}
mathieu@0
   104
mathieu@0
   105
NetlinkSocket::NetlinkSocket ()
mathieu@0
   106
  : m_shutdownSend (false),
mathieu@0
   107
    m_shutdownRecv (false),
mathieu@0
   108
    m_rxAvailable (0),
mathieu@0
   109
    m_srcPid (0),
mathieu@0
   110
    m_srcGroups (0),
mathieu@0
   111
    m_dstPid (0),
mathieu@0
   112
    m_dstGroups (0)
mathieu@0
   113
{
mathieu@0
   114
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   115
  m_errno = ERROR_NOTERROR;
mathieu@0
   116
}
mathieu@0
   117
NetlinkSocket::~NetlinkSocket ()
mathieu@0
   118
{
mathieu@0
   119
  NS_LOG_FUNCTION (this);
mathieu@0
   120
}
mathieu@0
   121
void 
mathieu@0
   122
NetlinkSocket::DoDispose (void)
mathieu@0
   123
{
mathieu@0
   124
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   125
}
mathieu@0
   126
mathieu@0
   127
int
mathieu@0
   128
NetlinkSocket::ErrnoToSimuErrno (void)
mathieu@0
   129
{
mathieu@0
   130
  switch (m_errno)
mathieu@0
   131
    {
mathieu@0
   132
    case Socket::ERROR_ISCONN:
mathieu@0
   133
      return EISCONN;
mathieu@0
   134
    case Socket::ERROR_NOTCONN:
mathieu@0
   135
      return ENOTCONN;
mathieu@0
   136
    case Socket::ERROR_MSGSIZE:
mathieu@0
   137
      return EMSGSIZE;
mathieu@0
   138
    case Socket::ERROR_AGAIN:
mathieu@0
   139
      return EAGAIN;
mathieu@0
   140
    case Socket::ERROR_SHUTDOWN:
mathieu@0
   141
      return ESHUTDOWN;
mathieu@0
   142
    case Socket::ERROR_OPNOTSUPP:
mathieu@0
   143
      return EOPNOTSUPP;
mathieu@0
   144
    case Socket::ERROR_AFNOSUPPORT:
mathieu@0
   145
      return EAFNOSUPPORT;
mathieu@0
   146
    case Socket::ERROR_INVAL:
mathieu@0
   147
      return EINVAL;
mathieu@0
   148
    case Socket::ERROR_BADF:
mathieu@0
   149
      return EBADF;
mathieu@0
   150
    case Socket::ERROR_NOROUTETOHOST:
mathieu@0
   151
      return EHOSTUNREACH;
mathieu@0
   152
    case Socket::ERROR_NODEV:
mathieu@0
   153
      return ENODEV;
mathieu@0
   154
    case Socket::ERROR_ADDRNOTAVAIL:
mathieu@0
   155
      return EADDRNOTAVAIL;
mathieu@0
   156
    case Socket::SOCKET_ERRNO_LAST:
mathieu@0
   157
    case Socket::ERROR_NOTERROR:
mathieu@0
   158
    default:
mathieu@0
   159
      NS_ASSERT (false);
mathieu@0
   160
      return 0; // quiet compiler
mathieu@0
   161
      break;
mathieu@0
   162
    }
mathieu@0
   163
}
mathieu@0
   164
mathieu@0
   165
void 
mathieu@0
   166
NetlinkSocket::SetNode (Ptr<Node> node)
mathieu@0
   167
{
mathieu@0
   168
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   169
  m_node = node;
mathieu@0
   170
}
mathieu@0
   171
mathieu@0
   172
mathieu@0
   173
enum Socket::SocketErrno
mathieu@0
   174
NetlinkSocket::GetErrno (void) const
mathieu@0
   175
{
mathieu@0
   176
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   177
  return m_errno;
mathieu@0
   178
}
mathieu@63
   179
enum Socket::SocketType 
mathieu@63
   180
NetlinkSocket::GetSocketType (void) const
mathieu@63
   181
{
mathieu@63
   182
  return Socket::NS3_SOCK_DGRAM;
mathieu@63
   183
}
mathieu@0
   184
mathieu@0
   185
Ptr<Node>
mathieu@0
   186
NetlinkSocket::GetNode (void) const
mathieu@0
   187
{
mathieu@0
   188
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   189
  return m_node;
mathieu@0
   190
}
mathieu@0
   191
mathieu@0
   192
uint32_t
mathieu@0
   193
NetlinkSocket::GetSrcPid (void) const
mathieu@0
   194
{
mathieu@0
   195
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   196
  return m_srcPid;
mathieu@0
   197
}
mathieu@0
   198
uint32_t
mathieu@0
   199
NetlinkSocket::GetSrcGroups (void)const
mathieu@0
   200
{
mathieu@0
   201
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   202
  return m_srcGroups;
mathieu@0
   203
}
mathieu@0
   204
uint32_t
mathieu@0
   205
NetlinkSocket::GetDstPid (void) const
mathieu@0
   206
{
mathieu@0
   207
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   208
  return m_dstPid;
mathieu@0
   209
}
mathieu@0
   210
uint32_t
mathieu@0
   211
NetlinkSocket::GetDstGroups (void)const
mathieu@0
   212
{
mathieu@0
   213
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   214
  return m_dstGroups;
mathieu@0
   215
}
mathieu@0
   216
mathieu@0
   217
int
mathieu@0
   218
NetlinkSocket::Bind (void)
mathieu@0
   219
{
mathieu@0
   220
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   221
  NetlinkSocketAddress address;
mathieu@0
   222
  return DoBind (address);
mathieu@0
   223
}
mathieu@0
   224
int
mathieu@0
   225
NetlinkSocket::Bind (const Address &address)
mathieu@0
   226
{ 
mathieu@0
   227
  NS_LOG_FUNCTION (this << address);
mathieu@0
   228
mathieu@0
   229
  if (!NetlinkSocketAddress::IsMatchingType (address))
mathieu@0
   230
    {
mathieu@0
   231
      m_errno = ERROR_INVAL;
mathieu@0
   232
      return -1;
mathieu@0
   233
    }
mathieu@0
   234
  NetlinkSocketAddress ad = NetlinkSocketAddress::ConvertFrom (address);
mathieu@0
   235
  return DoBind (ad);
mathieu@0
   236
}
mathieu@0
   237
int
mathieu@0
   238
NetlinkSocket::DoBind (const NetlinkSocketAddress &address)
mathieu@0
   239
{
mathieu@0
   240
  NS_LOG_FUNCTION (this << address);
mathieu@0
   241
mathieu@0
   242
  m_srcPid = address.GetProcessID ();
mathieu@0
   243
  m_srcGroups = address.GetGroupsMask ();
mathieu@0
   244
mathieu@0
   245
  if (m_srcGroups)
mathieu@0
   246
    {
mathieu@0
   247
      GroupSockets::AddSocket(this);
mathieu@0
   248
    } 
mathieu@0
   249
  return 0;
mathieu@0
   250
}
mathieu@0
   251
mathieu@0
   252
int 
mathieu@0
   253
NetlinkSocket::Listen (void)
mathieu@0
   254
{
mathieu@0
   255
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   256
  m_errno = Socket::ERROR_OPNOTSUPP;
mathieu@0
   257
  return -1;
mathieu@0
   258
}
mathieu@0
   259
mathieu@0
   260
uint32_t
mathieu@0
   261
NetlinkSocket::GetTxAvailable (void) const
mathieu@0
   262
{
mathieu@0
   263
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   264
  return 0;
mathieu@0
   265
}
mathieu@0
   266
uint32_t
mathieu@0
   267
NetlinkSocket::GetRxAvailable (void) const
mathieu@0
   268
{
mathieu@0
   269
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   270
  // We separately maintain this state to avoid walking the queue 
mathieu@0
   271
  // every time this might be called
mathieu@0
   272
  return m_rxAvailable;
mathieu@0
   273
}
mathieu@0
   274
mathieu@0
   275
int
mathieu@0
   276
NetlinkSocket::ShutdownSend (void)
mathieu@0
   277
{
mathieu@0
   278
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   279
  m_shutdownSend = true;
mathieu@0
   280
  return 0;
mathieu@0
   281
}
mathieu@0
   282
int
mathieu@0
   283
NetlinkSocket::ShutdownRecv (void)
mathieu@0
   284
{
mathieu@0
   285
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   286
  m_shutdownRecv = true;
mathieu@0
   287
  return 0;
mathieu@0
   288
}
mathieu@0
   289
mathieu@0
   290
int
mathieu@0
   291
NetlinkSocket::Close (void)
mathieu@0
   292
{
mathieu@0
   293
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   294
  ShutdownSend();
mathieu@0
   295
  ShutdownRecv();
mathieu@0
   296
  return 0;
mathieu@0
   297
}
mathieu@0
   298
mathieu@0
   299
int
mathieu@0
   300
NetlinkSocket::Connect (const Address &address)
mathieu@0
   301
{
mathieu@0
   302
  NS_LOG_FUNCTION (this << address);
mathieu@0
   303
  m_errno = Socket::ERROR_OPNOTSUPP;
mathieu@0
   304
  return 0;
mathieu@0
   305
}
mathieu@0
   306
mathieu@0
   307
Ptr<Packet>
mathieu@0
   308
NetlinkSocket::Recv (uint32_t maxSize, uint32_t flags)
mathieu@0
   309
{
mathieu@0
   310
  NS_LOG_FUNCTION (this << maxSize<< flags);
mathieu@0
   311
  if (m_dataReceiveQueue.empty())
mathieu@0
   312
    {
mathieu@0
   313
      return 0;
mathieu@0
   314
    }
mathieu@0
   315
mathieu@0
   316
  Ptr<Packet> p = m_dataReceiveQueue.front ();
mathieu@0
   317
  if (p->GetSize () <= maxSize) 
mathieu@0
   318
    {
mathieu@0
   319
      m_dataReceiveQueue.pop ();
mathieu@0
   320
      m_rxAvailable -= p->GetSize ();
mathieu@0
   321
    }
mathieu@0
   322
  else
mathieu@0
   323
    {
mathieu@0
   324
      p = 0; 
mathieu@0
   325
    }
mathieu@0
   326
  return p;
mathieu@0
   327
}
mathieu@0
   328
mathieu@0
   329
Ptr<Packet>
mathieu@0
   330
NetlinkSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
mathieu@0
   331
{
mathieu@0
   332
  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
mathieu@0
   333
  Ptr<Packet> packet = Recv (maxSize, flags);
mathieu@0
   334
  if (packet != 0)
mathieu@0
   335
    {
mathieu@0
   336
      SocketAddressTag tag;
mathieu@0
   337
      bool found;
mathieu@0
   338
      found = packet->FindFirstMatchingByteTag (tag);
mathieu@0
   339
      NS_ASSERT (found);
mathieu@0
   340
      fromAddress = tag.GetAddress ();
mathieu@0
   341
    }
mathieu@0
   342
  return packet;
mathieu@0
   343
}
mathieu@0
   344
mathieu@0
   345
int
mathieu@0
   346
NetlinkSocket::Send (Ptr<Packet> p,uint32_t flags)
mathieu@0
   347
{
mathieu@0
   348
  NS_LOG_FUNCTION (this << p << flags);
mathieu@0
   349
  NetlinkSocketAddress address = NetlinkSocketAddress(m_dstPid, m_dstGroups);
mathieu@0
   350
  return SendTo(p, flags, address);
mathieu@0
   351
}
mathieu@0
   352
mathieu@0
   353
int
mathieu@0
   354
NetlinkSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &toAddress)
mathieu@0
   355
{
mathieu@0
   356
  NS_LOG_FUNCTION (this << p << flags << toAddress);
mathieu@0
   357
  NetlinkSocketAddress ad;
mathieu@0
   358
mathieu@0
   359
  if (!NetlinkSocketAddress::IsMatchingType (toAddress))
mathieu@0
   360
    {
mathieu@0
   361
      NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
mathieu@0
   362
      m_errno = ERROR_AFNOSUPPORT;
mathieu@0
   363
      return -1;
mathieu@0
   364
    }
mathieu@0
   365
  ad = NetlinkSocketAddress::ConvertFrom (toAddress);
mathieu@0
   366
  m_dstPid = ad.GetProcessID();
mathieu@0
   367
  m_dstGroups = ad.GetGroupsMask();
mathieu@0
   368
  NS_LOG_INFO ("send netlink message to pid = " << m_dstPid << ", groups = " << m_dstGroups);
mathieu@0
   369
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending netlink message from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ());
mathieu@0
   370
mathieu@0
   371
  //Ptr<NetlinkSocket>kernel_socket = GetNetlinkSocketByAddress(ad);
mathieu@0
   372
  //kernel_socket->m_receivedData.push_back(p);
mathieu@0
   373
  //kernel_socket->NotifyDataReceived(p);
mathieu@0
   374
mathieu@0
   375
  //when netlink socket send packet, the first step is to find the dest netlink socket through address
mathieu@0
   376
  //then send the packet to it. For we partly implement the netlink-family, the dest address
mathieu@0
   377
  //is always the kernel(pid = 0), (Actually, there must be one static kernel netlink socket to
mathieu@0
   378
  //receive/handle messages), we do not setup a kernel socket to receive packet.
mathieu@0
   379
  //
mathieu@0
   380
  
mathieu@0
   381
  MultipartNetlinkMessage multipartnlmsg;
mathieu@0
   382
  uint32_t packet_len, remain_len;
mathieu@0
   383
mathieu@0
   384
  packet_len = p->GetSize ();
mathieu@0
   385
  remain_len = packet_len;
mathieu@0
   386
mathieu@0
   387
  while (remain_len > NetlinkMessageHeader::GetHeaderSize ())
mathieu@0
   388
    {
mathieu@0
   389
      remain_len -= p->RemoveHeader (multipartnlmsg);
mathieu@0
   390
      NS_ASSERT (remain_len == p->GetSize ());
mathieu@0
   391
mathieu@0
   392
      //actually, message to kernel contains single one netlink message
mathieu@0
   393
      for (uint32_t i = 0; i < multipartnlmsg.GetNMessages(); i ++)
mathieu@0
   394
        {
mathieu@0
   395
          NetlinkMessage nlmsg = multipartnlmsg.GetMessage (i);
mathieu@0
   396
          if (HandleMessage (nlmsg) < 0)
mathieu@0
   397
            {
mathieu@0
   398
              if (m_errno)
mathieu@0
   399
                {
mathieu@0
   400
                  SendAckMessage (nlmsg, -ErrnoToSimuErrno ());
mathieu@0
   401
                }
mathieu@0
   402
            }
mathieu@0
   403
          else if (NetlinkMessage::IsMessageFlagsAck (nlmsg.GetHeader ().GetMsgFlags ()))
mathieu@0
   404
            {
mathieu@0
   405
              SendAckMessage (nlmsg, 0);
mathieu@0
   406
            }
mathieu@0
   407
        }
mathieu@0
   408
    }
mathieu@0
   409
mathieu@0
   410
  NotifyDataSent (packet_len);
mathieu@0
   411
  NS_LOG_INFO ("netlink socket kernel error " << -m_errno);
mathieu@0
   412
  return packet_len;
mathieu@0
   413
}
mathieu@0
   414
mathieu@0
   415
int
mathieu@0
   416
NetlinkSocket::GetSockName (Address &address) const
mathieu@0
   417
{
mathieu@0
   418
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   419
  NetlinkSocketAddress ad;
mathieu@0
   420
mathieu@0
   421
  ad.SetProcessID (GetSrcPid ());
mathieu@0
   422
  ad.SetGroupsMask (GetSrcGroups ());
mathieu@0
   423
  address = ad;
mathieu@0
   424
  return 0;
mathieu@0
   425
}
mathieu@0
   426
int
mathieu@0
   427
NetlinkSocket::GetPeerName (Address &address) const
mathieu@0
   428
{
mathieu@0
   429
  NS_LOG_FUNCTION_NOARGS ();
mathieu@0
   430
  // XXX
mathieu@0
   431
  NS_ASSERT (false);
mathieu@0
   432
  return -1;
mathieu@0
   433
}
mathieu@0
   434
bool 
mathieu@0
   435
NetlinkSocket::SetAllowBroadcast (bool allowBroadcast)
mathieu@0
   436
{
mathieu@0
   437
  NS_ASSERT (false);
mathieu@0
   438
  return false;
mathieu@0
   439
}
mathieu@0
   440
bool 
mathieu@0
   441
NetlinkSocket::GetAllowBroadcast () const
mathieu@0
   442
{
mathieu@0
   443
  NS_ASSERT (false);
mathieu@0
   444
  return false;
mathieu@0
   445
}
mathieu@0
   446
mathieu@0
   447
mathieu@0
   448
void
mathieu@0
   449
NetlinkSocket::ForwardUp (Ptr<Packet> packet, NetlinkSocketAddress &address)
mathieu@0
   450
{
mathieu@0
   451
  NS_LOG_FUNCTION (this << packet << address);
mathieu@0
   452
mathieu@0
   453
  if (m_shutdownRecv)
mathieu@0
   454
    {
mathieu@0
   455
      return;
mathieu@0
   456
    }
mathieu@0
   457
  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
mathieu@0
   458
    {
mathieu@0
   459
      SocketAddressTag tag;
mathieu@0
   460
      tag.SetAddress (address);
mathieu@0
   461
      packet->AddByteTag (tag);
mathieu@0
   462
      m_dataReceiveQueue.push (packet);
mathieu@0
   463
      m_rxAvailable += packet->GetSize ();
mathieu@0
   464
      NotifyDataRecv ();
mathieu@0
   465
    }
mathieu@0
   466
  else
mathieu@0
   467
    {
mathieu@0
   468
      NS_LOG_WARN ("No receive buffer space available.  Drop.");
mathieu@0
   469
      m_dropTrace (packet);
mathieu@0
   470
    }
mathieu@0
   471
}
mathieu@0
   472
mathieu@0
   473
int32_t
mathieu@0
   474
NetlinkSocket::SendMessageUnicast (const MultipartNetlinkMessage &nlmsg, uint32_t pid, int32_t nonblock)
mathieu@0
   475
{
mathieu@0
   476
  NS_LOG_FUNCTION (this << pid << nonblock);
mathieu@0
   477
  //here we send message instantly
mathieu@0
   478
  Ptr<Packet> p = Create<Packet> ();
mathieu@0
   479
  p->AddHeader (nlmsg);
mathieu@0
   480
mathieu@0
   481
  NetlinkSocketAddress address;
mathieu@0
   482
  address.SetProcessID (pid);
mathieu@0
   483
mathieu@0
   484
  //send packet to user space
mathieu@0
   485
  ForwardUp (p, address);
mathieu@0
   486
  return 0;
mathieu@0
   487
}
mathieu@0
   488
int32_t
mathieu@0
   489
NetlinkSocket::SendMessageBroadcast (const MultipartNetlinkMessage &nlmsg, 
mathieu@0
   490
                                     uint32_t pid, 
mathieu@0
   491
                                     uint32_t group,
mathieu@0
   492
                                     Ptr<Node> node)
mathieu@0
   493
{
mathieu@0
   494
  NS_LOG_FUNCTION ("SendMessageBroadcast" << pid << group);
mathieu@0
   495
  //fisrt find the dest netlink socket through group value, then attach this nlmsg to its recv-queue
mathieu@0
   496
  for (uint32_t i = 0; i < GroupSockets::GetNSockets (); i ++)
mathieu@0
   497
    {
mathieu@0
   498
      Ptr<NetlinkSocket> nlsock = GroupSockets::GetSocket (i);
mathieu@0
   499
mathieu@0
   500
      if ((nlsock->GetSrcGroups () & group) &&
mathieu@0
   501
          (nlsock->GetSrcPid () != pid) &&
mathieu@0
   502
          node == nlsock->GetNode ())
mathieu@0
   503
        {
mathieu@0
   504
          //here we send message instantly
mathieu@0
   505
          Ptr<Packet> p = Create<Packet> ();
mathieu@0
   506
          p->AddHeader (nlmsg);
mathieu@0
   507
mathieu@0
   508
          NetlinkSocketAddress address;
mathieu@0
   509
          address.SetProcessID (nlsock->GetSrcPid());
mathieu@0
   510
          address.SetGroupsMask (group);
mathieu@0
   511
mathieu@0
   512
          //send packet to user space
mathieu@0
   513
          nlsock->ForwardUp (p, address);
mathieu@0
   514
        }
mathieu@0
   515
    }
mathieu@0
   516
  return 0;
mathieu@0
   517
}
mathieu@0
   518
void
mathieu@0
   519
NetlinkSocket::SendAckMessage (const NetlinkMessage&nlmsg, int32_t err)
mathieu@0
   520
{
mathieu@0
   521
  NS_LOG_FUNCTION (this << err);
mathieu@0
   522
  NetlinkMessageHeader rep;
mathieu@0
   523
  NetlinkMessage ackmsg;
mathieu@0
   524
  NetlinkMessageError errmsg;
mathieu@0
   525
mathieu@0
   526
  rep.SetMsgPid (nlmsg.GetHeader ().GetMsgPid ());
mathieu@0
   527
  rep.SetMsgSeq (nlmsg.GetHeader ().GetMsgSeq ());
mathieu@0
   528
  rep.SetMsgType (NETLINK_MSG_ERROR);
mathieu@0
   529
  rep.SetMsgFlags (0);
mathieu@0
   530
mathieu@0
   531
  errmsg.SetError (err);
mathieu@0
   532
  //kernel send the whole nlmsg back if error != 0, here we just send the header back
mathieu@0
   533
  errmsg.SetMsg (nlmsg.GetHeader ());
mathieu@0
   534
mathieu@0
   535
  //then send errmsg back to user space
mathieu@0
   536
  ackmsg.SetHeader (rep);
mathieu@0
   537
  ackmsg.SetErrorMessage (errmsg);
mathieu@0
   538
mathieu@0
   539
  SendMessageUnicast (ackmsg, rep.GetMsgPid (), 1);
mathieu@0
   540
}
mathieu@0
   541
mathieu@0
   542
int32_t
mathieu@0
   543
NetlinkSocket::HandleMessage (const NetlinkMessage&nlmsg)
mathieu@0
   544
{
mathieu@0
   545
  NS_LOG_FUNCTION (this);
mathieu@0
   546
  uint16_t type = nlmsg.GetMsgType ();
mathieu@0
   547
  NetlinkMessageHeader nhr = nlmsg.GetHeader ();
mathieu@0
   548
mathieu@0
   549
  if (nhr.GetMsgLen () < NetlinkMessageHeader::GetHeaderSize ())
mathieu@0
   550
    {
mathieu@0
   551
      m_errno = ERROR_INVAL;
mathieu@0
   552
      return -1;
mathieu@0
   553
    }
mathieu@0
   554
mathieu@0
   555
  if (NetlinkMessage::IsMessageNetlinkControl (type))
mathieu@0
   556
    {
mathieu@0
   557
      NS_LOG_INFO ("netlink control message type not parsed in kernel");
mathieu@0
   558
      return 0;
mathieu@0
   559
    }
mathieu@0
   560
  else if (NetlinkMessage::IsMessageNetlinkRoute (type))
mathieu@0
   561
    {
mathieu@0
   562
      return HandleNetlinkRouteMessage (nlmsg);
mathieu@0
   563
    }
mathieu@0
   564
  else
mathieu@0
   565
    {
mathieu@0
   566
      NS_LOG_INFO ("netlink message type not parsed in kernel");
mathieu@0
   567
      m_errno = ERROR_INVAL;
mathieu@0
   568
      return -1;
mathieu@0
   569
    }  
mathieu@0
   570
}
mathieu@0
   571
mathieu@0
   572
int32_t
mathieu@0
   573
NetlinkSocket::HandleNetlinkRouteMessage (const NetlinkMessage &nlmsg)
mathieu@0
   574
{
mathieu@0
   575
  NS_LOG_FUNCTION (this);
mathieu@0
   576
  uint8_t family;
mathieu@0
   577
  int16_t type;
mathieu@0
   578
  int32_t err;
mathieu@0
   579
mathieu@0
   580
  /* Only requests are handled by kernel now */
mathieu@0
   581
  if (!NetlinkMessage::IsMessageFlagsRequest (nlmsg.GetHeader ().GetMsgFlags ()))
mathieu@0
   582
    return 0;
mathieu@0
   583
mathieu@0
   584
  type = nlmsg.GetMsgType ();
mathieu@0
   585
mathieu@0
   586
  /* A control message: ignore them */
mathieu@0
   587
  if (NetlinkMessage::IsMessageNetlinkControl (type))
mathieu@0
   588
    {
mathieu@0
   589
      return 0;
mathieu@0
   590
    }
mathieu@0
   591
  else if (NetlinkMessage::IsMessageNetlinkRoute (type))
mathieu@0
   592
    {
mathieu@0
   593
      /* All the messages must have at least 1 byte length */
mathieu@0
   594
      if (nlmsg.GetPayloadSize () < 1)
mathieu@0
   595
        return 0;
mathieu@0
   596
mathieu@0
   597
      family = nlmsg.GetFamily ();
mathieu@0
   598
      /*here we do not deal with different family, default for AF_NET*/
mathieu@0
   599
      NS_ASSERT(family == AF_INET || family == AF_UNSPEC || family == AF_PACKET || family == AF_INET6);  
mathieu@0
   600
mathieu@0
   601
      /*for GET*** message, dump it to userspace*/
mathieu@0
   602
      if (NetlinkMessage::IsMessageTypeGet (type) && 
mathieu@0
   603
          NetlinkMessage::IsMessageFlagsDump (nlmsg.GetHeader ().GetMsgFlags ())) 
mathieu@0
   604
        {
mathieu@0
   605
          DumpNetlinkRouteMessage (nlmsg, type, family);
mathieu@0
   606
          return -1;
mathieu@0
   607
        }
mathieu@0
   608
mathieu@0
   609
      /* other types of messages*/
mathieu@0
   610
      return DoNetlinkRouteMessage (nlmsg, type, family);
mathieu@0
   611
    }
mathieu@0
   612
  else/* Unknown message: reply with EINVAL */
mathieu@0
   613
    {
mathieu@0
   614
      err = ERROR_INVAL;
mathieu@0
   615
      return -1;
mathieu@0
   616
    } 
mathieu@0
   617
}
mathieu@0
   618
mathieu@0
   619
int32_t
mathieu@0
   620
NetlinkSocket::DumpNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
mathieu@0
   621
{
mathieu@0
   622
  NS_LOG_FUNCTION (this << type << family);
mathieu@0
   623
mathieu@0
   624
  NS_ASSERT (type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE || type == NETLINK_RTM_GETLINK);
mathieu@0
   625
mathieu@0
   626
  MultipartNetlinkMessage nlmsg_dump;
mathieu@0
   627
  NetlinkMessageHeader nhr = nlmsg.GetHeader ();
mathieu@0
   628
  int32_t err;
mathieu@0
   629
mathieu@0
   630
  if (type == NETLINK_RTM_GETADDR)
mathieu@0
   631
    {
mathieu@0
   632
      nlmsg_dump = BuildInterfaceAddressDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
mathieu@0
   633
    }
mathieu@0
   634
  else if (type == NETLINK_RTM_GETLINK)
mathieu@0
   635
    {
mathieu@0
   636
      nlmsg_dump = BuildInterfaceInfoDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);      
mathieu@0
   637
    }
mathieu@0
   638
  else if (type == NETLINK_RTM_GETROUTE)
mathieu@0
   639
    {
mathieu@0
   640
      nlmsg_dump = BuildRouteDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
mathieu@0
   641
    }
mathieu@0
   642
  else
mathieu@0
   643
    {
mathieu@0
   644
      m_errno = ERROR_INVAL;
mathieu@0
   645
      return -1;
mathieu@0
   646
    }
mathieu@0
   647
mathieu@0
   648
  //then append netlink message with type NLMSG_DONE
mathieu@0
   649
  NetlinkMessage nlmsg_done;
mathieu@0
   650
  NetlinkMessageHeader nhr2 = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 
mathieu@0
   651
                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
mathieu@0
   652
  nlmsg_done.SetHeader (nhr2);
mathieu@0
   653
  //kernel append nlmsg_dump size to it, here we omit it
mathieu@0
   654
  nlmsg_dump.AppendMessage (nlmsg_done);
mathieu@0
   655
mathieu@0
   656
  err = SendMessageUnicast (nlmsg_dump, m_srcPid, 1);
mathieu@0
   657
  return err;
mathieu@0
   658
}
mathieu@0
   659
mathieu@0
   660
/*here only for ADD/DEL/GET*** types*/
mathieu@0
   661
int32_t
mathieu@0
   662
NetlinkSocket::DoNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
mathieu@0
   663
{
mathieu@0
   664
  NS_LOG_FUNCTION (this << type <<family);
mathieu@0
   665
  int32_t err;
mathieu@0
   666
mathieu@0
   667
  if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
mathieu@0
   668
    {      
mathieu@0
   669
      err = DoInterfaceAddressMessage (nlmsg, type, family);
mathieu@0
   670
    }
mathieu@0
   671
  else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
mathieu@0
   672
    {     
mathieu@0
   673
      err = DoRouteMessage (nlmsg, type, family);
mathieu@0
   674
    }
mathieu@0
   675
  else if (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK)
mathieu@0
   676
    {     
mathieu@0
   677
      err = DoInterfaceInfoMessage (nlmsg, type, family);
mathieu@0
   678
    }
mathieu@0
   679
  else
mathieu@0
   680
    {
mathieu@0
   681
      NS_LOG_LOGIC ("netlink message:type( " << type << ") not processed by ns3 now." );
mathieu@0
   682
      m_errno = ERROR_INVAL;
mathieu@0
   683
      err = -1;
mathieu@0
   684
    } 
mathieu@0
   685
  
mathieu@0
   686
  return err;
mathieu@0
   687
}
mathieu@0
   688
mathieu@0
   689
MultipartNetlinkMessage
mathieu@0
   690
NetlinkSocket::BuildInterfaceAddressDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
mathieu@0
   691
{
mathieu@0
   692
  NS_LOG_FUNCTION (this << pid << seq <<family);
mathieu@0
   693
  MultipartNetlinkMessage nlmsg_dump;
mathieu@0
   694
  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
mathieu@0
   695
mathieu@0
   696
  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
mathieu@0
   697
    {
mathieu@0
   698
      if (!ipv4->IsUp (i))
mathieu@0
   699
        continue;
mathieu@0
   700
mathieu@0
   701
      Ipv4Address addri = ipv4->GetAddress (i, 0).GetLocal ();
mathieu@0
   702
      Ipv4Mask maski = ipv4->GetAddress (i, 0).GetMask ();
mathieu@0
   703
      Ipv4Address bcast = ipv4->GetAddress (i, 0).GetBroadcast ();
mathieu@0
   704
mathieu@0
   705
      //here get the address mask length
mathieu@0
   706
      uint32_t mask = maski.Get ();
mathieu@0
   707
      uint8_t mask_len = 0;
mathieu@0
   708
      while (mask)
mathieu@0
   709
        {
mathieu@0
   710
          mask = mask << 1;
mathieu@0
   711
          mask_len ++;
mathieu@0
   712
        }
mathieu@0
   713
      
mathieu@0
   714
      //next fill the message body
mathieu@0
   715
      NetlinkMessage nlmsg_ifa;
mathieu@0
   716
      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
mathieu@0
   717
      InterfaceAddressMessage ifamsg;
mathieu@0
   718
mathieu@0
   719
      ifamsg.SetInterfaceIndex (i);
mathieu@0
   720
      ifamsg.SetFamily (AF_INET);//default AF_INET      
mathieu@0
   721
      ifamsg.SetLength (mask_len);
mathieu@0
   722
      ifamsg.SetFlags (0);
mathieu@0
   723
      ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
   724
mathieu@0
   725
      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addri));
mathieu@0
   726
      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addri));
mathieu@0
   727
      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
mathieu@0
   728
      //      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL,    STRING,  "ns3-ifaddr"));//not used in ns3
mathieu@0
   729
      //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST,  ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
mathieu@0
   730
      //XXXother attributes not used by ns3
mathieu@0
   731
mathieu@0
   732
      nlmsg_ifa.SetHeader(nhr);
mathieu@0
   733
      nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
mathieu@0
   734
      nlmsg_dump.AppendMessage (nlmsg_ifa);
mathieu@0
   735
    }
mathieu@0
   736
mathieu@0
   737
  // For IPv6
mathieu@0
   738
  Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
mathieu@0
   739
mathieu@0
   740
  for (uint32_t i = 0; i < ipv6->GetNInterfaces(); i ++)
mathieu@0
   741
    {
mathieu@0
   742
      if (!ipv6->IsUp (i))
mathieu@0
   743
        continue;
mathieu@0
   744
mathieu@0
   745
      for (uint32_t j = 0; j < ipv6->GetNAddresses(i); j ++)
mathieu@0
   746
        {
mathieu@0
   747
          Ipv6Address addri = ipv6->GetAddress (i, j).GetAddress();
mathieu@0
   748
          Ipv6Prefix prefix = ipv6->GetAddress (i, j).GetPrefix ();
mathieu@0
   749
mathieu@0
   750
          //here get the address mask length
mathieu@0
   751
          uint8_t mask_len = prefix.GetPrefixLength();
mathieu@0
   752
mathieu@0
   753
          //loopback address's prefix is wrong... FIXME
mathieu@0
   754
          if (addri.IsEqual(Ipv6Address::GetLoopback()))
mathieu@0
   755
            mask_len = 128;
mathieu@0
   756
      
mathieu@0
   757
          //next fill the message body
mathieu@0
   758
          NetlinkMessage nlmsg_ifa;
mathieu@0
   759
          NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
mathieu@0
   760
          InterfaceAddressMessage ifamsg;       
mathieu@0
   761
mathieu@0
   762
          ifamsg.SetInterfaceIndex(i);
mathieu@0
   763
          ifamsg.SetFamily(AF_INET6);
mathieu@0
   764
          ifamsg.SetFlags(0);
mathieu@0
   765
mathieu@0
   766
mathieu@0
   767
          if (addri.IsLinkLocal())
mathieu@0
   768
            {
mathieu@0
   769
              ifamsg.SetLength(64);
mathieu@0
   770
              ifamsg.SetScope (RouteMessage::RT_SCOPE_LINK);
mathieu@0
   771
            }
mathieu@0
   772
          else
mathieu@0
   773
            {
mathieu@0
   774
              ifamsg.SetLength(mask_len);
mathieu@0
   775
              ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
   776
            }
mathieu@0
   777
mathieu@0
   778
mathieu@0
   779
          ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addri));
mathieu@0
   780
          ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addri));
mathieu@0
   781
          //XXXother attributes not used by ns3
mathieu@0
   782
mathieu@0
   783
          nlmsg_ifa.SetHeader(nhr);
mathieu@0
   784
          nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
mathieu@0
   785
          nlmsg_dump.AppendMessage (nlmsg_ifa);
mathieu@0
   786
        }
mathieu@0
   787
    }
mathieu@0
   788
  return nlmsg_dump;
mathieu@0
   789
}
mathieu@0
   790
MultipartNetlinkMessage
mathieu@0
   791
NetlinkSocket::BuildInterfaceInfoDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
mathieu@0
   792
{
mathieu@0
   793
  NS_LOG_FUNCTION (this << pid << seq <<family);
mathieu@0
   794
  MultipartNetlinkMessage nlmsg_dump;
mathieu@0
   795
  for (uint32_t i = 0; i < m_node->GetNDevices (); i ++)
mathieu@0
   796
    {
mathieu@0
   797
      Ptr<NetDevice> dev = m_node->GetDevice (i);
mathieu@0
   798
      Address mac;
mathieu@0
   799
      Address bcast;
mathieu@0
   800
      uint32_t mtu;
mathieu@0
   801
      uint32_t flags = 0;
mathieu@0
   802
mathieu@0
   803
      mac = dev->GetAddress ();
mathieu@0
   804
      bcast = dev->GetBroadcast ();
mathieu@0
   805
      mtu = (uint32_t)dev->GetMtu ();
mathieu@0
   806
mathieu@0
   807
      if (dev->IsLinkUp ())
mathieu@0
   808
        {
mathieu@0
   809
          flags |= IFF_RUNNING;
mathieu@0
   810
          flags |= IFF_UP;
mathieu@0
   811
        }
mathieu@0
   812
      if (dev->IsBroadcast ())
mathieu@0
   813
        {
mathieu@0
   814
          flags |= IFF_BROADCAST;
mathieu@0
   815
        }
mathieu@0
   816
      if (dev->IsMulticast ())
mathieu@0
   817
        {
mathieu@0
   818
          flags |= IFF_MULTICAST;
mathieu@0
   819
        }
mathieu@0
   820
mathieu@0
   821
      NetlinkMessage nlmsg_ifinfo;
mathieu@0
   822
      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWLINK, NETLINK_MSG_F_MULTI, seq, pid);
mathieu@0
   823
      InterfaceInfoMessage ifinfomsg;     
mathieu@0
   824
mathieu@0
   825
      ifinfomsg.SetFamily(0);      // AF_UNSPEC
mathieu@0
   826
      ifinfomsg.SetDeviceType (0); // not clear
mathieu@0
   827
      ifinfomsg.SetInterfaceIndex (i);
mathieu@0
   828
      ifinfomsg.SetDeviceFlags (flags); // not clear
mathieu@0
   829
      ifinfomsg.SetChangeMask (0xffffffff);
mathieu@0
   830
mathieu@0
   831
      // the ns3 device have no  name, here we set "ns3-device i" for test
mathieu@0
   832
      std::stringstream ss;
mathieu@0
   833
      ss <<  "ns3-device" << i;
mathieu@0
   834
mathieu@0
   835
      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_IFNAME,    STRING,  ss.str()));
mathieu@0
   836
      //not used in ns3
mathieu@0
   837
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_TXQLEN,    U32,     0));
mathieu@0
   838
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_WEIGHT,    U32,     0));
mathieu@0
   839
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_OPERSTATE, U8,      0));
mathieu@0
   840
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINKMODE,  U8,      0));
mathieu@0
   841
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MAP,       UNSPEC,  0));
mathieu@0
   842
      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_ADDRESS,   ADDRESS, mac));
mathieu@0
   843
      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_BROADCAST, ADDRESS, bcast));
mathieu@0
   844
      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MTU,       U32,     mtu));
mathieu@0
   845
      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINK,      U32,     i));
mathieu@0
   846
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_QDISC,     STRING,  ""));
mathieu@0
   847
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MASTER,    U32,     0));
mathieu@0
   848
      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_STATS,     UNSPEC,  0));
mathieu@0
   849
mathieu@0
   850
      nlmsg_ifinfo.SetHeader (nhr);
mathieu@0
   851
      nlmsg_ifinfo.SetInterfaceInfoMessage (ifinfomsg);
mathieu@0
   852
      nlmsg_dump.AppendMessage (nlmsg_ifinfo);
mathieu@0
   853
    }
mathieu@0
   854
  return nlmsg_dump;
mathieu@0
   855
}
mathieu@0
   856
MultipartNetlinkMessage
mathieu@0
   857
NetlinkSocket::BuildRouteDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
mathieu@0
   858
{
mathieu@0
   859
  NS_LOG_FUNCTION (this << pid << seq <<family);
mathieu@0
   860
  MultipartNetlinkMessage nlmsg_dump;
mathieu@0
   861
  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
mathieu@0
   862
mathieu@0
   863
  // We only care about staticRouting for netlink support
mathieu@0
   864
  Ipv4StaticRoutingHelper routingHelper;
mathieu@0
   865
  Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
mathieu@0
   866
  for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
mathieu@0
   867
    {
mathieu@0
   868
      NetlinkMessage nlmsg_rt;
mathieu@0
   869
      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
mathieu@0
   870
      RouteMessage rtmsg;
mathieu@0
   871
      Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
mathieu@0
   872
mathieu@0
   873
      rtmsg.SetFamily (AF_INET);
mathieu@0
   874
      rtmsg.SetDstLength (32);
mathieu@0
   875
      rtmsg.SetSrcLength (0);
mathieu@0
   876
      rtmsg.SetTos (0);//not clear
mathieu@0
   877
      rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
mathieu@0
   878
      rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
   879
      rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
mathieu@0
   880
      rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
mathieu@0
   881
mathieu@0
   882
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
mathieu@0
   883
      // ns3 use local address as the route src address
mathieu@0
   884
      //      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, route.GetSource()));
mathieu@0
   885
      //      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, route.GetSource()));//not used in ns3
mathieu@0
   886
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
mathieu@0
   887
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));      
mathieu@0
   888
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
mathieu@0
   889
mathieu@0
   890
      nlmsg_rt.SetHeader (nhr);
mathieu@0
   891
      nlmsg_rt.SetRouteMessage (rtmsg);
mathieu@0
   892
      nlmsg_dump.AppendMessage (nlmsg_rt);
mathieu@0
   893
    }
mathieu@0
   894
mathieu@0
   895
  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
mathieu@0
   896
  // We only care about staticRouting for netlink support
mathieu@0
   897
  Ipv6StaticRoutingHelper routingHelper6;
mathieu@0
   898
  Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
mathieu@0
   899
  for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
mathieu@0
   900
    {
mathieu@0
   901
      NetlinkMessage nlmsg_rt;
mathieu@0
   902
      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
mathieu@0
   903
      RouteMessage rtmsg;
mathieu@0
   904
      Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
mathieu@0
   905
mathieu@0
   906
      rtmsg.SetFamily (AF_INET6);
mathieu@0
   907
      rtmsg.SetDstLength (128);
mathieu@0
   908
      rtmsg.SetSrcLength (0);
mathieu@0
   909
      rtmsg.SetTos (0);//not clear
mathieu@0
   910
      rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
mathieu@0
   911
      rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
   912
      rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
mathieu@0
   913
      rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
mathieu@0
   914
mathieu@0
   915
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
mathieu@0
   916
      //ns3 use local address as the route src address
mathieu@0
   917
      // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, 
mathieu@0
   918
      //                                          ipv6->GetSourceAddress(route.GetDest ())));
mathieu@0
   919
      // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, 
mathieu@0
   920
      //                                          ipv6->GetSourceAddress(route.GetDest ())));
mathieu@0
   921
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
mathieu@0
   922
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));      
mathieu@0
   923
      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
mathieu@0
   924
mathieu@0
   925
      nlmsg_rt.SetHeader (nhr);
mathieu@0
   926
      nlmsg_rt.SetRouteMessage (rtmsg);
mathieu@0
   927
      nlmsg_dump.AppendMessage (nlmsg_rt);
mathieu@0
   928
    }
mathieu@0
   929
mathieu@0
   930
  return nlmsg_dump;
mathieu@0
   931
}
mathieu@0
   932
mathieu@0
   933
int32_t
mathieu@0
   934
NetlinkSocket::DoInterfaceAddressMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
mathieu@0
   935
{
mathieu@0
   936
  NS_LOG_FUNCTION (this << type << family);
mathieu@0
   937
  NS_ASSERT (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
mathieu@0
   938
mathieu@0
   939
  // XXX
mathieu@0
   940
  NS_ASSERT_MSG (false, "Not implemented yet (RTM_NEWADDR/RTM_DELADDR)");
mathieu@0
   941
mathieu@0
   942
  InterfaceAddressMessage ifamsg = nlmsg.GetInterfaceAddressMessage ();
mathieu@0
   943
  Ipv4Address addri, addr_local, bcast;
mathieu@0
   944
  NetlinkAttribute attr_local;
mathieu@0
   945
  uint32_t index = ifamsg.GetInterfaceIndex ();
mathieu@0
   946
  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
mathieu@0
   947
  int flag4 = 0, flag6 = 0;
mathieu@0
   948
mathieu@0
   949
  if (type == NETLINK_RTM_NEWADDR)
mathieu@0
   950
    {
mathieu@0
   951
      //when adding an interface address, it should check the input arguments
mathieu@0
   952
      //prefix-len and local address attribute
mathieu@0
   953
      if (ifamsg.GetLength () > 32 || 
mathieu@0
   954
          ifamsg.GetAttributeByType (attr_local, InterfaceAddressMessage::IF_A_LOCAL) == false)
mathieu@0
   955
        {
mathieu@0
   956
          m_errno = ERROR_INVAL;
mathieu@0
   957
          return -1;
mathieu@0
   958
        }
mathieu@0
   959
    }  
mathieu@0
   960
mathieu@0
   961
  //get necessary information for add/del, many attributes we not used
mathieu@0
   962
  for (uint32_t i = 0; i < ifamsg.GetNNetlinkAttribute (); i ++)
mathieu@0
   963
    {
mathieu@0
   964
      NetlinkAttribute attr = ifamsg.GetNetlinkAttribute (i);
mathieu@0
   965
      uint32_t attr_type = attr.GetAttrType ();
mathieu@0
   966
mathieu@0
   967
      switch(attr_type)
mathieu@0
   968
        {
mathieu@0
   969
        case InterfaceAddressMessage::IF_A_ADDRESS:
mathieu@0
   970
          addri = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
   971
          break;
mathieu@0
   972
        case InterfaceAddressMessage::IF_A_BROADCAST:
mathieu@0
   973
          bcast = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
mathieu@0
   974
          break;
mathieu@0
   975
        case InterfaceAddressMessage::IF_A_LOCAL:
mathieu@0
   976
          addr_local = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
mathieu@0
   977
          break;
mathieu@0
   978
        case InterfaceAddressMessage::IF_A_LABEL:
mathieu@0
   979
        case InterfaceAddressMessage::IF_A_ANYCAST:
mathieu@0
   980
          break;
mathieu@0
   981
        }
mathieu@0
   982
    }
mathieu@0
   983
mathieu@0
   984
  if (type == NETLINK_RTM_NEWADDR)
mathieu@0
   985
    {
mathieu@0
   986
      //when adding an interface address by index, if the indexed interface was not exist,
mathieu@0
   987
      //create an new NetDevice with an new index and set the address
mathieu@0
   988
      //otherwise set the indexed interface directly
mathieu@0
   989
      if (index >= ipv4->GetNInterfaces ())
mathieu@0
   990
        {          
mathieu@0
   991
          Ptr<SimpleNetDevice> dev;
mathieu@0
   992
          dev = CreateObject<SimpleNetDevice> ();
mathieu@0
   993
          dev ->SetAddress (Mac48Address::Allocate ());
mathieu@0
   994
          m_node->AddDevice (dev);
mathieu@0
   995
mathieu@0
   996
          uint32_t netdev_idx = ipv4->AddInterface (dev);
mathieu@0
   997
          // FIXME!
mathieu@0
   998
          Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
mathieu@0
   999
          ipv4->AddAddress (netdev_idx, ipv4Addr);
mathieu@0
  1000
          ipv4->SetUp (netdev_idx);
mathieu@0
  1001
          NS_LOG_INFO ("Add an interface address at index "<< netdev_idx << "but not the ifamsg input" << index);
mathieu@0
  1002
        }
mathieu@0
  1003
      else
mathieu@0
  1004
        {
mathieu@0
  1005
          Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
mathieu@0
  1006
          ipv4->AddAddress (index, ipv4Addr);
mathieu@0
  1007
          if (!ipv4->IsUp (index))
mathieu@0
  1008
            ipv4->SetUp (index);
mathieu@0
  1009
        }    
mathieu@0
  1010
      flag4 = 1;
mathieu@0
  1011
    }
mathieu@0
  1012
  else//type == NETLINK_RTM_DELADDR
mathieu@0
  1013
    {
mathieu@0
  1014
      //when delete an interface address by index, if the indexed interface  was not exist
mathieu@0
  1015
      //return an error EINVAL, otherwise set down the interface which has the addri
mathieu@0
  1016
      if (index >= ipv4->GetNInterfaces ())
mathieu@0
  1017
        {
mathieu@0
  1018
          m_errno = ERROR_NODEV;
mathieu@0
  1019
          return -1;
mathieu@0
  1020
        }
mathieu@0
  1021
      else
mathieu@0
  1022
        {
mathieu@0
  1023
          for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
mathieu@0
  1024
            {
mathieu@0
  1025
              Ipv4Address ad = ipv4->GetAddress (i, 0).GetLocal ();
mathieu@0
  1026
              if (ad == addri && ipv4->IsUp (i))
mathieu@0
  1027
                {
mathieu@0
  1028
                  ipv4->SetDown (i);
mathieu@0
  1029
                  break;
mathieu@0
  1030
                }
mathieu@0
  1031
              if (i == ipv4->GetNInterfaces () - 1)
mathieu@0
  1032
                {
mathieu@0
  1033
                  m_errno = ERROR_ADDRNOTAVAIL;
mathieu@0
  1034
                  return -1;
mathieu@0
  1035
                }
mathieu@0
  1036
            }
mathieu@0
  1037
          flag4 = 1;
mathieu@0
  1038
        }      
mathieu@0
  1039
    }
mathieu@0
  1040
  
mathieu@0
  1041
  //then send an broadcast message, let all user know this operation happened
mathieu@0
  1042
  NetlinkMessage nlmsg_broadcast = nlmsg;
mathieu@0
  1043
  NetlinkMessageHeader nhr;
mathieu@0
  1044
  nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
mathieu@0
  1045
  nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
mathieu@0
  1046
  nlmsg_broadcast.SetHeader (nhr);
mathieu@0
  1047
  if (flag4)
mathieu@0
  1048
    {
mathieu@0
  1049
      SendMessageBroadcast (nlmsg_broadcast, 0, NETLINK_RTM_GRP_IPV4_IFADDR, GetNode ());
mathieu@0
  1050
    }
mathieu@0
  1051
  else if (flag6)
mathieu@0
  1052
    {
mathieu@0
  1053
      SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_IFADDR, GetNode ());
mathieu@0
  1054
    }
mathieu@0
  1055
mathieu@0
  1056
  return 0;
mathieu@0
  1057
}
mathieu@0
  1058
mathieu@0
  1059
int32_t
mathieu@0
  1060
NetlinkSocket::DoInterfaceInfoMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
mathieu@0
  1061
{
mathieu@0
  1062
  NS_LOG_FUNCTION (this << type << family);
mathieu@0
  1063
  NS_ASSERT (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK);
mathieu@0
  1064
  InterfaceInfoMessage ifinfomsg = nlmsg.GetInterfaceInfoMessage ();
mathieu@0
  1065
  // XXX
mathieu@0
  1066
  NS_ASSERT_MSG (false, "Not implemented yet (RTM_GETLINK/RTM_SETLINK)");
mathieu@0
  1067
  return -1;
mathieu@0
  1068
}
mathieu@0
  1069
mathieu@0
  1070
Address
mathieu@0
  1071
NetlinkSocket::ConvertFrom (uint8_t family, const Address &address)
mathieu@0
  1072
{
mathieu@0
  1073
  Address retval;
mathieu@0
  1074
  if (family == AF_INET)
mathieu@0
  1075
    {
mathieu@0
  1076
      retval = Ipv4Address::ConvertFrom (address);
mathieu@0
  1077
    }
mathieu@0
  1078
  else if (family == AF_INET6)
mathieu@0
  1079
    {
mathieu@0
  1080
      retval = Ipv6Address::ConvertFrom (address);
mathieu@0
  1081
    }
mathieu@0
  1082
  return retval;
mathieu@0
  1083
}
mathieu@0
  1084
mathieu@0
  1085
int32_t
mathieu@0
  1086
NetlinkSocket::DoRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
mathieu@0
  1087
{
mathieu@0
  1088
  NS_LOG_FUNCTION (this << type << family);
mathieu@0
  1089
  NS_ASSERT (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE ||type == NETLINK_RTM_GETROUTE);
mathieu@0
  1090
mathieu@0
  1091
  RouteMessage rtmsg = nlmsg.GetRouteMessage ();
mathieu@0
  1092
  Ipv4Address src, dest, gateway;
mathieu@0
  1093
  Ipv6Address src6, dest6, gateway6;
mathieu@0
  1094
  uint32_t index = 0;
mathieu@0
  1095
  int attr_flags[RouteMessage::RT_A_MAX] = {0};
mathieu@0
  1096
  uint8_t dstlen = rtmsg.GetDstLength ();
mathieu@0
  1097
mathieu@0
  1098
  //get necessary information for add/del, many attributes we not used
mathieu@0
  1099
  for (uint32_t i = 0; i < rtmsg.GetNNetlinkAttribute (); i ++)
mathieu@0
  1100
    {
mathieu@0
  1101
      NetlinkAttribute attr = rtmsg.GetNetlinkAttribute (i);
mathieu@0
  1102
      uint32_t attr_type = attr.GetAttrType ();
mathieu@0
  1103
      attr_flags[attr_type] = 1;
mathieu@0
  1104
mathieu@0
  1105
      switch(attr_type)
mathieu@0
  1106
        {
mathieu@0
  1107
        case RouteMessage::RT_A_DST:
mathieu@0
  1108
          if (family == AF_INET)
mathieu@0
  1109
            {
mathieu@0
  1110
              dest = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1111
            }
mathieu@0
  1112
          else if (family == AF_INET6)
mathieu@0
  1113
            {
mathieu@0
  1114
              dest6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1115
            }
mathieu@0
  1116
          break;
mathieu@0
  1117
        case RouteMessage::RT_A_SRC:
mathieu@0
  1118
          if (family == AF_INET)
mathieu@0
  1119
            {
mathieu@0
  1120
              src = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1121
            }
mathieu@0
  1122
          else if (family == AF_INET6)
mathieu@0
  1123
            {
mathieu@0
  1124
              src6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1125
            }
mathieu@0
  1126
          break;
mathieu@0
  1127
        case RouteMessage::RT_A_OIF:
mathieu@0
  1128
          index = attr.GetAttrPayload ().GetU32 ();
mathieu@0
  1129
          break;
mathieu@0
  1130
        case RouteMessage::RT_A_GATEWAY:
mathieu@0
  1131
          if (family == AF_INET)
mathieu@0
  1132
            {
mathieu@0
  1133
              gateway = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1134
            }
mathieu@0
  1135
          else if (family == AF_INET6)
mathieu@0
  1136
            {
mathieu@0
  1137
              gateway6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
mathieu@0
  1138
            }
mathieu@0
  1139
          break;
mathieu@0
  1140
        case RouteMessage::RT_A_IIF:
mathieu@0
  1141
        case RouteMessage::RT_A_PRIORITY:
mathieu@0
  1142
        case RouteMessage::RT_A_PREFSRC:
mathieu@0
  1143
        case RouteMessage::RT_A_METRICS:
mathieu@0
  1144
        case RouteMessage::RT_A_MULTIPATH:
mathieu@0
  1145
        case RouteMessage::RT_A_PROTOINFO:
mathieu@0
  1146
        case RouteMessage::RT_A_FLOW:
mathieu@0
  1147
        case RouteMessage::RT_A_CACHEINFO:
mathieu@0
  1148
        case RouteMessage::RT_A_SESSION:
mathieu@0
  1149
        case RouteMessage::RT_A_MP_ALGO:
mathieu@0
  1150
        case RouteMessage::RT_A_TABLE:
mathieu@0
  1151
          NS_LOG_INFO("route attribute not used by ns3" << attr_type);
mathieu@0
  1152
          //not used by ns3
mathieu@0
  1153
          break;
mathieu@0
  1154
        }
mathieu@0
  1155
    }
mathieu@0
  1156
mathieu@0
  1157
  // Sigh....
mathieu@0
  1158
  Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
mathieu@0
  1159
  Ipv4StaticRoutingHelper routingHelper;
mathieu@0
  1160
  Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
mathieu@0
  1161
mathieu@0
  1162
  Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
mathieu@0
  1163
  Ipv6StaticRoutingHelper routingHelper6;
mathieu@0
  1164
  Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
mathieu@0
  1165
mathieu@0
  1166
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Route message, type: " << type << "; from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
mathieu@0
  1167
      << " to " << dest<< " through " << gateway);
mathieu@0
  1168
mathieu@0
  1169
  if (type == NETLINK_RTM_NEWROUTE)
mathieu@0
  1170
    {
mathieu@0
  1171
      //ns3 add a route entry only depends on 2 or 3 attribute
mathieu@0
  1172
      //other route msg attibute were ignored
mathieu@0
  1173
      if (attr_flags[RouteMessage::RT_A_DST])
mathieu@0
  1174
        {
mathieu@0
  1175
          if (family == AF_INET)
mathieu@0
  1176
            {
mathieu@0
  1177
              if (!attr_flags[RouteMessage::RT_A_OIF])
mathieu@0
  1178
                {
mathieu@0
  1179
                  bool found = 0;
mathieu@0
  1180
                  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
mathieu@0
  1181
                    {
mathieu@0
  1182
                      for (uint32_t j = 0; j < ipv4->GetNAddresses (i); j++)
mathieu@0
  1183
                        {
mathieu@0
  1184
                          if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
mathieu@0
  1185
                            {
mathieu@0
  1186
                              Ipv4Mask mask = ipv4->GetAddress (i, j).GetMask ();
mathieu@0
  1187
                              if (mask.IsMatch (ipv4->GetAddress (i, j).GetLocal (), gateway))
mathieu@0
  1188
                                {
mathieu@0
  1189
                                  index = i;
mathieu@0
  1190
                                  found = true;
mathieu@0
  1191
                                  break;
mathieu@0
  1192
                                }
mathieu@0
  1193
                            }
mathieu@0
  1194
                          if (found) break;
mathieu@0
  1195
                        }
mathieu@0
  1196
                    }
mathieu@0
  1197
                  if (!found)
mathieu@0
  1198
                    {
mathieu@0
  1199
                      NS_LOG_DEBUG ("No suitable interface to add an route entry");
mathieu@0
  1200
                      m_errno = ERROR_ADDRNOTAVAIL;
mathieu@0
  1201
                      return -1;
mathieu@0
  1202
                    }
mathieu@0
  1203
                }
mathieu@0
  1204
            if (dstlen == 32)
mathieu@0
  1205
              {
mathieu@0
  1206
                int exist_flag = 0;
mathieu@0
  1207
                for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
mathieu@0
  1208
                  {
mathieu@0
  1209
                    Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
mathieu@0
  1210
                    if (dest == rt.GetDest ())
mathieu@0
  1211
                      {
mathieu@0
  1212
                        exist_flag = 1;
mathieu@0
  1213
                      }
mathieu@0
  1214
                  }
mathieu@0
  1215
mathieu@0
  1216
                if (exist_flag)
mathieu@0
  1217
                  { //route to dest already exists
mathieu@0
  1218
                    int delete_flag = 0;
mathieu@0
  1219
                    if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_REPLACE)
mathieu@0
  1220
                      {
mathieu@0
  1221
                        for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
mathieu@0
  1222
                          {
mathieu@0
  1223
                            Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
mathieu@0
  1224
                            if (dest == rt.GetDest ())
mathieu@0
  1225
                              {
mathieu@0
  1226
                                ipv4Static->RemoveRoute (i);
mathieu@0
  1227
                                NS_LOG_DEBUG ("Route from  " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to "
mathieu@0
  1228
                                    << dest << " through " << gateway << " removed");
mathieu@0
  1229
                                delete_flag = 1;
mathieu@0
  1230
                              }
mathieu@0
  1231
                          }
mathieu@0
  1232
mathieu@0
  1233
                        if (!delete_flag)
mathieu@0
  1234
                          {
mathieu@0
  1235
                             NS_LOG_INFO ("no route entry removed by dest address in new route sector " << dest);
mathieu@0
  1236
                             m_errno = ERROR_INVAL;
mathieu@0
  1237
                             return -1;
mathieu@0
  1238
                           }
mathieu@0
  1239
                      }
mathieu@0
  1240
                    else
mathieu@0
  1241
                      {
mathieu@0
  1242
                        NS_LOG_DEBUG ("Route exists but overwriting declined!");
mathieu@0
  1243
                      }
mathieu@0
  1244
                    if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
mathieu@0
  1245
                      {
mathieu@0
  1246
                        NS_LOG_DEBUG (Simulator::Now().GetSeconds() << "Overwrite route from "
mathieu@0
  1247
                            << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest<< " through " << gateway << " with index" << index);
mathieu@0
  1248
                        ipv4Static->AddHostRouteTo (dest, gateway, index);
mathieu@0
  1249
                      }
mathieu@0
  1250
                    else
mathieu@0
  1251
                      {
mathieu@0
  1252
                        NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Overwrite route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
mathieu@0
  1253
                            << " to " << dest<< " through " << "self" << " with index" << index);
mathieu@0
  1254
                        ipv4Static->AddHostRouteTo (dest, index);
mathieu@0
  1255
                      }
mathieu@0
  1256
                }
mathieu@0
  1257
                else
mathieu@0
  1258
                  { //route to dest doesn't exist
mathieu@0
  1259
                    if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_CREATE)
mathieu@0
  1260
                      {
mathieu@0
  1261
                        if (attr_flags[RouteMessage::RT_A_GATEWAY])
mathieu@0
  1262
                          {
mathieu@0
  1263
                            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
mathieu@0
  1264
                                << " to " << dest<< " through " << gateway << " with index" << index);
mathieu@0
  1265
                            ipv4Static->AddHostRouteTo (dest, gateway, index);
mathieu@0
  1266
                          }
mathieu@0
  1267
                        else
mathieu@0
  1268
                          {
mathieu@0
  1269
                            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
mathieu@0
  1270
                                << " to " << dest<< " through " << "self" << " with index" << index);
mathieu@0
  1271
                            ipv4Static->AddHostRouteTo (dest, index);
mathieu@0
  1272
                          }
mathieu@0
  1273
                      }
mathieu@0
  1274
                    else
mathieu@0
  1275
                      {
mathieu@0
  1276
                        NS_LOG_ERROR ("Route doesn't exist but writing declined!");
mathieu@0
  1277
                      }
mathieu@0
  1278
                  }
mathieu@0
  1279
mathieu@0
  1280
                NS_LOG_DEBUG ("=After change attempt=");
mathieu@0
  1281
                //Dump of table
mathieu@0
  1282
                NS_LOG_DEBUG (m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << ":");
mathieu@0
  1283
                for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
mathieu@0
  1284
                  {
mathieu@0
  1285
                    Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
mathieu@0
  1286
                    NS_LOG_DEBUG (rt.GetDest () << " through " << rt.GetGateway ());
mathieu@0
  1287
                  }
mathieu@0
  1288
                NS_LOG_DEBUG ("= = = = = = = = = = =");
mathieu@0
  1289
              }
mathieu@0
  1290
            else // dstlen != 32
mathieu@0
  1291
              {
mathieu@0
  1292
                if (attr_flags[RouteMessage::RT_A_GATEWAY])
mathieu@0
  1293
                  {
mathieu@0
  1294
                    ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), gateway, index);
mathieu@0
  1295
                  }
mathieu@0
  1296
                else
mathieu@0
  1297
                  {
mathieu@0
  1298
                    ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), index);
mathieu@0
  1299
                  }
mathieu@0
  1300
              }
mathieu@0
  1301
          }
mathieu@0
  1302
          else if (family == AF_INET6)
mathieu@0
  1303
            {
mathieu@0
  1304
            if (!attr_flags[RouteMessage::RT_A_OIF])
mathieu@0
  1305
              {
mathieu@0
  1306
#ifdef FIXME
mathieu@0
  1307
              if (ipv6->GetIfIndexForDestination (gateway6, index) == false)
mathieu@0
  1308
                {
mathieu@0
  1309
                  NS_LOG_INFO ("No suitable interface to add an route entry");
mathieu@0
  1310
                  m_errno = ERROR_ADDRNOTAVAIL;
mathieu@0
  1311
                  return -1;
mathieu@0
  1312
                }
mathieu@0
  1313
#endif
mathieu@0
  1314
              }
mathieu@0
  1315
mathieu@0
  1316
            Ipv6Prefix pref (dstlen);
mathieu@0
  1317
            if (attr_flags[RouteMessage::RT_A_GATEWAY])
mathieu@0
  1318
              {
mathieu@0
  1319
                ipv6Static->AddNetworkRouteTo (dest6, pref, gateway6, index);
mathieu@0
  1320
              }
mathieu@0
  1321
            else
mathieu@0
  1322
              {
mathieu@0
  1323
                ipv6Static->AddNetworkRouteTo (dest6, pref, Ipv6Address("::"), index);
mathieu@0
  1324
              }
mathieu@0
  1325
            }
mathieu@0
  1326
          }
mathieu@0
  1327
        else
mathieu@0
  1328
          {
mathieu@0
  1329
            NS_LOG_INFO("too few attributes to add an route entry");
mathieu@0
  1330
            m_errno = ERROR_INVAL;
mathieu@0
  1331
            return -1;
mathieu@0
  1332
          }
mathieu@0
  1333
    }
mathieu@0
  1334
  else if (type == NETLINK_RTM_DELROUTE)
mathieu@0
  1335
    {
mathieu@0
  1336
      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Route delete request from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
mathieu@0
  1337
          << " to " << dest<< " through " << gateway);
mathieu@0
  1338
      if (attr_flags[RouteMessage::RT_A_DST])
mathieu@0
  1339
        {
mathieu@0
  1340
          int delete_flag = 0;
mathieu@0
  1341
mathieu@0
  1342
          if (family == AF_INET)
mathieu@0
  1343
            {
mathieu@0
  1344
              for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
mathieu@0
  1345
                {
mathieu@0
  1346
                Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
mathieu@0
  1347
                if (gateway == rt.GetGateway () && dest == rt.GetDest ())
mathieu@0
  1348
                  {
mathieu@0
  1349
                    ipv4Static->RemoveRoute (i);
mathieu@0
  1350
                    delete_flag = 1;
mathieu@0
  1351
                  }
mathieu@0
  1352
                }
mathieu@0
  1353
            }
mathieu@0
  1354
          else if (family == AF_INET6)
mathieu@0
  1355
            {
mathieu@0
  1356
              for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
mathieu@0
  1357
                {
mathieu@0
  1358
                Ipv6RoutingTableEntry rt = ipv6Static->GetRoute (i);
mathieu@0
  1359
                if (gateway6 == rt.GetGateway () && dest6 == rt.GetDest ())
mathieu@0
  1360
                  {
mathieu@0
  1361
                    ipv6Static->RemoveRoute (i);
mathieu@0
  1362
                    delete_flag = 1;
mathieu@0
  1363
                  }
mathieu@0
  1364
                }
mathieu@0
  1365
            }
mathieu@0
  1366
mathieu@0
  1367
          if (!delete_flag)
mathieu@0
  1368
            {
mathieu@0
  1369
              NS_LOG_INFO ("no route entry removed by dest address " << dest);
mathieu@0
  1370
              m_errno = ERROR_INVAL;
mathieu@0
  1371
              return -1;
mathieu@0
  1372
            }
mathieu@0
  1373
        }
mathieu@0
  1374
      else
mathieu@0
  1375
        {
mathieu@0
  1376
          NS_LOG_INFO ("too few attributes to add an route entry");
mathieu@0
  1377
          m_errno = ERROR_INVAL;
mathieu@0
  1378
          return -1;    
mathieu@0
  1379
        }
mathieu@0
  1380
    }
mathieu@0
  1381
  else// type == NETLINK_RTM_GETROUTE
mathieu@0
  1382
    {
mathieu@0
  1383
      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "GetRoute "<< "from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest);
mathieu@0
  1384
      if (!attr_flags[RouteMessage::RT_A_DST])
mathieu@0
  1385
        {
mathieu@0
  1386
          NS_LOG_INFO ("too few attributes to get an route entry");
mathieu@0
  1387
          m_errno = ERROR_INVAL;
mathieu@0
  1388
          return -1;
mathieu@0
  1389
        }
mathieu@0
  1390
      
mathieu@0
  1391
      int get_flag = 0;
mathieu@0
  1392
      if (family == AF_INET)
mathieu@0
  1393
        {
mathieu@0
  1394
          for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
mathieu@0
  1395
            {
mathieu@0
  1396
              Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
mathieu@0
  1397
              //find the route entry with same dest address and send unicast to user space
mathieu@0
  1398
              if (dest.IsEqual (route.GetDest ()))
mathieu@0
  1399
                {
mathieu@0
  1400
                  //                Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
mathieu@0
  1401
                  NetlinkMessage nlmsg_route;
mathieu@0
  1402
                  NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0, 
mathieu@0
  1403
                                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
mathieu@0
  1404
                  RouteMessage rtmsg;
mathieu@0
  1405
mathieu@0
  1406
                  //fill rtmsg and attributes
mathieu@0
  1407
                  rtmsg.SetFamily (AF_INET);
mathieu@0
  1408
                  rtmsg.SetDstLength (32);
mathieu@0
  1409
                  rtmsg.SetSrcLength (0);
mathieu@0
  1410
                  rtmsg.SetTos (0);//not clear
mathieu@0
  1411
                  rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
mathieu@0
  1412
                  rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
  1413
                  rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
mathieu@0
  1414
                  rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
mathieu@0
  1415
mathieu@0
  1416
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
mathieu@0
  1417
                  //ns3 use local address as the route src address
mathieu@0
  1418
                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
mathieu@0
  1419
                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
mathieu@0
  1420
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
mathieu@0
  1421
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
mathieu@0
  1422
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
mathieu@0
  1423
mathieu@0
  1424
                  //fill an netlink message body
mathieu@0
  1425
                  nlmsg_route.SetHeader (nhr);
mathieu@0
  1426
                  nlmsg_route.SetRouteMessage (rtmsg);
mathieu@0
  1427
                  
mathieu@0
  1428
                  SendMessageUnicast (nlmsg_route, m_srcPid, 1);
mathieu@0
  1429
                  get_flag = 1;
mathieu@0
  1430
                }
mathieu@0
  1431
            }
mathieu@0
  1432
        }
mathieu@0
  1433
      else if (family == AF_INET6)
mathieu@0
  1434
        {
mathieu@0
  1435
          for (uint32_t i = 0; i < ipv6Static->GetNRoutes(); i ++)
mathieu@0
  1436
            {
mathieu@0
  1437
              Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
mathieu@0
  1438
              //find the route entry with same dest address and send unicast to user space
mathieu@0
  1439
              if (dest6.IsEqual (route.GetDest ()))
mathieu@0
  1440
                {
mathieu@0
  1441
                  NetlinkMessage nlmsg_route;
mathieu@0
  1442
                  NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0, 
mathieu@0
  1443
                                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
mathieu@0
  1444
                  RouteMessage rtmsg;
mathieu@0
  1445
mathieu@0
  1446
                  //fill rtmsg and attributes
mathieu@0
  1447
                  rtmsg.SetFamily (AF_INET6);
mathieu@0
  1448
                  rtmsg.SetDstLength (32);
mathieu@0
  1449
                  rtmsg.SetSrcLength (0);
mathieu@0
  1450
                  rtmsg.SetTos (0);//not clear
mathieu@0
  1451
                  rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
mathieu@0
  1452
                  rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
  1453
                  rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
mathieu@0
  1454
                  rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
mathieu@0
  1455
mathieu@0
  1456
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
mathieu@0
  1457
                  //ns3 use local address as the route src address
mathieu@0
  1458
                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
mathieu@0
  1459
                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
mathieu@0
  1460
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
mathieu@0
  1461
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
mathieu@0
  1462
                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
mathieu@0
  1463
mathieu@0
  1464
                  //fill an netlink message body
mathieu@0
  1465
                  nlmsg_route.SetHeader (nhr);
mathieu@0
  1466
                  nlmsg_route.SetRouteMessage (rtmsg);
mathieu@0
  1467
mathieu@0
  1468
                  SendMessageUnicast (nlmsg_route, m_srcPid, 1);
mathieu@0
  1469
                  get_flag = 1;
mathieu@0
  1470
                }
mathieu@0
  1471
            }
mathieu@0
  1472
        }
mathieu@0
  1473
      
mathieu@0
  1474
      if (!get_flag)
mathieu@0
  1475
        {
mathieu@0
  1476
          NS_LOG_INFO ("no route entry exist by dest address" << dest);
mathieu@0
  1477
          m_errno = ERROR_INVAL;
mathieu@0
  1478
          return -1;
mathieu@0
  1479
        }
mathieu@0
  1480
    }
mathieu@0
  1481
mathieu@0
  1482
  //then send an broadcast message, let all user know this operation happened
mathieu@0
  1483
  MultipartNetlinkMessage nlmsg_multi;
mathieu@0
  1484
  NetlinkMessage nlmsg_broadcast = nlmsg;
mathieu@0
  1485
  NetlinkMessage nlmsg_done;
mathieu@0
  1486
  NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
mathieu@0
  1487
  nlmsg_done.SetHeader (nhr_done);
mathieu@0
  1488
  nlmsg_multi.AppendMessage (nlmsg);
mathieu@0
  1489
  nlmsg_multi.AppendMessage (nlmsg_done);
mathieu@0
  1490
  SendMessageBroadcast (nlmsg_multi, 0, NETLINK_RTM_GRP_IPV4_ROUTE, GetNode ());
mathieu@0
  1491
  //   SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
mathieu@0
  1492
  return 0;
mathieu@0
  1493
}
mathieu@0
  1494
mathieu@0
  1495
int32_t
mathieu@0
  1496
NetlinkSocket::NotifyIfLinkMessage (Address address, uint16_t type, uint8_t family)
mathieu@0
  1497
{
mathieu@0
  1498
  NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfLinkMessage)");
mathieu@0
  1499
  return 0;
mathieu@0
  1500
}
mathieu@0
  1501
mathieu@0
  1502
int32_t
mathieu@0
  1503
NetlinkSocket::NotifyIfAddrMessage (Ipv6Interface* interface, Ipv6Address addr, int cmd)
mathieu@0
  1504
{
mathieu@0
  1505
  MultipartNetlinkMessage nlmsg_multi;
mathieu@0
  1506
  NetlinkMessage nlmsg_ifa;
mathieu@0
  1507
  NetlinkMessageHeader nhr = NetlinkMessageHeader (cmd, NETLINK_MSG_F_MULTI, 0, 0);
mathieu@0
  1508
  InterfaceAddressMessage ifamsg;
mathieu@0
  1509
mathieu@0
  1510
  NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfAddrMessage)");
mathieu@0
  1511
mathieu@0
  1512
  // FIXME!
mathieu@0
  1513
  Ipv6Prefix prefix = Ipv6Prefix(64);
mathieu@0
  1514
mathieu@0
  1515
  //here get the address mask length
mathieu@0
  1516
  uint8_t bytes[16];
mathieu@0
  1517
  prefix.GetBytes (bytes);
mathieu@0
  1518
  uint8_t mask_len = 0;
mathieu@0
  1519
  for (int j = 0; j < 16; j++)
mathieu@0
  1520
    {
mathieu@0
  1521
      while (bytes[j])
mathieu@0
  1522
        {
mathieu@0
  1523
          bytes[j] = bytes[j] << 1;
mathieu@0
  1524
          mask_len ++;
mathieu@0
  1525
        }
mathieu@0
  1526
    }
mathieu@0
  1527
      
mathieu@0
  1528
  ifamsg.SetInterfaceIndex (interface->GetDevice ()->GetIfIndex ());
mathieu@0
  1529
  ifamsg.SetFamily (AF_INET6);
mathieu@0
  1530
  ifamsg.SetLength (mask_len);
mathieu@0
  1531
  ifamsg.SetFlags (0);
mathieu@0
  1532
  ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
mathieu@0
  1533
mathieu@0
  1534
  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addr));
mathieu@0
  1535
  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addr));
mathieu@0
  1536
  //  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
mathieu@0
  1537
  //      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL,    STRING,  "ns3-ifaddr"));//not used in ns3
mathieu@0
  1538
  //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST,  ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
mathieu@0
  1539
  //XXXother attributes not used by ns3
mathieu@0
  1540
mathieu@0
  1541
  nlmsg_ifa.SetHeader (nhr);
mathieu@0
  1542
  nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
mathieu@0
  1543
mathieu@0
  1544
  NetlinkMessage nlmsg_done;
mathieu@0
  1545
  NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
mathieu@0
  1546
  nlmsg_done.SetHeader (nhr_done);
mathieu@0
  1547
mathieu@0
  1548
  nlmsg_multi.AppendMessage (nlmsg_ifa);
mathieu@0
  1549
  nlmsg_multi.AppendMessage (nlmsg_done);
mathieu@0
  1550
mathieu@0
  1551
  SendMessageBroadcast (nlmsg_multi, 0, RTMGRP_IPV6_IFADDR, interface->GetDevice ()->GetNode ());  
mathieu@0
  1552
  return 0;
mathieu@0
  1553
}
mathieu@0
  1554
mathieu@0
  1555
#ifdef FIXME
mathieu@0
  1556
int32_t
mathieu@0
  1557
NetlinkSocket::NotifyRouteMessage(Ojbect route, uint16_t type, uint8_t family)
mathieu@0
  1558
{
mathieu@0
  1559
  NetlinkMessage nlmsg_broadcast = nlmsg;
mathieu@0
  1560
  NetlinkMessageHeader nhr;
mathieu@0
  1561
  NS_ASSERT_MSG (false, "Not implemented yet");
mathieu@0
  1562
mathieu@0
  1563
  nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
mathieu@0
  1564
  nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
mathieu@0
  1565
  nlmsg_broadcast.SetHeader (nhr);
mathieu@0
  1566
  SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
mathieu@0
  1567
  return 0;
mathieu@0
  1568
}
mathieu@0
  1569
#endif
mathieu@0
  1570
mathieu@0
  1571
}//namespace ns3