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