Re: Code working with LIBNET_RAW4, not with LIBNET_LINK

Mike Schiffman <[email protected]> Sun, 30 Jan 2005 22:31:28 -0800
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
I mentioned this in last email. You need to use libdnet's route lookup 
and ARP cache query routines. Firewalk does exactly this. Below is the 
relevant function from Firewalk-5.0/src/packet_build.c.

int
fw_packet_build_probe(struct firepack **fp)
{
     arp_t *a;
     route_t *r;
     struct arp_entry arp;
     struct route_entry route;

     /* first build our transport layer header */
     switch ((*fp)->protocol)
     {
         case IPPROTO_UDP:
             if (fw_packet_build_udp(fp) == -1)
             {
                 /* error msg set in fw_packet_build_udp() */
                 return (-1);
             }
             break;
         case IPPROTO_TCP:
             if (fw_packet_build_tcp(fp) == -1)
             {
                 /* error msg set in fw_packet_build_tcp() */
                 return (-1);
             }
             break;
         default:
             sprintf((*fp)->errbuf,
                     "fw_packet_build_probe(): unknown protocol");
             return (-1);
     }

     /* build our IPv4 header */
     (*fp)->ip = libnet_build_ipv4(
             (*fp)->packet_size,                 /* packetlength */
             0,                                  /* IP tos */
             (*fp)->id,                          /* IP id */
             0,                                  /* IP frag bits */
             (*fp)->ttl,                         /* IP time to live */
             (*fp)->protocol,                    /* transport protocol */
             0,                                  /* checksum */
             (*fp)->sin.sin_addr.s_addr,         /* IP source */
             (*fp)->metric,                      /* IP destination */
             NULL,                               /* IP payload */
             0,                                  /* IP payload size */
             (*fp)->l,                           /* libnet context */
             0);                                 /* No saved ptag */

     if ((*fp)->ip == -1)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "libnet_build_ipv4() 
%s",
                 libnet_geterror((*fp)->l));
         return (-1);
     }

     /*
      *  Now we need to get the MAC address of our first hop gateway.
      *  Dnet to the rescue!  We start by doing a route table lookup
      *  to determine the IP address we use to get to the
      *  destination host (the metric).
      */
     r = route_open();
     if (r == NULL)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_open()");
         route_close(r);
         return (-1);
     }

     /* convert the metric address to dnet's native addr_t format */
     if (addr_aton(libnet_addr2name4((*fp)->metric, 0),
             &route.route_dst) < 0)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "addr_aton()");
         route_close(r);
         return (-1);
     }
     /* get the route entry telling us how to reach the metric */
     if (route_get(r, &route) < 0)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_get()");
         route_close(r);
         return (-1);
     }
     route_close(r);

     a = arp_open();
     if (a == NULL)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "arp_open()");
         return (-1);
     }
     /* get the MAC of the first hop gateway */
     arp.arp_pa = route.route_gw;
     if (arp_get(a, &arp) < 0)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_get()");
         arp_close(a);
         return (-1);
     }
     arp_close(a);

     /* build our ethernet header */
     if (libnet_autobuild_ethernet(
             (u_char *)&arp.arp_ha.addr_eth,
             ETHERTYPE_IP,
             (*fp)->l) == -1)
     {
         snprintf((*fp)->errbuf, FW_ERRBUF_SIZE,
                 "libnet_autobuild_ethernet() %s",
                 libnet_geterror((*fp)->l));
         arp_close(a);
         return (-1);
     }

     return (1);
}



On Jan 30, 2005, at 8:27 PM, Karen Pease wrote:

> A couple weeks ago, I posted here with problems sending packets via
> LIBNET_LINk when they worked with LIBNET_RAW4.  Last I posted, I 
> thought I
> had resolved the problem by using the libnet_ethernet_autobuild 
> function;
> however, it turns out that it was only working in a situation that I
> previously had working (sending from my home computer to my work 
> computer) (I
> discovered this shortly after I send my last emaiL); I've tried to 
> work on it
> on my own, but have had no success in getting packets to arrive the 
> other
> way.  So, I'm still stuck where I was before.
>
> The main problem is mac addrs.  The libnet example code for raw 
> sockets (which
> I was pointed to before) uses hard coded mac addrs; naturally, as I 
> mentioned
> before, this means that the code is effectively worthless in real-world
> applications, since you don't know beforehand what a target machine's 
> mac
> addr will be.  I can get packets from my home computer to my work 
> computer
> using mac addr ff.ff.ff.ff.ff.ff; however, the same does not work in 
> reverse.
> Assumedly this has something to do with my router (I'm behind NAT with 
> port
> forwarding for the port being sent to).  To send packets from work to 
> home, I
> need to be able to look up the router's mac addr (in fact, if I hard 
> code it,
> they make it home just fine).  I previously asked if there was a libnet
> function to do this for you.  I got no clear response, so I assume the 
> answer
> is "no".
>
> So as not to bother the list any more, I decided to try and look it up 
> myself;
> to the best of my knowlege, this is done with arp who-has requests.  
> So, I
> tried sending who-has requests, and set up this nice system to send 
> them out
> and sniff the results back off the network.  I got no response.  
> Looking in
> tcpdump, only a small percentage of all machines on the network that 
> issued
> who-has requests got them answered - at least, so far as I could see in
> sniffed network traffic.  All of the who-has requests seemed to be 
> structured
> the same (including mine).  So, I'm not sure what I'm missing.
>
> In short, I have to ask: How can I get a remote machine's mac addr to 
> use with
> libnet?  I'm getting somewhat frustrated here.  :(
>
>  - Karen
>
>
--
Mike Schiffman, CISSP
http://www.packetfactory.net/schiffman
Doveryay No Proveryay