netlink/netlink-socket.cc
changeset 66 2fe1f3e576c9
parent 63 e89dca438df6
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netlink/netlink-socket.cc	Thu May 05 09:28:21 2011 +0200
     1.3 @@ -0,0 +1,1571 @@
     1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     1.5 +/*
     1.6 + * Copyright (c) 2008 Liu Jian
     1.7 + *
     1.8 + * This program is free software; you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License version 2 as
    1.10 + * published by the Free Software Foundation;
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program; if not, write to the Free Software
    1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.20 + *
    1.21 + * Author: Liu Jian <liujatp@gmail.com>
    1.22 + *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
    1.23 + */
    1.24 +
    1.25 +#include "netlink-socket.h"
    1.26 +#include "netlink-socket-address.h"
    1.27 +#include "netlink-message.h"
    1.28 +#include "netlink-message-route.h"
    1.29 +#include "ns3/log.h"
    1.30 +#include "ns3/node.h"
    1.31 +#include "ns3/packet.h"
    1.32 +#include "ns3/ipv4-address.h"
    1.33 +#include "ns3/ipv4.h"
    1.34 +#include "ns3/simple-net-device.h"
    1.35 +#include "ns3/uinteger.h"
    1.36 +#include "ns3/trace-source-accessor.h"
    1.37 +#include <iostream>
    1.38 +#include <sstream>
    1.39 +#include "ns3/ipv6-address.h"
    1.40 +#include "ns3/ipv6.h"
    1.41 +#include "ns3/ipv4-l3-protocol.h"
    1.42 +#include "ns3/ipv4-static-routing-helper.h"
    1.43 +#include "ns3/ipv4-routing-table-entry.h"
    1.44 +#include "ns3/ipv6-l3-protocol.h"
    1.45 +#include "ns3/ipv6-interface.h"
    1.46 +#include "ns3/ipv6-static-routing-helper.h"
    1.47 +#include "ns3/ipv6-routing-table-entry.h"
    1.48 +#include "ns3/socket.h"
    1.49 +#include "ns3/mac48-address.h"
    1.50 +#include <sys/socket.h>
    1.51 +#include <linux/if.h>
    1.52 +#include <errno.h>
    1.53 +
    1.54 +NS_LOG_COMPONENT_DEFINE ("NetlinkSocket");
    1.55 +
    1.56 +namespace ns3 {
    1.57 +
    1.58 +// GroupSockets store the netlinksocket with noero group value
    1.59 +// it was due to the mulitcast netlink messages.
    1.60 +class GroupSockets
    1.61 +{
    1.62 +public:
    1.63 +  static uint32_t GetNSockets(void)
    1.64 +  { 
    1.65 +    return m_Sockets.size();
    1.66 +  }
    1.67 +  static Ptr<NetlinkSocket> GetSocket(uint32_t index)
    1.68 +  {
    1.69 +    NS_ASSERT(index < m_Sockets.size());
    1.70 +    return m_Sockets[index];
    1.71 +  }
    1.72 +  static void AddSocket(Ptr<NetlinkSocket>sock)
    1.73 +  {
    1.74 +    m_Sockets.push_back(sock);
    1.75 +  }
    1.76 +private:
    1.77 +   /*use a std::vector to store the sockets with nozero group value*/
    1.78 +  static std::vector<Ptr<NetlinkSocket> >m_Sockets;
    1.79 +};
    1.80 +std::vector<Ptr<NetlinkSocket> >GroupSockets::m_Sockets;
    1.81 +
    1.82 +NS_OBJECT_ENSURE_REGISTERED (NetlinkSocket);
    1.83 +
    1.84 +/*
    1.85 +Netlink Socket
    1.86 +*/
    1.87 +TypeId
    1.88 +NetlinkSocket::GetTypeId (void)
    1.89 +{
    1.90 +  static TypeId tid = TypeId ("ns3::NetlinkSocket")
    1.91 +    .SetParent<Socket> ()
    1.92 +    .AddConstructor<NetlinkSocket> ()
    1.93 +    .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
    1.94 +                     MakeTraceSourceAccessor (&NetlinkSocket::m_dropTrace))
    1.95 +    .AddAttribute ("RcvBufSize",
    1.96 +                   "NetlinkSocket maximum receive buffer size (bytes)",
    1.97 +                   UintegerValue (0xffffffffl),
    1.98 +                   MakeUintegerAccessor (&NetlinkSocket::m_rcvBufSize),
    1.99 +                   MakeUintegerChecker<uint32_t> ())
   1.100 +    .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
   1.101 +                   CallbackValue (),
   1.102 +                   MakeCallbackAccessor (&NetlinkSocket::m_icmpCallback),
   1.103 +                   MakeCallbackChecker ())
   1.104 +    ;
   1.105 +  return tid;
   1.106 +}
   1.107 +
   1.108 +NetlinkSocket::NetlinkSocket ()
   1.109 +  : m_shutdownSend (false),
   1.110 +    m_shutdownRecv (false),
   1.111 +    m_rxAvailable (0),
   1.112 +    m_srcPid (0),
   1.113 +    m_srcGroups (0),
   1.114 +    m_dstPid (0),
   1.115 +    m_dstGroups (0)
   1.116 +{
   1.117 +  NS_LOG_FUNCTION_NOARGS ();
   1.118 +  m_errno = ERROR_NOTERROR;
   1.119 +}
   1.120 +NetlinkSocket::~NetlinkSocket ()
   1.121 +{
   1.122 +  NS_LOG_FUNCTION (this);
   1.123 +}
   1.124 +void 
   1.125 +NetlinkSocket::DoDispose (void)
   1.126 +{
   1.127 +  NS_LOG_FUNCTION_NOARGS ();
   1.128 +}
   1.129 +
   1.130 +int
   1.131 +NetlinkSocket::ErrnoToSimuErrno (void)
   1.132 +{
   1.133 +  switch (m_errno)
   1.134 +    {
   1.135 +    case Socket::ERROR_ISCONN:
   1.136 +      return EISCONN;
   1.137 +    case Socket::ERROR_NOTCONN:
   1.138 +      return ENOTCONN;
   1.139 +    case Socket::ERROR_MSGSIZE:
   1.140 +      return EMSGSIZE;
   1.141 +    case Socket::ERROR_AGAIN:
   1.142 +      return EAGAIN;
   1.143 +    case Socket::ERROR_SHUTDOWN:
   1.144 +      return ESHUTDOWN;
   1.145 +    case Socket::ERROR_OPNOTSUPP:
   1.146 +      return EOPNOTSUPP;
   1.147 +    case Socket::ERROR_AFNOSUPPORT:
   1.148 +      return EAFNOSUPPORT;
   1.149 +    case Socket::ERROR_INVAL:
   1.150 +      return EINVAL;
   1.151 +    case Socket::ERROR_BADF:
   1.152 +      return EBADF;
   1.153 +    case Socket::ERROR_NOROUTETOHOST:
   1.154 +      return EHOSTUNREACH;
   1.155 +    case Socket::ERROR_NODEV:
   1.156 +      return ENODEV;
   1.157 +    case Socket::ERROR_ADDRNOTAVAIL:
   1.158 +      return EADDRNOTAVAIL;
   1.159 +    case Socket::SOCKET_ERRNO_LAST:
   1.160 +    case Socket::ERROR_NOTERROR:
   1.161 +    default:
   1.162 +      NS_ASSERT (false);
   1.163 +      return 0; // quiet compiler
   1.164 +      break;
   1.165 +    }
   1.166 +}
   1.167 +
   1.168 +void 
   1.169 +NetlinkSocket::SetNode (Ptr<Node> node)
   1.170 +{
   1.171 +  NS_LOG_FUNCTION_NOARGS ();
   1.172 +  m_node = node;
   1.173 +}
   1.174 +
   1.175 +
   1.176 +enum Socket::SocketErrno
   1.177 +NetlinkSocket::GetErrno (void) const
   1.178 +{
   1.179 +  NS_LOG_FUNCTION_NOARGS ();
   1.180 +  return m_errno;
   1.181 +}
   1.182 +enum Socket::SocketType 
   1.183 +NetlinkSocket::GetSocketType (void) const
   1.184 +{
   1.185 +  return Socket::NS3_SOCK_DGRAM;
   1.186 +}
   1.187 +
   1.188 +Ptr<Node>
   1.189 +NetlinkSocket::GetNode (void) const
   1.190 +{
   1.191 +  NS_LOG_FUNCTION_NOARGS ();
   1.192 +  return m_node;
   1.193 +}
   1.194 +
   1.195 +uint32_t
   1.196 +NetlinkSocket::GetSrcPid (void) const
   1.197 +{
   1.198 +  NS_LOG_FUNCTION_NOARGS ();
   1.199 +  return m_srcPid;
   1.200 +}
   1.201 +uint32_t
   1.202 +NetlinkSocket::GetSrcGroups (void)const
   1.203 +{
   1.204 +  NS_LOG_FUNCTION_NOARGS ();
   1.205 +  return m_srcGroups;
   1.206 +}
   1.207 +uint32_t
   1.208 +NetlinkSocket::GetDstPid (void) const
   1.209 +{
   1.210 +  NS_LOG_FUNCTION_NOARGS ();
   1.211 +  return m_dstPid;
   1.212 +}
   1.213 +uint32_t
   1.214 +NetlinkSocket::GetDstGroups (void)const
   1.215 +{
   1.216 +  NS_LOG_FUNCTION_NOARGS ();
   1.217 +  return m_dstGroups;
   1.218 +}
   1.219 +
   1.220 +int
   1.221 +NetlinkSocket::Bind (void)
   1.222 +{
   1.223 +  NS_LOG_FUNCTION_NOARGS ();
   1.224 +  NetlinkSocketAddress address;
   1.225 +  return DoBind (address);
   1.226 +}
   1.227 +int
   1.228 +NetlinkSocket::Bind (const Address &address)
   1.229 +{ 
   1.230 +  NS_LOG_FUNCTION (this << address);
   1.231 +
   1.232 +  if (!NetlinkSocketAddress::IsMatchingType (address))
   1.233 +    {
   1.234 +      m_errno = ERROR_INVAL;
   1.235 +      return -1;
   1.236 +    }
   1.237 +  NetlinkSocketAddress ad = NetlinkSocketAddress::ConvertFrom (address);
   1.238 +  return DoBind (ad);
   1.239 +}
   1.240 +int
   1.241 +NetlinkSocket::DoBind (const NetlinkSocketAddress &address)
   1.242 +{
   1.243 +  NS_LOG_FUNCTION (this << address);
   1.244 +
   1.245 +  m_srcPid = address.GetProcessID ();
   1.246 +  m_srcGroups = address.GetGroupsMask ();
   1.247 +
   1.248 +  if (m_srcGroups)
   1.249 +    {
   1.250 +      GroupSockets::AddSocket(this);
   1.251 +    } 
   1.252 +  return 0;
   1.253 +}
   1.254 +
   1.255 +int 
   1.256 +NetlinkSocket::Listen (void)
   1.257 +{
   1.258 +  NS_LOG_FUNCTION_NOARGS ();
   1.259 +  m_errno = Socket::ERROR_OPNOTSUPP;
   1.260 +  return -1;
   1.261 +}
   1.262 +
   1.263 +uint32_t
   1.264 +NetlinkSocket::GetTxAvailable (void) const
   1.265 +{
   1.266 +  NS_LOG_FUNCTION_NOARGS ();
   1.267 +  return 0;
   1.268 +}
   1.269 +uint32_t
   1.270 +NetlinkSocket::GetRxAvailable (void) const
   1.271 +{
   1.272 +  NS_LOG_FUNCTION_NOARGS ();
   1.273 +  // We separately maintain this state to avoid walking the queue 
   1.274 +  // every time this might be called
   1.275 +  return m_rxAvailable;
   1.276 +}
   1.277 +
   1.278 +int
   1.279 +NetlinkSocket::ShutdownSend (void)
   1.280 +{
   1.281 +  NS_LOG_FUNCTION_NOARGS ();
   1.282 +  m_shutdownSend = true;
   1.283 +  return 0;
   1.284 +}
   1.285 +int
   1.286 +NetlinkSocket::ShutdownRecv (void)
   1.287 +{
   1.288 +  NS_LOG_FUNCTION_NOARGS ();
   1.289 +  m_shutdownRecv = true;
   1.290 +  return 0;
   1.291 +}
   1.292 +
   1.293 +int
   1.294 +NetlinkSocket::Close (void)
   1.295 +{
   1.296 +  NS_LOG_FUNCTION_NOARGS ();
   1.297 +  ShutdownSend();
   1.298 +  ShutdownRecv();
   1.299 +  return 0;
   1.300 +}
   1.301 +
   1.302 +int
   1.303 +NetlinkSocket::Connect (const Address &address)
   1.304 +{
   1.305 +  NS_LOG_FUNCTION (this << address);
   1.306 +  m_errno = Socket::ERROR_OPNOTSUPP;
   1.307 +  return 0;
   1.308 +}
   1.309 +
   1.310 +Ptr<Packet>
   1.311 +NetlinkSocket::Recv (uint32_t maxSize, uint32_t flags)
   1.312 +{
   1.313 +  NS_LOG_FUNCTION (this << maxSize<< flags);
   1.314 +  if (m_dataReceiveQueue.empty())
   1.315 +    {
   1.316 +      return 0;
   1.317 +    }
   1.318 +
   1.319 +  Ptr<Packet> p = m_dataReceiveQueue.front ();
   1.320 +  if (p->GetSize () <= maxSize) 
   1.321 +    {
   1.322 +      m_dataReceiveQueue.pop ();
   1.323 +      m_rxAvailable -= p->GetSize ();
   1.324 +    }
   1.325 +  else
   1.326 +    {
   1.327 +      p = 0; 
   1.328 +    }
   1.329 +  return p;
   1.330 +}
   1.331 +
   1.332 +Ptr<Packet>
   1.333 +NetlinkSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
   1.334 +{
   1.335 +  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
   1.336 +  Ptr<Packet> packet = Recv (maxSize, flags);
   1.337 +  if (packet != 0)
   1.338 +    {
   1.339 +      SocketAddressTag tag;
   1.340 +      bool found;
   1.341 +      found = packet->FindFirstMatchingByteTag (tag);
   1.342 +      NS_ASSERT (found);
   1.343 +      fromAddress = tag.GetAddress ();
   1.344 +    }
   1.345 +  return packet;
   1.346 +}
   1.347 +
   1.348 +int
   1.349 +NetlinkSocket::Send (Ptr<Packet> p,uint32_t flags)
   1.350 +{
   1.351 +  NS_LOG_FUNCTION (this << p << flags);
   1.352 +  NetlinkSocketAddress address = NetlinkSocketAddress(m_dstPid, m_dstGroups);
   1.353 +  return SendTo(p, flags, address);
   1.354 +}
   1.355 +
   1.356 +int
   1.357 +NetlinkSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &toAddress)
   1.358 +{
   1.359 +  NS_LOG_FUNCTION (this << p << flags << toAddress);
   1.360 +  NetlinkSocketAddress ad;
   1.361 +
   1.362 +  if (!NetlinkSocketAddress::IsMatchingType (toAddress))
   1.363 +    {
   1.364 +      NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
   1.365 +      m_errno = ERROR_AFNOSUPPORT;
   1.366 +      return -1;
   1.367 +    }
   1.368 +  ad = NetlinkSocketAddress::ConvertFrom (toAddress);
   1.369 +  m_dstPid = ad.GetProcessID();
   1.370 +  m_dstGroups = ad.GetGroupsMask();
   1.371 +  NS_LOG_INFO ("send netlink message to pid = " << m_dstPid << ", groups = " << m_dstGroups);
   1.372 +  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending netlink message from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ());
   1.373 +
   1.374 +  //Ptr<NetlinkSocket>kernel_socket = GetNetlinkSocketByAddress(ad);
   1.375 +  //kernel_socket->m_receivedData.push_back(p);
   1.376 +  //kernel_socket->NotifyDataReceived(p);
   1.377 +
   1.378 +  //when netlink socket send packet, the first step is to find the dest netlink socket through address
   1.379 +  //then send the packet to it. For we partly implement the netlink-family, the dest address
   1.380 +  //is always the kernel(pid = 0), (Actually, there must be one static kernel netlink socket to
   1.381 +  //receive/handle messages), we do not setup a kernel socket to receive packet.
   1.382 +  //
   1.383 +  
   1.384 +  MultipartNetlinkMessage multipartnlmsg;
   1.385 +  uint32_t packet_len, remain_len;
   1.386 +
   1.387 +  packet_len = p->GetSize ();
   1.388 +  remain_len = packet_len;
   1.389 +
   1.390 +  while (remain_len > NetlinkMessageHeader::GetHeaderSize ())
   1.391 +    {
   1.392 +      remain_len -= p->RemoveHeader (multipartnlmsg);
   1.393 +      NS_ASSERT (remain_len == p->GetSize ());
   1.394 +
   1.395 +      //actually, message to kernel contains single one netlink message
   1.396 +      for (uint32_t i = 0; i < multipartnlmsg.GetNMessages(); i ++)
   1.397 +        {
   1.398 +          NetlinkMessage nlmsg = multipartnlmsg.GetMessage (i);
   1.399 +          if (HandleMessage (nlmsg) < 0)
   1.400 +            {
   1.401 +              if (m_errno)
   1.402 +                {
   1.403 +                  SendAckMessage (nlmsg, -ErrnoToSimuErrno ());
   1.404 +                }
   1.405 +            }
   1.406 +          else if (NetlinkMessage::IsMessageFlagsAck (nlmsg.GetHeader ().GetMsgFlags ()))
   1.407 +            {
   1.408 +              SendAckMessage (nlmsg, 0);
   1.409 +            }
   1.410 +        }
   1.411 +    }
   1.412 +
   1.413 +  NotifyDataSent (packet_len);
   1.414 +  NS_LOG_INFO ("netlink socket kernel error " << -m_errno);
   1.415 +  return packet_len;
   1.416 +}
   1.417 +
   1.418 +int
   1.419 +NetlinkSocket::GetSockName (Address &address) const
   1.420 +{
   1.421 +  NS_LOG_FUNCTION_NOARGS ();
   1.422 +  NetlinkSocketAddress ad;
   1.423 +
   1.424 +  ad.SetProcessID (GetSrcPid ());
   1.425 +  ad.SetGroupsMask (GetSrcGroups ());
   1.426 +  address = ad;
   1.427 +  return 0;
   1.428 +}
   1.429 +int
   1.430 +NetlinkSocket::GetPeerName (Address &address) const
   1.431 +{
   1.432 +  NS_LOG_FUNCTION_NOARGS ();
   1.433 +  // XXX
   1.434 +  NS_ASSERT (false);
   1.435 +  return -1;
   1.436 +}
   1.437 +bool 
   1.438 +NetlinkSocket::SetAllowBroadcast (bool allowBroadcast)
   1.439 +{
   1.440 +  NS_ASSERT (false);
   1.441 +  return false;
   1.442 +}
   1.443 +bool 
   1.444 +NetlinkSocket::GetAllowBroadcast () const
   1.445 +{
   1.446 +  NS_ASSERT (false);
   1.447 +  return false;
   1.448 +}
   1.449 +
   1.450 +
   1.451 +void
   1.452 +NetlinkSocket::ForwardUp (Ptr<Packet> packet, NetlinkSocketAddress &address)
   1.453 +{
   1.454 +  NS_LOG_FUNCTION (this << packet << address);
   1.455 +
   1.456 +  if (m_shutdownRecv)
   1.457 +    {
   1.458 +      return;
   1.459 +    }
   1.460 +  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
   1.461 +    {
   1.462 +      SocketAddressTag tag;
   1.463 +      tag.SetAddress (address);
   1.464 +      packet->AddByteTag (tag);
   1.465 +      m_dataReceiveQueue.push (packet);
   1.466 +      m_rxAvailable += packet->GetSize ();
   1.467 +      NotifyDataRecv ();
   1.468 +    }
   1.469 +  else
   1.470 +    {
   1.471 +      NS_LOG_WARN ("No receive buffer space available.  Drop.");
   1.472 +      m_dropTrace (packet);
   1.473 +    }
   1.474 +}
   1.475 +
   1.476 +int32_t
   1.477 +NetlinkSocket::SendMessageUnicast (const MultipartNetlinkMessage &nlmsg, uint32_t pid, int32_t nonblock)
   1.478 +{
   1.479 +  NS_LOG_FUNCTION (this << pid << nonblock);
   1.480 +  //here we send message instantly
   1.481 +  Ptr<Packet> p = Create<Packet> ();
   1.482 +  p->AddHeader (nlmsg);
   1.483 +
   1.484 +  NetlinkSocketAddress address;
   1.485 +  address.SetProcessID (pid);
   1.486 +
   1.487 +  //send packet to user space
   1.488 +  ForwardUp (p, address);
   1.489 +  return 0;
   1.490 +}
   1.491 +int32_t
   1.492 +NetlinkSocket::SendMessageBroadcast (const MultipartNetlinkMessage &nlmsg, 
   1.493 +                                     uint32_t pid, 
   1.494 +                                     uint32_t group,
   1.495 +                                     Ptr<Node> node)
   1.496 +{
   1.497 +  NS_LOG_FUNCTION ("SendMessageBroadcast" << pid << group);
   1.498 +  //fisrt find the dest netlink socket through group value, then attach this nlmsg to its recv-queue
   1.499 +  for (uint32_t i = 0; i < GroupSockets::GetNSockets (); i ++)
   1.500 +    {
   1.501 +      Ptr<NetlinkSocket> nlsock = GroupSockets::GetSocket (i);
   1.502 +
   1.503 +      if ((nlsock->GetSrcGroups () & group) &&
   1.504 +          (nlsock->GetSrcPid () != pid) &&
   1.505 +          node == nlsock->GetNode ())
   1.506 +        {
   1.507 +          //here we send message instantly
   1.508 +          Ptr<Packet> p = Create<Packet> ();
   1.509 +          p->AddHeader (nlmsg);
   1.510 +
   1.511 +          NetlinkSocketAddress address;
   1.512 +          address.SetProcessID (nlsock->GetSrcPid());
   1.513 +          address.SetGroupsMask (group);
   1.514 +
   1.515 +          //send packet to user space
   1.516 +          nlsock->ForwardUp (p, address);
   1.517 +        }
   1.518 +    }
   1.519 +  return 0;
   1.520 +}
   1.521 +void
   1.522 +NetlinkSocket::SendAckMessage (const NetlinkMessage&nlmsg, int32_t err)
   1.523 +{
   1.524 +  NS_LOG_FUNCTION (this << err);
   1.525 +  NetlinkMessageHeader rep;
   1.526 +  NetlinkMessage ackmsg;
   1.527 +  NetlinkMessageError errmsg;
   1.528 +
   1.529 +  rep.SetMsgPid (nlmsg.GetHeader ().GetMsgPid ());
   1.530 +  rep.SetMsgSeq (nlmsg.GetHeader ().GetMsgSeq ());
   1.531 +  rep.SetMsgType (NETLINK_MSG_ERROR);
   1.532 +  rep.SetMsgFlags (0);
   1.533 +
   1.534 +  errmsg.SetError (err);
   1.535 +  //kernel send the whole nlmsg back if error != 0, here we just send the header back
   1.536 +  errmsg.SetMsg (nlmsg.GetHeader ());
   1.537 +
   1.538 +  //then send errmsg back to user space
   1.539 +  ackmsg.SetHeader (rep);
   1.540 +  ackmsg.SetErrorMessage (errmsg);
   1.541 +
   1.542 +  SendMessageUnicast (ackmsg, rep.GetMsgPid (), 1);
   1.543 +}
   1.544 +
   1.545 +int32_t
   1.546 +NetlinkSocket::HandleMessage (const NetlinkMessage&nlmsg)
   1.547 +{
   1.548 +  NS_LOG_FUNCTION (this);
   1.549 +  uint16_t type = nlmsg.GetMsgType ();
   1.550 +  NetlinkMessageHeader nhr = nlmsg.GetHeader ();
   1.551 +
   1.552 +  if (nhr.GetMsgLen () < NetlinkMessageHeader::GetHeaderSize ())
   1.553 +    {
   1.554 +      m_errno = ERROR_INVAL;
   1.555 +      return -1;
   1.556 +    }
   1.557 +
   1.558 +  if (NetlinkMessage::IsMessageNetlinkControl (type))
   1.559 +    {
   1.560 +      NS_LOG_INFO ("netlink control message type not parsed in kernel");
   1.561 +      return 0;
   1.562 +    }
   1.563 +  else if (NetlinkMessage::IsMessageNetlinkRoute (type))
   1.564 +    {
   1.565 +      return HandleNetlinkRouteMessage (nlmsg);
   1.566 +    }
   1.567 +  else
   1.568 +    {
   1.569 +      NS_LOG_INFO ("netlink message type not parsed in kernel");
   1.570 +      m_errno = ERROR_INVAL;
   1.571 +      return -1;
   1.572 +    }  
   1.573 +}
   1.574 +
   1.575 +int32_t
   1.576 +NetlinkSocket::HandleNetlinkRouteMessage (const NetlinkMessage &nlmsg)
   1.577 +{
   1.578 +  NS_LOG_FUNCTION (this);
   1.579 +  uint8_t family;
   1.580 +  int16_t type;
   1.581 +  int32_t err;
   1.582 +
   1.583 +  /* Only requests are handled by kernel now */
   1.584 +  if (!NetlinkMessage::IsMessageFlagsRequest (nlmsg.GetHeader ().GetMsgFlags ()))
   1.585 +    return 0;
   1.586 +
   1.587 +  type = nlmsg.GetMsgType ();
   1.588 +
   1.589 +  /* A control message: ignore them */
   1.590 +  if (NetlinkMessage::IsMessageNetlinkControl (type))
   1.591 +    {
   1.592 +      return 0;
   1.593 +    }
   1.594 +  else if (NetlinkMessage::IsMessageNetlinkRoute (type))
   1.595 +    {
   1.596 +      /* All the messages must have at least 1 byte length */
   1.597 +      if (nlmsg.GetPayloadSize () < 1)
   1.598 +        return 0;
   1.599 +
   1.600 +      family = nlmsg.GetFamily ();
   1.601 +      /*here we do not deal with different family, default for AF_NET*/
   1.602 +      NS_ASSERT(family == AF_INET || family == AF_UNSPEC || family == AF_PACKET || family == AF_INET6);  
   1.603 +
   1.604 +      /*for GET*** message, dump it to userspace*/
   1.605 +      if (NetlinkMessage::IsMessageTypeGet (type) && 
   1.606 +          NetlinkMessage::IsMessageFlagsDump (nlmsg.GetHeader ().GetMsgFlags ())) 
   1.607 +        {
   1.608 +          DumpNetlinkRouteMessage (nlmsg, type, family);
   1.609 +          return -1;
   1.610 +        }
   1.611 +
   1.612 +      /* other types of messages*/
   1.613 +      return DoNetlinkRouteMessage (nlmsg, type, family);
   1.614 +    }
   1.615 +  else/* Unknown message: reply with EINVAL */
   1.616 +    {
   1.617 +      err = ERROR_INVAL;
   1.618 +      return -1;
   1.619 +    } 
   1.620 +}
   1.621 +
   1.622 +int32_t
   1.623 +NetlinkSocket::DumpNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
   1.624 +{
   1.625 +  NS_LOG_FUNCTION (this << type << family);
   1.626 +
   1.627 +  NS_ASSERT (type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE || type == NETLINK_RTM_GETLINK);
   1.628 +
   1.629 +  MultipartNetlinkMessage nlmsg_dump;
   1.630 +  NetlinkMessageHeader nhr = nlmsg.GetHeader ();
   1.631 +  int32_t err;
   1.632 +
   1.633 +  if (type == NETLINK_RTM_GETADDR)
   1.634 +    {
   1.635 +      nlmsg_dump = BuildInterfaceAddressDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
   1.636 +    }
   1.637 +  else if (type == NETLINK_RTM_GETLINK)
   1.638 +    {
   1.639 +      nlmsg_dump = BuildInterfaceInfoDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);      
   1.640 +    }
   1.641 +  else if (type == NETLINK_RTM_GETROUTE)
   1.642 +    {
   1.643 +      nlmsg_dump = BuildRouteDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
   1.644 +    }
   1.645 +  else
   1.646 +    {
   1.647 +      m_errno = ERROR_INVAL;
   1.648 +      return -1;
   1.649 +    }
   1.650 +
   1.651 +  //then append netlink message with type NLMSG_DONE
   1.652 +  NetlinkMessage nlmsg_done;
   1.653 +  NetlinkMessageHeader nhr2 = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 
   1.654 +                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
   1.655 +  nlmsg_done.SetHeader (nhr2);
   1.656 +  //kernel append nlmsg_dump size to it, here we omit it
   1.657 +  nlmsg_dump.AppendMessage (nlmsg_done);
   1.658 +
   1.659 +  err = SendMessageUnicast (nlmsg_dump, m_srcPid, 1);
   1.660 +  return err;
   1.661 +}
   1.662 +
   1.663 +/*here only for ADD/DEL/GET*** types*/
   1.664 +int32_t
   1.665 +NetlinkSocket::DoNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
   1.666 +{
   1.667 +  NS_LOG_FUNCTION (this << type <<family);
   1.668 +  int32_t err;
   1.669 +
   1.670 +  if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
   1.671 +    {      
   1.672 +      err = DoInterfaceAddressMessage (nlmsg, type, family);
   1.673 +    }
   1.674 +  else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
   1.675 +    {     
   1.676 +      err = DoRouteMessage (nlmsg, type, family);
   1.677 +    }
   1.678 +  else if (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK)
   1.679 +    {     
   1.680 +      err = DoInterfaceInfoMessage (nlmsg, type, family);
   1.681 +    }
   1.682 +  else
   1.683 +    {
   1.684 +      NS_LOG_LOGIC ("netlink message:type( " << type << ") not processed by ns3 now." );
   1.685 +      m_errno = ERROR_INVAL;
   1.686 +      err = -1;
   1.687 +    } 
   1.688 +  
   1.689 +  return err;
   1.690 +}
   1.691 +
   1.692 +MultipartNetlinkMessage
   1.693 +NetlinkSocket::BuildInterfaceAddressDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
   1.694 +{
   1.695 +  NS_LOG_FUNCTION (this << pid << seq <<family);
   1.696 +  MultipartNetlinkMessage nlmsg_dump;
   1.697 +  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
   1.698 +
   1.699 +  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
   1.700 +    {
   1.701 +      if (!ipv4->IsUp (i))
   1.702 +        continue;
   1.703 +
   1.704 +      Ipv4Address addri = ipv4->GetAddress (i, 0).GetLocal ();
   1.705 +      Ipv4Mask maski = ipv4->GetAddress (i, 0).GetMask ();
   1.706 +      Ipv4Address bcast = ipv4->GetAddress (i, 0).GetBroadcast ();
   1.707 +
   1.708 +      //here get the address mask length
   1.709 +      uint32_t mask = maski.Get ();
   1.710 +      uint8_t mask_len = 0;
   1.711 +      while (mask)
   1.712 +        {
   1.713 +          mask = mask << 1;
   1.714 +          mask_len ++;
   1.715 +        }
   1.716 +      
   1.717 +      //next fill the message body
   1.718 +      NetlinkMessage nlmsg_ifa;
   1.719 +      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
   1.720 +      InterfaceAddressMessage ifamsg;
   1.721 +
   1.722 +      ifamsg.SetInterfaceIndex (i);
   1.723 +      ifamsg.SetFamily (AF_INET);//default AF_INET      
   1.724 +      ifamsg.SetLength (mask_len);
   1.725 +      ifamsg.SetFlags (0);
   1.726 +      ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
   1.727 +
   1.728 +      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addri));
   1.729 +      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addri));
   1.730 +      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
   1.731 +      //      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL,    STRING,  "ns3-ifaddr"));//not used in ns3
   1.732 +      //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST,  ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
   1.733 +      //XXXother attributes not used by ns3
   1.734 +
   1.735 +      nlmsg_ifa.SetHeader(nhr);
   1.736 +      nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
   1.737 +      nlmsg_dump.AppendMessage (nlmsg_ifa);
   1.738 +    }
   1.739 +
   1.740 +  // For IPv6
   1.741 +  Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
   1.742 +
   1.743 +  for (uint32_t i = 0; i < ipv6->GetNInterfaces(); i ++)
   1.744 +    {
   1.745 +      if (!ipv6->IsUp (i))
   1.746 +        continue;
   1.747 +
   1.748 +      for (uint32_t j = 0; j < ipv6->GetNAddresses(i); j ++)
   1.749 +        {
   1.750 +          Ipv6Address addri = ipv6->GetAddress (i, j).GetAddress();
   1.751 +          Ipv6Prefix prefix = ipv6->GetAddress (i, j).GetPrefix ();
   1.752 +
   1.753 +          //here get the address mask length
   1.754 +          uint8_t mask_len = prefix.GetPrefixLength();
   1.755 +
   1.756 +          //loopback address's prefix is wrong... FIXME
   1.757 +          if (addri.IsEqual(Ipv6Address::GetLoopback()))
   1.758 +            mask_len = 128;
   1.759 +      
   1.760 +          //next fill the message body
   1.761 +          NetlinkMessage nlmsg_ifa;
   1.762 +          NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
   1.763 +          InterfaceAddressMessage ifamsg;       
   1.764 +
   1.765 +          ifamsg.SetInterfaceIndex(i);
   1.766 +          ifamsg.SetFamily(AF_INET6);
   1.767 +          ifamsg.SetFlags(0);
   1.768 +
   1.769 +
   1.770 +          if (addri.IsLinkLocal())
   1.771 +            {
   1.772 +              ifamsg.SetLength(64);
   1.773 +              ifamsg.SetScope (RouteMessage::RT_SCOPE_LINK);
   1.774 +            }
   1.775 +          else
   1.776 +            {
   1.777 +              ifamsg.SetLength(mask_len);
   1.778 +              ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
   1.779 +            }
   1.780 +
   1.781 +
   1.782 +          ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addri));
   1.783 +          ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addri));
   1.784 +          //XXXother attributes not used by ns3
   1.785 +
   1.786 +          nlmsg_ifa.SetHeader(nhr);
   1.787 +          nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
   1.788 +          nlmsg_dump.AppendMessage (nlmsg_ifa);
   1.789 +        }
   1.790 +    }
   1.791 +  return nlmsg_dump;
   1.792 +}
   1.793 +MultipartNetlinkMessage
   1.794 +NetlinkSocket::BuildInterfaceInfoDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
   1.795 +{
   1.796 +  NS_LOG_FUNCTION (this << pid << seq <<family);
   1.797 +  MultipartNetlinkMessage nlmsg_dump;
   1.798 +  for (uint32_t i = 0; i < m_node->GetNDevices (); i ++)
   1.799 +    {
   1.800 +      Ptr<NetDevice> dev = m_node->GetDevice (i);
   1.801 +      Address mac;
   1.802 +      Address bcast;
   1.803 +      uint32_t mtu;
   1.804 +      uint32_t flags = 0;
   1.805 +
   1.806 +      mac = dev->GetAddress ();
   1.807 +      bcast = dev->GetBroadcast ();
   1.808 +      mtu = (uint32_t)dev->GetMtu ();
   1.809 +
   1.810 +      if (dev->IsLinkUp ())
   1.811 +        {
   1.812 +          flags |= IFF_RUNNING;
   1.813 +          flags |= IFF_UP;
   1.814 +        }
   1.815 +      if (dev->IsBroadcast ())
   1.816 +        {
   1.817 +          flags |= IFF_BROADCAST;
   1.818 +        }
   1.819 +      if (dev->IsMulticast ())
   1.820 +        {
   1.821 +          flags |= IFF_MULTICAST;
   1.822 +        }
   1.823 +
   1.824 +      NetlinkMessage nlmsg_ifinfo;
   1.825 +      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWLINK, NETLINK_MSG_F_MULTI, seq, pid);
   1.826 +      InterfaceInfoMessage ifinfomsg;     
   1.827 +
   1.828 +      ifinfomsg.SetFamily(0);      // AF_UNSPEC
   1.829 +      ifinfomsg.SetDeviceType (0); // not clear
   1.830 +      ifinfomsg.SetInterfaceIndex (i);
   1.831 +      ifinfomsg.SetDeviceFlags (flags); // not clear
   1.832 +      ifinfomsg.SetChangeMask (0xffffffff);
   1.833 +
   1.834 +      // the ns3 device have no  name, here we set "ns3-device i" for test
   1.835 +      std::stringstream ss;
   1.836 +      ss <<  "ns3-device" << i;
   1.837 +
   1.838 +      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_IFNAME,    STRING,  ss.str()));
   1.839 +      //not used in ns3
   1.840 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_TXQLEN,    U32,     0));
   1.841 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_WEIGHT,    U32,     0));
   1.842 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_OPERSTATE, U8,      0));
   1.843 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINKMODE,  U8,      0));
   1.844 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MAP,       UNSPEC,  0));
   1.845 +      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_ADDRESS,   ADDRESS, mac));
   1.846 +      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_BROADCAST, ADDRESS, bcast));
   1.847 +      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MTU,       U32,     mtu));
   1.848 +      ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINK,      U32,     i));
   1.849 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_QDISC,     STRING,  ""));
   1.850 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MASTER,    U32,     0));
   1.851 +      //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_STATS,     UNSPEC,  0));
   1.852 +
   1.853 +      nlmsg_ifinfo.SetHeader (nhr);
   1.854 +      nlmsg_ifinfo.SetInterfaceInfoMessage (ifinfomsg);
   1.855 +      nlmsg_dump.AppendMessage (nlmsg_ifinfo);
   1.856 +    }
   1.857 +  return nlmsg_dump;
   1.858 +}
   1.859 +MultipartNetlinkMessage
   1.860 +NetlinkSocket::BuildRouteDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
   1.861 +{
   1.862 +  NS_LOG_FUNCTION (this << pid << seq <<family);
   1.863 +  MultipartNetlinkMessage nlmsg_dump;
   1.864 +  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
   1.865 +
   1.866 +  // We only care about staticRouting for netlink support
   1.867 +  Ipv4StaticRoutingHelper routingHelper;
   1.868 +  Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
   1.869 +  for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
   1.870 +    {
   1.871 +      NetlinkMessage nlmsg_rt;
   1.872 +      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
   1.873 +      RouteMessage rtmsg;
   1.874 +      Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
   1.875 +
   1.876 +      rtmsg.SetFamily (AF_INET);
   1.877 +      rtmsg.SetDstLength (32);
   1.878 +      rtmsg.SetSrcLength (0);
   1.879 +      rtmsg.SetTos (0);//not clear
   1.880 +      rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
   1.881 +      rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
   1.882 +      rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
   1.883 +      rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
   1.884 +
   1.885 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
   1.886 +      // ns3 use local address as the route src address
   1.887 +      //      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, route.GetSource()));
   1.888 +      //      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, route.GetSource()));//not used in ns3
   1.889 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
   1.890 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));      
   1.891 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
   1.892 +
   1.893 +      nlmsg_rt.SetHeader (nhr);
   1.894 +      nlmsg_rt.SetRouteMessage (rtmsg);
   1.895 +      nlmsg_dump.AppendMessage (nlmsg_rt);
   1.896 +    }
   1.897 +
   1.898 +  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
   1.899 +  // We only care about staticRouting for netlink support
   1.900 +  Ipv6StaticRoutingHelper routingHelper6;
   1.901 +  Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
   1.902 +  for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
   1.903 +    {
   1.904 +      NetlinkMessage nlmsg_rt;
   1.905 +      NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
   1.906 +      RouteMessage rtmsg;
   1.907 +      Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
   1.908 +
   1.909 +      rtmsg.SetFamily (AF_INET6);
   1.910 +      rtmsg.SetDstLength (128);
   1.911 +      rtmsg.SetSrcLength (0);
   1.912 +      rtmsg.SetTos (0);//not clear
   1.913 +      rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
   1.914 +      rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
   1.915 +      rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
   1.916 +      rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
   1.917 +
   1.918 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
   1.919 +      //ns3 use local address as the route src address
   1.920 +      // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, 
   1.921 +      //                                          ipv6->GetSourceAddress(route.GetDest ())));
   1.922 +      // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, 
   1.923 +      //                                          ipv6->GetSourceAddress(route.GetDest ())));
   1.924 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
   1.925 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));      
   1.926 +      rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
   1.927 +
   1.928 +      nlmsg_rt.SetHeader (nhr);
   1.929 +      nlmsg_rt.SetRouteMessage (rtmsg);
   1.930 +      nlmsg_dump.AppendMessage (nlmsg_rt);
   1.931 +    }
   1.932 +
   1.933 +  return nlmsg_dump;
   1.934 +}
   1.935 +
   1.936 +int32_t
   1.937 +NetlinkSocket::DoInterfaceAddressMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
   1.938 +{
   1.939 +  NS_LOG_FUNCTION (this << type << family);
   1.940 +  NS_ASSERT (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
   1.941 +
   1.942 +  // XXX
   1.943 +  NS_ASSERT_MSG (false, "Not implemented yet (RTM_NEWADDR/RTM_DELADDR)");
   1.944 +
   1.945 +  InterfaceAddressMessage ifamsg = nlmsg.GetInterfaceAddressMessage ();
   1.946 +  Ipv4Address addri, addr_local, bcast;
   1.947 +  NetlinkAttribute attr_local;
   1.948 +  uint32_t index = ifamsg.GetInterfaceIndex ();
   1.949 +  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
   1.950 +  int flag4 = 0, flag6 = 0;
   1.951 +
   1.952 +  if (type == NETLINK_RTM_NEWADDR)
   1.953 +    {
   1.954 +      //when adding an interface address, it should check the input arguments
   1.955 +      //prefix-len and local address attribute
   1.956 +      if (ifamsg.GetLength () > 32 || 
   1.957 +          ifamsg.GetAttributeByType (attr_local, InterfaceAddressMessage::IF_A_LOCAL) == false)
   1.958 +        {
   1.959 +          m_errno = ERROR_INVAL;
   1.960 +          return -1;
   1.961 +        }
   1.962 +    }  
   1.963 +
   1.964 +  //get necessary information for add/del, many attributes we not used
   1.965 +  for (uint32_t i = 0; i < ifamsg.GetNNetlinkAttribute (); i ++)
   1.966 +    {
   1.967 +      NetlinkAttribute attr = ifamsg.GetNetlinkAttribute (i);
   1.968 +      uint32_t attr_type = attr.GetAttrType ();
   1.969 +
   1.970 +      switch(attr_type)
   1.971 +        {
   1.972 +        case InterfaceAddressMessage::IF_A_ADDRESS:
   1.973 +          addri = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
   1.974 +          break;
   1.975 +        case InterfaceAddressMessage::IF_A_BROADCAST:
   1.976 +          bcast = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
   1.977 +          break;
   1.978 +        case InterfaceAddressMessage::IF_A_LOCAL:
   1.979 +          addr_local = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
   1.980 +          break;
   1.981 +        case InterfaceAddressMessage::IF_A_LABEL:
   1.982 +        case InterfaceAddressMessage::IF_A_ANYCAST:
   1.983 +          break;
   1.984 +        }
   1.985 +    }
   1.986 +
   1.987 +  if (type == NETLINK_RTM_NEWADDR)
   1.988 +    {
   1.989 +      //when adding an interface address by index, if the indexed interface was not exist,
   1.990 +      //create an new NetDevice with an new index and set the address
   1.991 +      //otherwise set the indexed interface directly
   1.992 +      if (index >= ipv4->GetNInterfaces ())
   1.993 +        {          
   1.994 +          Ptr<SimpleNetDevice> dev;
   1.995 +          dev = CreateObject<SimpleNetDevice> ();
   1.996 +          dev ->SetAddress (Mac48Address::Allocate ());
   1.997 +          m_node->AddDevice (dev);
   1.998 +
   1.999 +          uint32_t netdev_idx = ipv4->AddInterface (dev);
  1.1000 +          // FIXME!
  1.1001 +          Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
  1.1002 +          ipv4->AddAddress (netdev_idx, ipv4Addr);
  1.1003 +          ipv4->SetUp (netdev_idx);
  1.1004 +          NS_LOG_INFO ("Add an interface address at index "<< netdev_idx << "but not the ifamsg input" << index);
  1.1005 +        }
  1.1006 +      else
  1.1007 +        {
  1.1008 +          Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
  1.1009 +          ipv4->AddAddress (index, ipv4Addr);
  1.1010 +          if (!ipv4->IsUp (index))
  1.1011 +            ipv4->SetUp (index);
  1.1012 +        }    
  1.1013 +      flag4 = 1;
  1.1014 +    }
  1.1015 +  else//type == NETLINK_RTM_DELADDR
  1.1016 +    {
  1.1017 +      //when delete an interface address by index, if the indexed interface  was not exist
  1.1018 +      //return an error EINVAL, otherwise set down the interface which has the addri
  1.1019 +      if (index >= ipv4->GetNInterfaces ())
  1.1020 +        {
  1.1021 +          m_errno = ERROR_NODEV;
  1.1022 +          return -1;
  1.1023 +        }
  1.1024 +      else
  1.1025 +        {
  1.1026 +          for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
  1.1027 +            {
  1.1028 +              Ipv4Address ad = ipv4->GetAddress (i, 0).GetLocal ();
  1.1029 +              if (ad == addri && ipv4->IsUp (i))
  1.1030 +                {
  1.1031 +                  ipv4->SetDown (i);
  1.1032 +                  break;
  1.1033 +                }
  1.1034 +              if (i == ipv4->GetNInterfaces () - 1)
  1.1035 +                {
  1.1036 +                  m_errno = ERROR_ADDRNOTAVAIL;
  1.1037 +                  return -1;
  1.1038 +                }
  1.1039 +            }
  1.1040 +          flag4 = 1;
  1.1041 +        }      
  1.1042 +    }
  1.1043 +  
  1.1044 +  //then send an broadcast message, let all user know this operation happened
  1.1045 +  NetlinkMessage nlmsg_broadcast = nlmsg;
  1.1046 +  NetlinkMessageHeader nhr;
  1.1047 +  nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
  1.1048 +  nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
  1.1049 +  nlmsg_broadcast.SetHeader (nhr);
  1.1050 +  if (flag4)
  1.1051 +    {
  1.1052 +      SendMessageBroadcast (nlmsg_broadcast, 0, NETLINK_RTM_GRP_IPV4_IFADDR, GetNode ());
  1.1053 +    }
  1.1054 +  else if (flag6)
  1.1055 +    {
  1.1056 +      SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_IFADDR, GetNode ());
  1.1057 +    }
  1.1058 +
  1.1059 +  return 0;
  1.1060 +}
  1.1061 +
  1.1062 +int32_t
  1.1063 +NetlinkSocket::DoInterfaceInfoMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
  1.1064 +{
  1.1065 +  NS_LOG_FUNCTION (this << type << family);
  1.1066 +  NS_ASSERT (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK);
  1.1067 +  InterfaceInfoMessage ifinfomsg = nlmsg.GetInterfaceInfoMessage ();
  1.1068 +  // XXX
  1.1069 +  NS_ASSERT_MSG (false, "Not implemented yet (RTM_GETLINK/RTM_SETLINK)");
  1.1070 +  return -1;
  1.1071 +}
  1.1072 +
  1.1073 +Address
  1.1074 +NetlinkSocket::ConvertFrom (uint8_t family, const Address &address)
  1.1075 +{
  1.1076 +  Address retval;
  1.1077 +  if (family == AF_INET)
  1.1078 +    {
  1.1079 +      retval = Ipv4Address::ConvertFrom (address);
  1.1080 +    }
  1.1081 +  else if (family == AF_INET6)
  1.1082 +    {
  1.1083 +      retval = Ipv6Address::ConvertFrom (address);
  1.1084 +    }
  1.1085 +  return retval;
  1.1086 +}
  1.1087 +
  1.1088 +int32_t
  1.1089 +NetlinkSocket::DoRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
  1.1090 +{
  1.1091 +  NS_LOG_FUNCTION (this << type << family);
  1.1092 +  NS_ASSERT (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE ||type == NETLINK_RTM_GETROUTE);
  1.1093 +
  1.1094 +  RouteMessage rtmsg = nlmsg.GetRouteMessage ();
  1.1095 +  Ipv4Address src, dest, gateway;
  1.1096 +  Ipv6Address src6, dest6, gateway6;
  1.1097 +  uint32_t index = 0;
  1.1098 +  int attr_flags[RouteMessage::RT_A_MAX] = {0};
  1.1099 +  uint8_t dstlen = rtmsg.GetDstLength ();
  1.1100 +
  1.1101 +  //get necessary information for add/del, many attributes we not used
  1.1102 +  for (uint32_t i = 0; i < rtmsg.GetNNetlinkAttribute (); i ++)
  1.1103 +    {
  1.1104 +      NetlinkAttribute attr = rtmsg.GetNetlinkAttribute (i);
  1.1105 +      uint32_t attr_type = attr.GetAttrType ();
  1.1106 +      attr_flags[attr_type] = 1;
  1.1107 +
  1.1108 +      switch(attr_type)
  1.1109 +        {
  1.1110 +        case RouteMessage::RT_A_DST:
  1.1111 +          if (family == AF_INET)
  1.1112 +            {
  1.1113 +              dest = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1114 +            }
  1.1115 +          else if (family == AF_INET6)
  1.1116 +            {
  1.1117 +              dest6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1118 +            }
  1.1119 +          break;
  1.1120 +        case RouteMessage::RT_A_SRC:
  1.1121 +          if (family == AF_INET)
  1.1122 +            {
  1.1123 +              src = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1124 +            }
  1.1125 +          else if (family == AF_INET6)
  1.1126 +            {
  1.1127 +              src6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1128 +            }
  1.1129 +          break;
  1.1130 +        case RouteMessage::RT_A_OIF:
  1.1131 +          index = attr.GetAttrPayload ().GetU32 ();
  1.1132 +          break;
  1.1133 +        case RouteMessage::RT_A_GATEWAY:
  1.1134 +          if (family == AF_INET)
  1.1135 +            {
  1.1136 +              gateway = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1137 +            }
  1.1138 +          else if (family == AF_INET6)
  1.1139 +            {
  1.1140 +              gateway6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
  1.1141 +            }
  1.1142 +          break;
  1.1143 +        case RouteMessage::RT_A_IIF:
  1.1144 +        case RouteMessage::RT_A_PRIORITY:
  1.1145 +        case RouteMessage::RT_A_PREFSRC:
  1.1146 +        case RouteMessage::RT_A_METRICS:
  1.1147 +        case RouteMessage::RT_A_MULTIPATH:
  1.1148 +        case RouteMessage::RT_A_PROTOINFO:
  1.1149 +        case RouteMessage::RT_A_FLOW:
  1.1150 +        case RouteMessage::RT_A_CACHEINFO:
  1.1151 +        case RouteMessage::RT_A_SESSION:
  1.1152 +        case RouteMessage::RT_A_MP_ALGO:
  1.1153 +        case RouteMessage::RT_A_TABLE:
  1.1154 +          NS_LOG_INFO("route attribute not used by ns3" << attr_type);
  1.1155 +          //not used by ns3
  1.1156 +          break;
  1.1157 +        }
  1.1158 +    }
  1.1159 +
  1.1160 +  // Sigh....
  1.1161 +  Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
  1.1162 +  Ipv4StaticRoutingHelper routingHelper;
  1.1163 +  Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
  1.1164 +
  1.1165 +  Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
  1.1166 +  Ipv6StaticRoutingHelper routingHelper6;
  1.1167 +  Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
  1.1168 +
  1.1169 +  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Route message, type: " << type << "; from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
  1.1170 +      << " to " << dest<< " through " << gateway);
  1.1171 +
  1.1172 +  if (type == NETLINK_RTM_NEWROUTE)
  1.1173 +    {
  1.1174 +      //ns3 add a route entry only depends on 2 or 3 attribute
  1.1175 +      //other route msg attibute were ignored
  1.1176 +      if (attr_flags[RouteMessage::RT_A_DST])
  1.1177 +        {
  1.1178 +          if (family == AF_INET)
  1.1179 +            {
  1.1180 +              if (!attr_flags[RouteMessage::RT_A_OIF])
  1.1181 +                {
  1.1182 +                  bool found = 0;
  1.1183 +                  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
  1.1184 +                    {
  1.1185 +                      for (uint32_t j = 0; j < ipv4->GetNAddresses (i); j++)
  1.1186 +                        {
  1.1187 +                          if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
  1.1188 +                            {
  1.1189 +                              Ipv4Mask mask = ipv4->GetAddress (i, j).GetMask ();
  1.1190 +                              if (mask.IsMatch (ipv4->GetAddress (i, j).GetLocal (), gateway))
  1.1191 +                                {
  1.1192 +                                  index = i;
  1.1193 +                                  found = true;
  1.1194 +                                  break;
  1.1195 +                                }
  1.1196 +                            }
  1.1197 +                          if (found) break;
  1.1198 +                        }
  1.1199 +                    }
  1.1200 +                  if (!found)
  1.1201 +                    {
  1.1202 +                      NS_LOG_DEBUG ("No suitable interface to add an route entry");
  1.1203 +                      m_errno = ERROR_ADDRNOTAVAIL;
  1.1204 +                      return -1;
  1.1205 +                    }
  1.1206 +                }
  1.1207 +            if (dstlen == 32)
  1.1208 +              {
  1.1209 +                int exist_flag = 0;
  1.1210 +                for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
  1.1211 +                  {
  1.1212 +                    Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
  1.1213 +                    if (dest == rt.GetDest ())
  1.1214 +                      {
  1.1215 +                        exist_flag = 1;
  1.1216 +                      }
  1.1217 +                  }
  1.1218 +
  1.1219 +                if (exist_flag)
  1.1220 +                  { //route to dest already exists
  1.1221 +                    int delete_flag = 0;
  1.1222 +                    if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_REPLACE)
  1.1223 +                      {
  1.1224 +                        for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
  1.1225 +                          {
  1.1226 +                            Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
  1.1227 +                            if (dest == rt.GetDest ())
  1.1228 +                              {
  1.1229 +                                ipv4Static->RemoveRoute (i);
  1.1230 +                                NS_LOG_DEBUG ("Route from  " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to "
  1.1231 +                                    << dest << " through " << gateway << " removed");
  1.1232 +                                delete_flag = 1;
  1.1233 +                              }
  1.1234 +                          }
  1.1235 +
  1.1236 +                        if (!delete_flag)
  1.1237 +                          {
  1.1238 +                             NS_LOG_INFO ("no route entry removed by dest address in new route sector " << dest);
  1.1239 +                             m_errno = ERROR_INVAL;
  1.1240 +                             return -1;
  1.1241 +                           }
  1.1242 +                      }
  1.1243 +                    else
  1.1244 +                      {
  1.1245 +                        NS_LOG_DEBUG ("Route exists but overwriting declined!");
  1.1246 +                      }
  1.1247 +                    if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
  1.1248 +                      {
  1.1249 +                        NS_LOG_DEBUG (Simulator::Now().GetSeconds() << "Overwrite route from "
  1.1250 +                            << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest<< " through " << gateway << " with index" << index);
  1.1251 +                        ipv4Static->AddHostRouteTo (dest, gateway, index);
  1.1252 +                      }
  1.1253 +                    else
  1.1254 +                      {
  1.1255 +                        NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Overwrite route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
  1.1256 +                            << " to " << dest<< " through " << "self" << " with index" << index);
  1.1257 +                        ipv4Static->AddHostRouteTo (dest, index);
  1.1258 +                      }
  1.1259 +                }
  1.1260 +                else
  1.1261 +                  { //route to dest doesn't exist
  1.1262 +                    if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_CREATE)
  1.1263 +                      {
  1.1264 +                        if (attr_flags[RouteMessage::RT_A_GATEWAY])
  1.1265 +                          {
  1.1266 +                            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
  1.1267 +                                << " to " << dest<< " through " << gateway << " with index" << index);
  1.1268 +                            ipv4Static->AddHostRouteTo (dest, gateway, index);
  1.1269 +                          }
  1.1270 +                        else
  1.1271 +                          {
  1.1272 +                            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
  1.1273 +                                << " to " << dest<< " through " << "self" << " with index" << index);
  1.1274 +                            ipv4Static->AddHostRouteTo (dest, index);
  1.1275 +                          }
  1.1276 +                      }
  1.1277 +                    else
  1.1278 +                      {
  1.1279 +                        NS_LOG_ERROR ("Route doesn't exist but writing declined!");
  1.1280 +                      }
  1.1281 +                  }
  1.1282 +
  1.1283 +                NS_LOG_DEBUG ("=After change attempt=");
  1.1284 +                //Dump of table
  1.1285 +                NS_LOG_DEBUG (m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << ":");
  1.1286 +                for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
  1.1287 +                  {
  1.1288 +                    Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
  1.1289 +                    NS_LOG_DEBUG (rt.GetDest () << " through " << rt.GetGateway ());
  1.1290 +                  }
  1.1291 +                NS_LOG_DEBUG ("= = = = = = = = = = =");
  1.1292 +              }
  1.1293 +            else // dstlen != 32
  1.1294 +              {
  1.1295 +                if (attr_flags[RouteMessage::RT_A_GATEWAY])
  1.1296 +                  {
  1.1297 +                    ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), gateway, index);
  1.1298 +                  }
  1.1299 +                else
  1.1300 +                  {
  1.1301 +                    ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), index);
  1.1302 +                  }
  1.1303 +              }
  1.1304 +          }
  1.1305 +          else if (family == AF_INET6)
  1.1306 +            {
  1.1307 +            if (!attr_flags[RouteMessage::RT_A_OIF])
  1.1308 +              {
  1.1309 +#ifdef FIXME
  1.1310 +              if (ipv6->GetIfIndexForDestination (gateway6, index) == false)
  1.1311 +                {
  1.1312 +                  NS_LOG_INFO ("No suitable interface to add an route entry");
  1.1313 +                  m_errno = ERROR_ADDRNOTAVAIL;
  1.1314 +                  return -1;
  1.1315 +                }
  1.1316 +#endif
  1.1317 +              }
  1.1318 +
  1.1319 +            Ipv6Prefix pref (dstlen);
  1.1320 +            if (attr_flags[RouteMessage::RT_A_GATEWAY])
  1.1321 +              {
  1.1322 +                ipv6Static->AddNetworkRouteTo (dest6, pref, gateway6, index);
  1.1323 +              }
  1.1324 +            else
  1.1325 +              {
  1.1326 +                ipv6Static->AddNetworkRouteTo (dest6, pref, Ipv6Address("::"), index);
  1.1327 +              }
  1.1328 +            }
  1.1329 +          }
  1.1330 +        else
  1.1331 +          {
  1.1332 +            NS_LOG_INFO("too few attributes to add an route entry");
  1.1333 +            m_errno = ERROR_INVAL;
  1.1334 +            return -1;
  1.1335 +          }
  1.1336 +    }
  1.1337 +  else if (type == NETLINK_RTM_DELROUTE)
  1.1338 +    {
  1.1339 +      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Route delete request from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
  1.1340 +          << " to " << dest<< " through " << gateway);
  1.1341 +      if (attr_flags[RouteMessage::RT_A_DST])
  1.1342 +        {
  1.1343 +          int delete_flag = 0;
  1.1344 +
  1.1345 +          if (family == AF_INET)
  1.1346 +            {
  1.1347 +              for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
  1.1348 +                {
  1.1349 +                Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
  1.1350 +                if (gateway == rt.GetGateway () && dest == rt.GetDest ())
  1.1351 +                  {
  1.1352 +                    ipv4Static->RemoveRoute (i);
  1.1353 +                    delete_flag = 1;
  1.1354 +                  }
  1.1355 +                }
  1.1356 +            }
  1.1357 +          else if (family == AF_INET6)
  1.1358 +            {
  1.1359 +              for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
  1.1360 +                {
  1.1361 +                Ipv6RoutingTableEntry rt = ipv6Static->GetRoute (i);
  1.1362 +                if (gateway6 == rt.GetGateway () && dest6 == rt.GetDest ())
  1.1363 +                  {
  1.1364 +                    ipv6Static->RemoveRoute (i);
  1.1365 +                    delete_flag = 1;
  1.1366 +                  }
  1.1367 +                }
  1.1368 +            }
  1.1369 +
  1.1370 +          if (!delete_flag)
  1.1371 +            {
  1.1372 +              NS_LOG_INFO ("no route entry removed by dest address " << dest);
  1.1373 +              m_errno = ERROR_INVAL;
  1.1374 +              return -1;
  1.1375 +            }
  1.1376 +        }
  1.1377 +      else
  1.1378 +        {
  1.1379 +          NS_LOG_INFO ("too few attributes to add an route entry");
  1.1380 +          m_errno = ERROR_INVAL;
  1.1381 +          return -1;    
  1.1382 +        }
  1.1383 +    }
  1.1384 +  else// type == NETLINK_RTM_GETROUTE
  1.1385 +    {
  1.1386 +      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "GetRoute "<< "from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest);
  1.1387 +      if (!attr_flags[RouteMessage::RT_A_DST])
  1.1388 +        {
  1.1389 +          NS_LOG_INFO ("too few attributes to get an route entry");
  1.1390 +          m_errno = ERROR_INVAL;
  1.1391 +          return -1;
  1.1392 +        }
  1.1393 +      
  1.1394 +      int get_flag = 0;
  1.1395 +      if (family == AF_INET)
  1.1396 +        {
  1.1397 +          for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
  1.1398 +            {
  1.1399 +              Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
  1.1400 +              //find the route entry with same dest address and send unicast to user space
  1.1401 +              if (dest.IsEqual (route.GetDest ()))
  1.1402 +                {
  1.1403 +                  //                Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
  1.1404 +                  NetlinkMessage nlmsg_route;
  1.1405 +                  NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0, 
  1.1406 +                                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
  1.1407 +                  RouteMessage rtmsg;
  1.1408 +
  1.1409 +                  //fill rtmsg and attributes
  1.1410 +                  rtmsg.SetFamily (AF_INET);
  1.1411 +                  rtmsg.SetDstLength (32);
  1.1412 +                  rtmsg.SetSrcLength (0);
  1.1413 +                  rtmsg.SetTos (0);//not clear
  1.1414 +                  rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
  1.1415 +                  rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
  1.1416 +                  rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
  1.1417 +                  rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
  1.1418 +
  1.1419 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
  1.1420 +                  //ns3 use local address as the route src address
  1.1421 +                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
  1.1422 +                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
  1.1423 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
  1.1424 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
  1.1425 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
  1.1426 +
  1.1427 +                  //fill an netlink message body
  1.1428 +                  nlmsg_route.SetHeader (nhr);
  1.1429 +                  nlmsg_route.SetRouteMessage (rtmsg);
  1.1430 +                  
  1.1431 +                  SendMessageUnicast (nlmsg_route, m_srcPid, 1);
  1.1432 +                  get_flag = 1;
  1.1433 +                }
  1.1434 +            }
  1.1435 +        }
  1.1436 +      else if (family == AF_INET6)
  1.1437 +        {
  1.1438 +          for (uint32_t i = 0; i < ipv6Static->GetNRoutes(); i ++)
  1.1439 +            {
  1.1440 +              Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
  1.1441 +              //find the route entry with same dest address and send unicast to user space
  1.1442 +              if (dest6.IsEqual (route.GetDest ()))
  1.1443 +                {
  1.1444 +                  NetlinkMessage nlmsg_route;
  1.1445 +                  NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0, 
  1.1446 +                                                                   nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
  1.1447 +                  RouteMessage rtmsg;
  1.1448 +
  1.1449 +                  //fill rtmsg and attributes
  1.1450 +                  rtmsg.SetFamily (AF_INET6);
  1.1451 +                  rtmsg.SetDstLength (32);
  1.1452 +                  rtmsg.SetSrcLength (0);
  1.1453 +                  rtmsg.SetTos (0);//not clear
  1.1454 +                  rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
  1.1455 +                  rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
  1.1456 +                  rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
  1.1457 +                  rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
  1.1458 +
  1.1459 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
  1.1460 +                  //ns3 use local address as the route src address
  1.1461 +                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
  1.1462 +                  // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
  1.1463 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
  1.1464 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
  1.1465 +                  rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
  1.1466 +
  1.1467 +                  //fill an netlink message body
  1.1468 +                  nlmsg_route.SetHeader (nhr);
  1.1469 +                  nlmsg_route.SetRouteMessage (rtmsg);
  1.1470 +
  1.1471 +                  SendMessageUnicast (nlmsg_route, m_srcPid, 1);
  1.1472 +                  get_flag = 1;
  1.1473 +                }
  1.1474 +            }
  1.1475 +        }
  1.1476 +      
  1.1477 +      if (!get_flag)
  1.1478 +        {
  1.1479 +          NS_LOG_INFO ("no route entry exist by dest address" << dest);
  1.1480 +          m_errno = ERROR_INVAL;
  1.1481 +          return -1;
  1.1482 +        }
  1.1483 +    }
  1.1484 +
  1.1485 +  //then send an broadcast message, let all user know this operation happened
  1.1486 +  MultipartNetlinkMessage nlmsg_multi;
  1.1487 +  NetlinkMessage nlmsg_broadcast = nlmsg;
  1.1488 +  NetlinkMessage nlmsg_done;
  1.1489 +  NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
  1.1490 +  nlmsg_done.SetHeader (nhr_done);
  1.1491 +  nlmsg_multi.AppendMessage (nlmsg);
  1.1492 +  nlmsg_multi.AppendMessage (nlmsg_done);
  1.1493 +  SendMessageBroadcast (nlmsg_multi, 0, NETLINK_RTM_GRP_IPV4_ROUTE, GetNode ());
  1.1494 +  //   SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
  1.1495 +  return 0;
  1.1496 +}
  1.1497 +
  1.1498 +int32_t
  1.1499 +NetlinkSocket::NotifyIfLinkMessage (Address address, uint16_t type, uint8_t family)
  1.1500 +{
  1.1501 +  NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfLinkMessage)");
  1.1502 +  return 0;
  1.1503 +}
  1.1504 +
  1.1505 +int32_t
  1.1506 +NetlinkSocket::NotifyIfAddrMessage (Ipv6Interface* interface, Ipv6Address addr, int cmd)
  1.1507 +{
  1.1508 +  MultipartNetlinkMessage nlmsg_multi;
  1.1509 +  NetlinkMessage nlmsg_ifa;
  1.1510 +  NetlinkMessageHeader nhr = NetlinkMessageHeader (cmd, NETLINK_MSG_F_MULTI, 0, 0);
  1.1511 +  InterfaceAddressMessage ifamsg;
  1.1512 +
  1.1513 +  NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfAddrMessage)");
  1.1514 +
  1.1515 +  // FIXME!
  1.1516 +  Ipv6Prefix prefix = Ipv6Prefix(64);
  1.1517 +
  1.1518 +  //here get the address mask length
  1.1519 +  uint8_t bytes[16];
  1.1520 +  prefix.GetBytes (bytes);
  1.1521 +  uint8_t mask_len = 0;
  1.1522 +  for (int j = 0; j < 16; j++)
  1.1523 +    {
  1.1524 +      while (bytes[j])
  1.1525 +        {
  1.1526 +          bytes[j] = bytes[j] << 1;
  1.1527 +          mask_len ++;
  1.1528 +        }
  1.1529 +    }
  1.1530 +      
  1.1531 +  ifamsg.SetInterfaceIndex (interface->GetDevice ()->GetIfIndex ());
  1.1532 +  ifamsg.SetFamily (AF_INET6);
  1.1533 +  ifamsg.SetLength (mask_len);
  1.1534 +  ifamsg.SetFlags (0);
  1.1535 +  ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
  1.1536 +
  1.1537 +  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL,    ADDRESS, addr));
  1.1538 +  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,  ADDRESS, addr));
  1.1539 +  //  ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
  1.1540 +  //      ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL,    STRING,  "ns3-ifaddr"));//not used in ns3
  1.1541 +  //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST,  ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
  1.1542 +  //XXXother attributes not used by ns3
  1.1543 +
  1.1544 +  nlmsg_ifa.SetHeader (nhr);
  1.1545 +  nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
  1.1546 +
  1.1547 +  NetlinkMessage nlmsg_done;
  1.1548 +  NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
  1.1549 +  nlmsg_done.SetHeader (nhr_done);
  1.1550 +
  1.1551 +  nlmsg_multi.AppendMessage (nlmsg_ifa);
  1.1552 +  nlmsg_multi.AppendMessage (nlmsg_done);
  1.1553 +
  1.1554 +  SendMessageBroadcast (nlmsg_multi, 0, RTMGRP_IPV6_IFADDR, interface->GetDevice ()->GetNode ());  
  1.1555 +  return 0;
  1.1556 +}
  1.1557 +
  1.1558 +#ifdef FIXME
  1.1559 +int32_t
  1.1560 +NetlinkSocket::NotifyRouteMessage(Ojbect route, uint16_t type, uint8_t family)
  1.1561 +{
  1.1562 +  NetlinkMessage nlmsg_broadcast = nlmsg;
  1.1563 +  NetlinkMessageHeader nhr;
  1.1564 +  NS_ASSERT_MSG (false, "Not implemented yet");
  1.1565 +
  1.1566 +  nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
  1.1567 +  nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
  1.1568 +  nlmsg_broadcast.SetHeader (nhr);
  1.1569 +  SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
  1.1570 +  return 0;
  1.1571 +}
  1.1572 +#endif
  1.1573 +
  1.1574 +}//namespace ns3