Re: Code working with LIBNET_RAW4, not with LIBNET_LINK

Karen Pease <[email protected]> Tue, 1 Feb 2005 15:55:49 -0600
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
On Tuesday 01 February 2005 2:05 am, Manu Garg wrote:
> Karen,
>
> Let me first try to understand your problem. You have an arrangement like
> this: A (local/home m/c) ---->Internet----->B(work m/c) 

A (local/home m/c) ----> router (NAT, with port forwarding) ----> Internet 
----> B (work m/c)

> First thing: It's NOT possible for you to find out hw address of the
> machine at the OTHER side of the router/gateway and it's NOT REQUIRED
> also.

I already understood that  :)  I still need to be able to get the gateway's 
MAC, however, and this is causing problems.

> To make your packet reach machine B,
> you need to first get it to your router and to do that you need your
> router's hw address NOT machine B's. 

Yes; unfortunately, I have been unable to get its hw addr.  When sending to my 
work machine, I can use FF.FF.FF.FF.FF.FF and the packets will get there.  
The same does not hold true in reverse, however.

> Code pointed by Mike does exactly that. The code first reads the
> kernel's routing table to find out the proper route for the
> destination and then it finds out hw address of that router(gateway)
> by arp cache lookup. That's what you need.

As I demonstrated in the previous email, the code provided by Mike fails on 
looking up arbitrary addresses; it only works for the gateway.  In my 
example, I ran it at home and attempted to look up my gateway (192.168.0.1); 
that succeeded.  Then I ran it at home and attempted to look up my work 
computer; it failed.  The output was included in the previous email.

Thanks for your help, Manu.

 - Karen

>
>
> On Tue, 1 Feb 2005 00:34:46 -0600, Karen Pease
>
> <[email protected]> wrote:
> > Just as the libnet code examples only work for hard-coded mac addrs, this
> > code only works for the gateway.  For example, lets try to generalize it
> > (I'll cut out my actual target ip; it's non-local):
> >
> >         struct arp_entry arp;
> > #if 1
> >         int ret=addr_pton("192.168.0.1",&(arp.arp_pa)); //My gateway
> > #else
> >         int ret=addr_pton("AAA.BBB.CCC.DDD",&(arp.arp_pa)); //IP snipped
> > out #endif
> >         printf("IP: %d.%d.%d.%d 
> > (%d)\n",((u_int8_t*)(&arp.arp_pa.addr_eth))
> > [0],((u_int8_t*)(&arp.arp_pa.addr_eth))[1],((u_int8_t*)
> > (&arp.arp_pa.addr_eth))[2],((u_int8_t*)(&arp.arp_pa.addr_eth))[3],ret);
> >
> >         arp_t* a=arp_open();
> >         printf("arp_t: %d\n",a);
> >
> >         ret=arp_get(a,&arp);
> >         printf("%d\n",ret);
> >
> >         arp_close(a);
> >
> >         for (int i=0; i<6; i++)
> >             uc.dest_mac[i]=((u_int8_t*)(&arp.arp_ha.addr_eth))[i];
> >
> >         printf("saddr: %02x.%02x.%02x.%02x.%02x.%02x daddr:
> > %02x.%02x.%02x. %02x.%02x.
> > %02x\n",uc.src_mac[0],uc.src_mac[1],uc.src_mac[2],uc.src_mac[3],uc.src_ma
> >c[4],uc.src_mac[5],uc.dest_mac[0],uc.dest_mac[1],uc.dest_mac[2],uc.dest_ma
> >c[3],uc.dest_mac[4],uc.dest_mac[5]); send(&uc,argv[3]);
> >
> > If we run this code as-is, we get:
> >
> > IP: 192.168.0.1  (0)
> > arp_t: 134564104
> > 0
> > saddr: 00.50.04.6c.e7.30 daddr: 00.20.e0.35.54.40
> >
> > However, if we change the #if 1 to a #if 0, we get:
> >
> > IP: AAA.BBB.CCC.DDD  (0)
> > arp_t: 134564104
> > -1
> > saddr: 00.50.04.6c.e7.30 daddr: 00.00.00.00.00.00
> >
> > As you'll note, arp_get gives an error (by returning -1) and doesn't set
> > the hardware address.
> >
> >  - Karen
> >
> > On Monday 31 January 2005 12:31 am, Mike Schiffman wrote:
> > > 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